Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
routing_index_manager.cc
Go to the documentation of this file.
1// Copyright 2010-2024 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 "absl/log/check.h"
24
25namespace operations_research {
26
27const int64_t RoutingIndexManager::kUnassigned = -1;
28
29RoutingIndexManager::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
35RoutingIndexManager::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
53void 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
138std::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
IntegerValue size
std::vector< NodeIndex > IndicesToNodes(const std::vector< int64_t > &indices) const
Same as IndexToNode but for a given vector of indices.
RoutingIndexManager(int num_nodes, int num_vehicles, NodeIndex depot)
int num_nodes() const
Returns the number of nodes in the manager.
int num_vehicles() const
Returns the number of vehicles in the manager.
std::vector< int64_t > NodesToIndices(const std::vector< NodeIndex > &nodes) const
Same as NodeToIndex but for a given vector of nodes.
NodeIndex IndexToNode(int64_t index) const
void resize(size_type new_size)
int index
In SWIG mode, we don't want anything besides these top-level includes.
STL namespace.
int nodes
std::optional< int64_t > end
int64_t start