64#ifndef ORTOOLS_GRAPH_SHORTEST_PATHS_H_
65#define ORTOOLS_GRAPH_SHORTEST_PATHS_H_
73#include "absl/base/attributes.h"
74#include "absl/container/flat_hash_map.h"
75#include "absl/functional/bind_front.h"
76#include "absl/log/check.h"
77#include "absl/types/span.h"
93 std::numeric_limits<uint32_t>::max();
96template <
class NodeIndex, NodeIndex kNilNode>
97class PathContainerImpl;
113template <
class GraphType>
147 std::vector<NodeIndex>* path)
const;
173 : container_(
std::move(impl)) {}
175 std::unique_ptr<Impl> container_;
179template <
class GraphType>
181 std::vector<typename GraphType::NodeIndex>* nodes) {
182 CHECK(nodes !=
nullptr);
184 nodes->reserve(graph.num_nodes());
185 for (
typename GraphType::NodeIterator iterator(graph); iterator.Ok();
187 nodes->push_back(iterator.Index());
191template <
class GraphType>
193 std::vector<typename GraphType::NodeIndex>* nodes) {
194 CHECK(nodes !=
nullptr);
196 nodes->reserve(graph.num_nodes());
197 for (
const typename GraphType::NodeIndex node : graph.AllNodes()) {
198 nodes->push_back(node);
207template <
class GraphType>
209 const GraphType& graph,
const std::vector<PathDistance>& arc_lengths,
210 typename GraphType::NodeIndex source,
212 std::vector<typename GraphType::NodeIndex> all_nodes;
219template <
class GraphType>
221 const GraphType& graph,
const std::vector<PathDistance>& arc_lengths,
222 typename GraphType::NodeIndex source,
223 const std::vector<typename GraphType::NodeIndex>& destinations,
225 std::vector<typename GraphType::NodeIndex> sources(1, source);
227 graph, arc_lengths, sources, destinations, 1, path_container);
238template <
class GraphType>
240 const GraphType& graph,
const std::vector<PathDistance>& arc_lengths,
241 typename GraphType::NodeIndex source,
242 typename GraphType::NodeIndex destination) {
243 std::vector<typename GraphType::NodeIndex> sources(1, source);
244 std::vector<typename GraphType::NodeIndex> destinations(1, destination);
246 auto path_container =
250 graph, arc_lengths, sources, destinations, 1, &path_container);
252 std::vector<typename GraphType::NodeIndex> path;
253 path_container.GetPath(source, destination, &path);
259template <
class GraphType>
261 const GraphType& graph,
const std::vector<PathDistance>& arc_lengths,
262 const std::vector<typename GraphType::NodeIndex>& sources,
int num_threads,
264 std::vector<typename GraphType::NodeIndex> all_nodes;
267 graph, arc_lengths, sources, all_nodes, num_threads, path_container);
271template <
class GraphType>
273 const GraphType& graph,
const std::vector<PathDistance>& arc_lengths,
275 std::vector<typename GraphType::NodeIndex> all_nodes;
278 graph, arc_lengths, all_nodes, all_nodes, num_threads, path_container);
290template <
class NodeIndex, NodeIndex kNilNode>
291class PathContainerImpl {
300 virtual void Initialize(
const std::vector<NodeIndex>& sources,
301 const std::vector<NodeIndex>& destinations,
327 std::vector<NodeIndex>* path)
const = 0;
337 NodeIndex from,
const std::vector<NodeIndex>& predecessor_in_path_tree,
338 const std::vector<PathDistance>& distance_to_destination) = 0;
352template <
class NodeIndex, NodeIndex kNilNode>
358 absl::Span<const NodeIndex> destinations);
368 std::vector<NodeIndex>* path)
const;
371 std::vector<NodeIndex> nodes_;
372 std::vector<int> parents_;
378template <
class NodeIndex, NodeIndex kNilNode>
380 absl::Span<const NodeIndex> paths,
381 absl::Span<const NodeIndex> destinations) {
382 std::vector<bool> node_explored(paths.size(),
false);
383 const int destination_size = destinations.size();
384 typedef std::pair<NodeIndex, NodeIndex> NodeParent;
385 std::vector<NodeParent> tree;
386 for (
int i = 0; i < destination_size; ++i) {
388 while (!node_explored[destination]) {
389 node_explored[destination] =
true;
390 tree.push_back(std::make_pair(destination, paths[destination]));
391 if (paths[destination] != kNilNode) {
392 destination = paths[destination];
396 std::sort(tree.begin(), tree.end());
397 const int num_nodes = tree.size();
399 absl::flat_hash_map<NodeIndex, int> node_indices;
401 for (
int i = 0; i < num_nodes; ++i) {
402 node_indices[tree[i].first] = i;
404 parents_.resize(num_nodes, -1);
405 for (
int i = 0; i < num_nodes; ++i) {
410 nodes_.resize(num_nodes, kNilNode);
411 for (
int i = 0; i < num_nodes; ++i) {
412 nodes_[i] = tree[i].first;
416template <
class NodeIndex, NodeIndex kNilNode>
418 const auto node_position = absl::c_lower_bound(nodes_, node);
419 if (node_position != nodes_.end() && *node_position == node) {
420 const int parent = parents_[node_position - nodes_.begin()];
421 if (parent != kNilNode) {
422 return nodes_[parent];
428template <
class NodeIndex, NodeIndex kNilNode>
431 DCHECK(path !=
nullptr);
433 const auto to_position = absl::c_lower_bound(nodes_,
to);
434 if (to_position != nodes_.end() && *to_position ==
to) {
435 int current_index = to_position - nodes_.begin();
437 while (current_node != from) {
438 path->push_back(current_node);
439 current_index = parents_[current_index];
441 if (current_index == kNilNode) {
445 current_node = nodes_[current_index];
447 path->push_back(current_node);
448 std::reverse(path->begin(), path->end());
453template <
class NodeIndex, NodeIndex kNilNode>
463 const std::vector<NodeIndex>& destinations,
468 distances_.resize(sources.size());
474 LOG(FATAL) <<
"Path not stored.";
478 LOG(FATAL) <<
"Path not stored.";
483 const std::vector<NodeIndex>&,
484 const std::vector<PathDistance>& distance_to_destination)
override {
493 static void ComputeReverse(absl::Span<const NodeIndex> nodes,
495 std::vector<int>* reverse_nodes) {
496 CHECK(reverse_nodes !=
nullptr);
497 const int kUnassignedIndex = -1;
498 reverse_nodes->clear();
499 reverse_nodes->resize(num_nodes, kUnassignedIndex);
500 for (
int i = 0; i < nodes.size(); ++i) {
501 reverse_nodes->at(nodes[i]) = i;
505 std::vector<std::vector<PathDistance>> distances_;
509template <
class NodeIndex, NodeIndex kNilNode>
510class InMemoryCompactPathContainer
511 :
public DistanceContainer<NodeIndex, kNilNode> {
522 void Initialize(
const std::vector<NodeIndex>& sources,
523 const std::vector<NodeIndex>& destinations,
526 destinations_ = destinations;
528 trees_.resize(sources.size());
535 std::vector<NodeIndex>* path)
const override {
536 DCHECK(path !=
nullptr);
540 NodeIndex from,
const std::vector<NodeIndex>& predecessor_in_path_tree,
541 const std::vector<PathDistance>& distance_to_destination)
override {
543 distance_to_destination);
549 std::vector<PathTree<NodeIndex, kNilNode>> trees_;
550 std::vector<NodeIndex> destinations_;
554template <
class NodeIndex, NodeIndex kNilNode>
562 is_destination_(false) {}
564 return distance_ > other.distance_;
587 bool is_destination_;
593template <
class NodeIndex, NodeIndex kNilNode>
601 "node_entry_class_is_not_well_packed");
603 DCHECK(priority_queue !=
nullptr);
604 DCHECK(entry !=
nullptr);
605 if (!priority_queue->Contains(entry)) {
606 entry->set_distance(distance);
607 priority_queue->Add(entry);
609 }
else if (distance < entry->distance()) {
610 entry->set_distance(distance);
611 priority_queue->NoteChangedPriority(entry);
621template <
class GraphType>
623 const GraphType*
const graph,
624 const std::vector<PathDistance>*
const arc_lengths,
625 typename GraphType::NodeIndex source,
626 const std::vector<typename GraphType::NodeIndex>*
const destinations,
628 using NodeIndex =
typename GraphType::NodeIndex;
629 using ArcIndex =
typename GraphType::ArcIndex;
631 CHECK(graph !=
nullptr);
632 CHECK(arc_lengths !=
nullptr);
633 CHECK(destinations !=
nullptr);
634 CHECK(paths !=
nullptr);
635 const int num_nodes = graph->num_nodes();
636 std::vector<NodeIndex> predecessor(num_nodes, GraphType::kNilNode);
638 std::vector<NodeEntryT> entries(num_nodes);
639 for (
const NodeIndex node : graph->AllNodes()) {
640 entries[node].set_node(node);
644 for (
int i = 0; i < destinations->size(); ++i) {
645 entries[(*destinations)[i]].set_is_destination(
true);
651 for (
const ArcIndex arc : graph->OutgoingArcs(source)) {
655 predecessor[next] = source;
658 int destinations_remaining = destinations->size();
659 while (!priority_queue.
IsEmpty()) {
660 NodeEntryT* current = priority_queue.
Top();
661 const NodeIndex current_node = current->node();
662 priority_queue.
Pop();
663 current->set_settled(
true);
664 if (current->is_destination()) {
665 destinations_remaining--;
666 if (destinations_remaining == 0) {
670 const PathDistance current_distance = current->distance();
671 for (
const ArcIndex arc : graph->OutgoingArcs(current_node)) {
673 NodeEntryT*
const entry = &entries[next];
674 if (!entry->settled()) {
675 DCHECK_GE(current_distance, 0);
680 predecessor[next] = current_node;
685 const int destinations_size = destinations->size();
686 std::vector<PathDistance> distances(destinations_size,
688 for (
int i = 0; i < destinations_size; ++i) {
690 if (entries[node].settled()) {
691 distances[i] = entries[node].distance();
699template <
class GraphType>
702template <
class GraphType>
705 DCHECK(container_ !=
nullptr);
706 return container_->GetDistance(from,
to);
709template <
class GraphType>
713 DCHECK(container_ !=
nullptr);
714 return container_->GetPenultimateNodeInPath(from,
to);
717template <
class GraphType>
720 DCHECK(container_ !=
nullptr);
721 DCHECK(path !=
nullptr);
722 container_->GetPath(from,
to, path);
725template <
class GraphType>
733template <
class GraphType>
741template <
class GraphType>
743 const GraphType& graph,
const std::vector<PathDistance>& arc_lengths,
744 const std::vector<typename GraphType::NodeIndex>& sources,
745 const std::vector<typename GraphType::NodeIndex>& destinations,
747 if (graph.num_nodes() > 0) {
748 CHECK_EQ(graph.num_arcs(), arc_lengths.size())
749 <<
"Number of arcs in graph must match arc length vector size";
752 std::vector<typename GraphType::NodeIndex> unique_sources = sources;
754 std::vector<typename GraphType::NodeIndex> unique_destinations =
760 container->
Initialize(unique_sources, unique_destinations,
763 std::unique_ptr<ThreadPool> pool(
new ThreadPool(num_threads));
764 for (
int i = 0; i < unique_sources.size(); ++i) {
765 pool->Schedule(absl::bind_front(
767 unique_sources[i], &unique_destinations, container));
770 container->Finalize();
771 VLOG(2) <<
"Elapsed time to compute shortest paths: " << timer.
Get() <<
"s";
typename GraphType::NodeIndex NodeIndex
void GetPath(NodeIndex from, NodeIndex to, std::vector< NodeIndex > *path) const
Impl * GetImplementation() const
PathDistance GetDistance(NodeIndex from, NodeIndex to) const
internal::PathContainerImpl< NodeIndex, GraphType::kNilNode > Impl
GenericPathContainer & operator=(const GenericPathContainer &)=delete
NodeIndex GetPenultimateNodeInPath(NodeIndex from, NodeIndex to) const
static GenericPathContainer BuildPathDistanceContainer()
GenericPathContainer(const GenericPathContainer &)=delete
static GenericPathContainer BuildInMemoryCompactPathContainer()
void GetPath(NodeIndex, NodeIndex, std::vector< NodeIndex > *) const override
void Initialize(const std::vector< NodeIndex > &sources, const std::vector< NodeIndex > &destinations, NodeIndex num_nodes) override
NodeIndex GetPenultimateNodeInPath(NodeIndex, NodeIndex) const override
PathDistance GetDistance(NodeIndex from, NodeIndex to) const override
std::vector< int > reverse_sources_
DistanceContainer & operator=(const DistanceContainer &)=delete
std::vector< int > reverse_destinations_
~DistanceContainer() override=default
void StoreSingleSourcePaths(NodeIndex from, const std::vector< NodeIndex > &, const std::vector< PathDistance > &distance_to_destination) override
NodeIndex GetPenultimateNodeInPath(NodeIndex from, NodeIndex to) const override
InMemoryCompactPathContainer & operator=(const InMemoryCompactPathContainer &)=delete
void StoreSingleSourcePaths(NodeIndex from, const std::vector< NodeIndex > &predecessor_in_path_tree, const std::vector< PathDistance > &distance_to_destination) override
void Initialize(const std::vector< NodeIndex > &sources, const std::vector< NodeIndex > &destinations, NodeIndex num_nodes) override
DistanceContainer< NodeIndex, kNilNode > Base
~InMemoryCompactPathContainer() override=default
void GetPath(NodeIndex from, NodeIndex to, std::vector< NodeIndex > *path) const override
InMemoryCompactPathContainer()
PathDistance distance() const
void set_node(NodeIndex node)
bool is_destination() const
void set_is_destination(bool is_destination)
void set_settled(bool settled)
void set_distance(PathDistance distance)
bool operator<(const NodeEntry &other) const
PathContainerImpl()=default
virtual NodeIndex GetPenultimateNodeInPath(NodeIndex from, NodeIndex to) const =0
virtual void Initialize(const std::vector< NodeIndex > &sources, const std::vector< NodeIndex > &destinations, NodeIndex num_nodes)=0
virtual void GetPath(NodeIndex from, NodeIndex to, std::vector< NodeIndex > *path) const =0
virtual ~PathContainerImpl()=default
virtual PathDistance GetDistance(NodeIndex from, NodeIndex to) const =0
virtual void StoreSingleSourcePaths(NodeIndex from, const std::vector< NodeIndex > &predecessor_in_path_tree, const std::vector< PathDistance > &distance_to_destination)=0
NodeIndex GetParent(NodeIndex node) const
void Initialize(absl::Span< const NodeIndex > paths, absl::Span< const NodeIndex > destinations)
void GetPath(NodeIndex from, NodeIndex to, std::vector< NodeIndex > *path) const
void STLSortAndRemoveDuplicates(T *v, const LessFunc &less_func)
const MapUtilMappedT< Collection > & FindWithDefault(const Collection &collection, const KeyType &key, const MapUtilMappedT< Collection > &value)
void ComputeOneToManyOnGraph(const GraphType *const graph, const std::vector< PathDistance > *const arc_lengths, typename GraphType::NodeIndex source, const std::vector< typename GraphType::NodeIndex > *const destinations, typename GenericPathContainer< GraphType >::Impl *const paths)
bool InsertOrUpdateEntry(PathDistance distance, NodeEntry< NodeIndex, kNilNode > *entry, AdjustablePriorityQueue< NodeEntry< NodeIndex, kNilNode > > *priority_queue)
void ComputeOneToManyShortestPaths(const GraphType &graph, const std::vector< PathDistance > &arc_lengths, typename GraphType::NodeIndex source, const std::vector< typename GraphType::NodeIndex > &destinations, GenericPathContainer< GraphType > *const path_container)
void ComputeManyToAllShortestPathsWithMultipleThreads(const GraphType &graph, const std::vector< PathDistance > &arc_lengths, const std::vector< typename GraphType::NodeIndex > &sources, int num_threads, GenericPathContainer< GraphType > *const path_container)
void ComputeAllToAllShortestPathsWithMultipleThreads(const GraphType &graph, const std::vector< PathDistance > &arc_lengths, int num_threads, GenericPathContainer< GraphType > *const path_container)
const PathDistance kDisconnectedPathDistance
std::vector< typename GraphType::NodeIndex > ComputeOneToOneShortestPath(const GraphType &graph, const std::vector< PathDistance > &arc_lengths, typename GraphType::NodeIndex source, typename GraphType::NodeIndex destination)
BlossomGraph::NodeIndex NodeIndex
void ComputeManyToManyShortestPathsWithMultipleThreads(const GraphType &graph, const std::vector< PathDistance > &arc_lengths, const std::vector< typename GraphType::NodeIndex > &sources, const std::vector< typename GraphType::NodeIndex > &destinations, int num_threads, GenericPathContainer< GraphType > *const paths)
void GetGraphNodesFromGraph(const GraphType &graph, std::vector< typename GraphType::NodeIndex > *nodes)
void GetGraphNodes(const GraphType &graph, std::vector< typename GraphType::NodeIndex > *nodes)
void ComputeOneToAllShortestPaths(const GraphType &graph, const std::vector< PathDistance > &arc_lengths, typename GraphType::NodeIndex source, GenericPathContainer< GraphType > *const path_container)
trees with all degrees equal to