Google OR-Tools v9.11
a fast and portable software suite for combinatorial optimization
Loading...
Searching...
No Matches
shortest_paths.h
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
14// This file contains functions to compute shortest paths on Ebert graphs using
15// Dijkstra's algorithm,
16// E.W. Dijkstra, "A note on two problems in connexion with graphs". Numerische
17// Mathematik 1:269–271, 1959. See for example:
18// http://www.springerlink.com/content/uu8608u0u27k7256/fulltext.pdf.
19// More information can also be found on Wikipedia:
20// http://en.wikipedia.org/wiki/Dijkstra's_algorithm
21//
22// This is a unidirectional implementation of Dijkstra's algorithm. A
23// bidirectional is available in bidirectional_dijkstra.h for specific use
24// cases.
25//
26// Each 1-to-many shortest path computation is run in a separate thread. Users
27// should select the number of threads to use according to the number of cores
28// available (each thread will use up one core). However, increasing the number
29// of threads also increases temporary memory used by each 1-to-many
30// computation.
31//
32// Also included are classes to store path data resulting from shortest path
33// computations (cf. PathContainer).
34//
35// Usage example computing all-pair shortest paths on a graph:
36// StaticGraph graph(...,...);
37// std::vector<uint32_t> arc_lengths(...,...);
38// ... populate graph and arc lengths ...
39// PathContainer container;
40// PathContainer::BuildInMemoryCompactPathContainer(&container);
41// ComputeAllToAllShortestPathsWithMultipleThreads(graph,
42// arc_lengths,
43// /*num_threads=*/4,
44// &container);
45//
46// Usage example computing shortest paths between a subset of graph nodes:
47// StaticGraph graph(...,...);
48// std::vector<uint32_t> arc_lengths(...,...);
49// ... populate graph and arc lengths ...
50// vector<NodeIndex> sources;
51// vector<NodeIndex> sinks;
52// ... fill sources and sinks ...
53// PathContainer container;
54// PathContainer::BuildInMemoryCompactPathContainer(&container);
55// ComputeManyToManyShortestPathsWithMultipleThreads(graph,
56// arc_lengths,
57// sources,
58// sinks,
59// /*num_threads=*/4,
60// &container);
61
62#ifndef OR_TOOLS_GRAPH_SHORTEST_PATHS_H_
63#define OR_TOOLS_GRAPH_SHORTEST_PATHS_H_
64
65#include <cstdint>
66#include <limits>
67#include <memory>
68#include <vector>
69
70#include "absl/log/check.h"
73#include "ortools/graph/graph.h"
74
75namespace operations_research {
76
77// Storing distances on 32 bits to limit memory consumption of distance
78// matrices. If distances don't fit on 32 bits, scaling and losing a bit of
79// precision should be acceptable in practice.
80typedef uint32_t PathDistance;
81
83 std::numeric_limits<uint32_t>::max();
84
86
87// Container class storing paths and distances along the paths. It is used in
88// shortest path computation functions to store resulting shortest paths.
89// Usage example iterating on the path between nodes from and to:
90// PathContainer path_container;
91// PathContainer::BuildInMemoryCompactPathContainer(&path_container);
92// ... fill up container ...
93// const NodeIndex from =...;
94// NodeIndex to =...;
95// while (to != from) {
96// LOG(INFO) << to;
97// to = path_container.GetPenultimateNodeInPath(from, to);
98// }
100 public:
102
103 // This type is neither copyable nor movable.
104 PathContainer(const PathContainer&) = delete;
106
108
109 // Returns the distance between node 'from' and node 'to' following the path
110 // out of 'from' and into 'to'. Note that if 'from' == 'to', the distance is
111 // not necessarily 0 if the path out of 'to' and back into 'to' has a distance
112 // greater than 0. If you do require the distance to be 0 in this case, add to
113 // the graph an arc from 'to' to itself with a length of 0.
114 // If nodes are not connected, returns kDisconnectedPathDistance.
116
117 // Returns the penultimate node on the path out of node 'from' into node 'to'
118 // (the direct predecessor of node 'to' on the path).
119 // If 'from' == 'to', the penultimate node is 'to' only if the shortest path
120 // from 'to' to itself is composed of the arc ('to, 'to'), which might not be
121 // the case if either this arc doesn't exist or if the length of this arc is
122 // greater than the distance of an alternate path.
123 // If nodes are not connected, returns StarGraph::kNilNode.
125
126 // Returns path nodes from node "from" to node "to" in a ordered vector.
127 // The vector starts with 'from' and ends with 'to', if both nodes are
128 // connected (otherwise an empty vector is returned).
129 void GetPath(NodeIndex from, NodeIndex to,
130 std::vector<NodeIndex>* path) const;
131
132 // For internal use only. Returns the internal container implementation.
134
135 // Builds a path container which only stores distances between path nodes.
136 static void BuildPathDistanceContainer(PathContainer* path_container);
137
138 // Builds a path container which stores explicit paths and distances between
139 // path nodes in a memory-compact representation.
140 // In this case GetPenultimateNodeInPath() is O(log(path_tree_size)),
141 // path_tree_size being the size of a tree of paths from a source node (in
142 // practice it is equal to the number of nodes in the graph if all nodes
143 // are strongly connected).
144 // GetPath is O(log(path_tree_size) + path_size), where path_size is the
145 // size of the resulting path; note this is faster than successive calls
146 // to GetPenultimateNodeInPath() which would result in
147 // O(log(path_tree_size) * path_size).
148 static void BuildInMemoryCompactPathContainer(PathContainer* path_container);
149
150 // TODO(user): Add save-to-disk container.
151 // TODO(user): Add BuildInMemoryFastPathContainer(), which does
152 // GetPenultimateNodeInPath() in O(1).
153
154 private:
155 std::unique_ptr<PathContainerImpl> container_;
156};
157
158// Utility function which returns a vector containing all nodes of a graph.
159template <class GraphType>
160void GetGraphNodes(const GraphType& graph, std::vector<NodeIndex>* nodes) {
161 CHECK(nodes != nullptr);
162 nodes->clear();
163 nodes->reserve(graph.num_nodes());
164 for (typename GraphType::NodeIterator iterator(graph); iterator.Ok();
165 iterator.Next()) {
166 nodes->push_back(iterator.Index());
167 }
168}
169
170template <class GraphType>
171void GetGraphNodesFromGraph(const GraphType& graph,
172 std::vector<typename GraphType::NodeIndex>* nodes) {
173 CHECK(nodes != nullptr);
174 nodes->clear();
175 nodes->reserve(graph.num_nodes());
176 for (const typename GraphType::NodeIndex node : graph.AllNodes()) {
177 nodes->push_back(node);
178 }
179}
180
181// In all the functions below the arc_lengths vector represents the lengths of
182// the arcs of the graph (arc_lengths[arc] is the length of arc).
183// Resulting shortest paths are stored in a path container 'path_container'.
184
185// Computes shortest paths from the node 'source' to all nodes in the graph.
186template <class GraphType>
188 const std::vector<PathDistance>& arc_lengths,
189 typename GraphType::NodeIndex source,
190 PathContainer* const path_container) {
191 std::vector<typename GraphType::NodeIndex> all_nodes;
194 path_container);
195}
196
197// Computes shortest paths from the node 'source' to nodes in 'destinations'.
198template <class GraphType>
200 const GraphType& graph, const std::vector<PathDistance>& arc_lengths,
201 typename GraphType::NodeIndex source,
202 const std::vector<typename GraphType::NodeIndex>& destinations,
203 PathContainer* const path_container) {
204 std::vector<typename GraphType::NodeIndex> sources(1, source);
206 graph, arc_lengths, sources, destinations, 1, path_container);
207}
208
209// Computes the shortest path from the node 'source' to the node 'destination'
210// and returns that path as a vector of nodes. If there is no path from 'source'
211// to 'destination', the returned vector is empty.
212//
213// To get distance information, use ComputeOneToManyShortestPaths with a single
214// destination and a `PathContainer` built with `BuildPathDistanceContainer` (if
215// you just need the distance) or `BuildInMemoryCompactPathContainer`
216// (otherwise).
217template <class GraphType>
218std::vector<typename GraphType::NodeIndex> ComputeOneToOneShortestPath(
219 const GraphType& graph, const std::vector<PathDistance>& arc_lengths,
220 typename GraphType::NodeIndex source,
221 typename GraphType::NodeIndex destination) {
222 std::vector<typename GraphType::NodeIndex> sources(1, source);
223 std::vector<typename GraphType::NodeIndex> destinations(1, destination);
224
225 PathContainer path_container;
227
229 graph, arc_lengths, sources, destinations, 1, &path_container);
230
231 std::vector<typename GraphType::NodeIndex> path;
232 path_container.GetPath(source, destination, &path);
233 return path;
234}
235
236// Computes shortest paths from the nodes in 'sources' to all nodes in the
237// graph.
238template <class GraphType>
240 const GraphType& graph, const std::vector<PathDistance>& arc_lengths,
241 const std::vector<typename GraphType::NodeIndex>& sources, int num_threads,
242 PathContainer* const path_container) {
243 std::vector<typename GraphType::NodeIndex> all_nodes;
246 graph, arc_lengths, sources, all_nodes, num_threads, path_container);
247}
248
249// Computes shortest paths from the nodes in 'sources' to the nodes in
250// 'destinations'.
251template <class GraphType>
253 const GraphType& graph, const std::vector<PathDistance>& arc_lengths,
254 const std::vector<typename GraphType::NodeIndex>& sources,
255 const std::vector<typename GraphType::NodeIndex>& destinations,
256 int num_threads, PathContainer* const path_container) {
257 (void)graph;
258 (void)arc_lengths;
259 (void)sources;
260 (void)destinations;
261 (void)num_threads;
262 (void)path_container;
263
264 LOG(DFATAL) << "Graph type not supported";
265}
266
267// Specialization for supported graph classes.
268
269using ::util::ListGraph;
270template <>
272 const ListGraph<>& graph, const std::vector<PathDistance>& arc_lengths,
273 const std::vector<ListGraph<>::NodeIndex>& sources,
274 const std::vector<ListGraph<>::NodeIndex>& destinations, int num_threads,
275 PathContainer* path_container);
276
277using ::util::StaticGraph;
278template <>
280 const StaticGraph<>& graph, const std::vector<PathDistance>& arc_lengths,
281 const std::vector<StaticGraph<>::NodeIndex>& sources,
282 const std::vector<StaticGraph<>::NodeIndex>& destinations, int num_threads,
283 PathContainer* path_container);
284
285using ::util::ReverseArcListGraph;
286template <>
288 const ReverseArcListGraph<>& graph,
289 const std::vector<PathDistance>& arc_lengths,
290 const std::vector<ReverseArcListGraph<>::NodeIndex>& sources,
291 const std::vector<ReverseArcListGraph<>::NodeIndex>& destinations,
292 int num_threads, PathContainer* path_container);
293
294using ::util::ReverseArcStaticGraph;
295template <>
297 const ReverseArcStaticGraph<>& graph,
298 const std::vector<PathDistance>& arc_lengths,
299 const std::vector<ReverseArcStaticGraph<>::NodeIndex>& sources,
300 const std::vector<ReverseArcStaticGraph<>::NodeIndex>& destinations,
301 int num_threads, PathContainer* path_container);
302
303using ::util::ReverseArcMixedGraph;
304template <>
306 const ReverseArcMixedGraph<>& graph,
307 const std::vector<PathDistance>& arc_lengths,
308 const std::vector<ReverseArcMixedGraph<>::NodeIndex>& sources,
309 const std::vector<ReverseArcMixedGraph<>::NodeIndex>& destinations,
310 int num_threads, PathContainer* path_container);
311
312// Computes shortest paths between all nodes of the graph.
313template <class GraphType>
315 const GraphType& graph, const std::vector<PathDistance>& arc_lengths,
316 int num_threads, PathContainer* const path_container) {
317 std::vector<typename GraphType::NodeIndex> all_nodes;
320 graph, arc_lengths, all_nodes, all_nodes, num_threads, path_container);
321}
322
323} // namespace operations_research
324
325#endif // OR_TOOLS_GRAPH_SHORTEST_PATHS_H_
static void BuildInMemoryCompactPathContainer(PathContainer *path_container)
PathContainer & operator=(const PathContainer &)=delete
NodeIndex GetPenultimateNodeInPath(NodeIndex from, NodeIndex to) const
PathContainer(const PathContainer &)=delete
This type is neither copyable nor movable.
void GetPath(NodeIndex from, NodeIndex to, std::vector< NodeIndex > *path) const
PathDistance GetDistance(NodeIndex from, NodeIndex to) const
static void BuildPathDistanceContainer(PathContainer *path_container)
Builds a path container which only stores distances between path nodes.
PathContainerImpl * GetImplementation() const
For internal use only. Returns the internal container implementation.
std::vector< double > arc_lengths
GraphType graph
In SWIG mode, we don't want anything besides these top-level includes.
const PathDistance kDisconnectedPathDistance
void GetGraphNodes(const GraphType &graph, std::vector< NodeIndex > *nodes)
Utility function which returns a vector containing all nodes of a graph.
void ComputeOneToAllShortestPaths(const GraphType &graph, const std::vector< PathDistance > &arc_lengths, typename GraphType::NodeIndex source, PathContainer *const path_container)
Computes shortest paths from the node 'source' to all nodes in the graph.
void ComputeAllToAllShortestPathsWithMultipleThreads(const GraphType &graph, const std::vector< PathDistance > &arc_lengths, int num_threads, PathContainer *const path_container)
Computes shortest paths between all nodes of the graph.
std::vector< typename GraphType::NodeIndex > ComputeOneToOneShortestPath(const GraphType &graph, const std::vector< PathDistance > &arc_lengths, typename GraphType::NodeIndex source, typename GraphType::NodeIndex destination)
void ComputeOneToManyShortestPaths(const GraphType &graph, const std::vector< PathDistance > &arc_lengths, typename GraphType::NodeIndex source, const std::vector< typename GraphType::NodeIndex > &destinations, PathContainer *const path_container)
Computes shortest paths from the node 'source' to nodes in 'destinations'.
void ComputeManyToAllShortestPathsWithMultipleThreads(const GraphType &graph, const std::vector< PathDistance > &arc_lengths, const std::vector< typename GraphType::NodeIndex > &sources, int num_threads, PathContainer *const path_container)
void GetGraphNodesFromGraph(const GraphType &graph, std::vector< typename GraphType::NodeIndex > *nodes)
void ComputeManyToManyShortestPathsWithMultipleThreads(const ListGraph<> &graph, const std::vector< PathDistance > &arc_lengths, const std::vector< ListGraph<>::NodeIndex > &sources, const std::vector< ListGraph<>::NodeIndex > &destinations, int num_threads, PathContainer *const path_container)
trees with all degrees equal to
int nodes