OR-Tools  9.6
routing_index_manager.cc
Go to the documentation of this file.
1 // Copyright 2010-2022 Google LLC
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 // http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
15 
16 #include <cstdint>
17 #include <memory>
18 #include <utility>
19 #include <vector>
20 
21 #include "absl/container/flat_hash_set.h"
22 #include "ortools/base/logging.h"
23 #include "ortools/base/map_util.h"
24 
25 namespace operations_research {
26 
27 const int64_t RoutingIndexManager::kUnassigned = -1;
28 
29 RoutingIndexManager::RoutingIndexManager(int num_nodes, int num_vehicles,
30  NodeIndex depot)
31  : RoutingIndexManager(num_nodes, num_vehicles,
32  std::vector<std::pair<NodeIndex, NodeIndex>>(
33  num_vehicles, {depot, depot})) {}
34 
35 RoutingIndexManager::RoutingIndexManager(int num_nodes, int num_vehicles,
36  const std::vector<NodeIndex>& starts,
37  const std::vector<NodeIndex>& ends) {
38  CHECK_EQ(starts.size(), num_vehicles);
39  CHECK_EQ(ends.size(), num_vehicles);
40  std::vector<std::pair<NodeIndex, NodeIndex>> starts_ends(num_vehicles);
41  for (int v = 0; v < num_vehicles; ++v) {
42  starts_ends[v] = {starts[v], ends[v]};
43  }
44  Initialize(num_nodes, num_vehicles, starts_ends);
45 }
46 
48  int num_nodes, int num_vehicles,
49  const std::vector<std::pair<NodeIndex, NodeIndex>>& starts_ends) {
50  Initialize(num_nodes, num_vehicles, starts_ends);
51 }
52 
53 void RoutingIndexManager::Initialize(
54  int num_nodes, int num_vehicles,
55  const std::vector<std::pair<NodeIndex, NodeIndex>>& starts_ends) {
56  static const NodeIndex kZeroNode(0);
57 
58  num_nodes_ = num_nodes;
59  num_vehicles_ = num_vehicles;
60  CHECK_EQ(num_vehicles_, starts_ends.size());
61  absl::flat_hash_set<NodeIndex> starts;
62  absl::flat_hash_set<NodeIndex> ends;
63  absl::flat_hash_set<NodeIndex> unique_depots;
64  for (const std::pair<NodeIndex, NodeIndex>& start_end : starts_ends) {
65  const NodeIndex start = start_end.first;
66  const NodeIndex end = start_end.second;
67  CHECK_GE(start, 0);
68  CHECK_GE(end, 0);
69  CHECK_LE(start, num_nodes_);
70  CHECK_LE(end, num_nodes_);
71  starts.insert(start);
72  ends.insert(end);
73  unique_depots.insert(start);
74  unique_depots.insert(end);
75  }
76  num_unique_depots_ = unique_depots.size();
77  const int size = num_nodes_ + num_vehicles_ - num_unique_depots_;
78 
79  index_to_node_.resize(size + num_vehicles_);
80  node_to_index_.resize(num_nodes_, kUnassigned);
81  vehicle_to_start_.resize(num_vehicles_);
82  vehicle_to_end_.resize(num_vehicles_);
83  int64_t index = 0;
84  for (NodeIndex i = kZeroNode; i < num_nodes_; ++i) {
85  if (starts.contains(i) || !ends.contains(i)) {
86  index_to_node_[index] = i;
87  node_to_index_[i] = index;
88  ++index;
89  }
90  }
91  absl::flat_hash_set<NodeIndex> seen_starts;
92  for (int i = 0; i < num_vehicles_; ++i) {
93  const NodeIndex start = starts_ends[i].first;
94  if (!seen_starts.contains(start)) {
95  seen_starts.insert(start);
96  const int64_t start_index = node_to_index_[start];
97  vehicle_to_start_[i] = start_index;
98  CHECK_NE(kUnassigned, start_index);
99  } else {
100  vehicle_to_start_[i] = index;
101  index_to_node_[index] = start;
102  ++index;
103  }
104  }
105  for (int i = 0; i < num_vehicles_; ++i) {
106  NodeIndex end = starts_ends[i].second;
107  index_to_node_[index] = end;
108  vehicle_to_end_[i] = index;
109  CHECK_LE(size, index);
110  ++index;
111  }
112 
113  // Logging model information.
114  VLOG(1) << "Number of nodes: " << num_nodes_;
115  VLOG(1) << "Number of vehicles: " << num_vehicles_;
116  for (int64_t index = 0; index < index_to_node_.size(); ++index) {
117  VLOG(2) << "Variable index " << index << " -> Node index "
118  << index_to_node_[index];
119  }
120  for (NodeIndex node = kZeroNode; node < node_to_index_.size(); ++node) {
121  VLOG(2) << "Node index " << node << " -> Variable index "
122  << node_to_index_[node];
123  }
124 }
125 
127  const std::vector<NodeIndex>& nodes) const {
128  std::vector<int64_t> indices;
129  indices.reserve(nodes.size());
130  for (const NodeIndex node : nodes) {
131  const int64_t index = NodeToIndex(node);
132  CHECK_NE(kUnassigned, index);
133  indices.push_back(index);
134  }
135  return indices;
136 }
137 
138 std::vector<RoutingIndexManager::NodeIndex> RoutingIndexManager::IndicesToNodes(
139  const std::vector<int64_t>& indices) const {
140  std::vector<NodeIndex> nodes;
141  nodes.reserve(indices.size());
142  for (const int64_t index : indices) {
143  nodes.push_back(IndexToNode(index));
144  }
145  return nodes;
146 }
147 
148 } // namespace operations_research
void resize(size_type new_size)
size_type size() const
Manager for any NodeIndex <-> variable index conversion.
std::vector< NodeIndex > IndicesToNodes(const std::vector< int64_t > &indices) const
std::vector< int64_t > NodesToIndices(const std::vector< NodeIndex > &nodes) const
RoutingIndexManager(int num_nodes, int num_vehicles, NodeIndex depot)
Creates a NodeIndex to variable index mapping for a problem containing 'num_nodes',...
NodeIndex IndexToNode(int64_t index) const
int64_t NodeToIndex(NodeIndex node) const
int index
Collection of objects used to extend the Constraint Solver library.
int nodes
std::optional< int64_t > end
int64_t start
#define VLOG(verboselevel)
Definition: vlog.h:39