20#include "absl/log/check.h"
21#include "absl/types/span.h"
29using GraphType = util::StaticGraph<>;
33struct ShortestPathOnDagProblem {
35 std::vector<double> arc_lengths;
36 std::vector<ArcIndex> original_arc_indices;
37 std::vector<NodeIndex> topological_order;
40ShortestPathOnDagProblem ReadProblem(
41 const int num_nodes, absl::Span<const ArcWithLength> arcs_with_length) {
42 GraphType graph(num_nodes, arcs_with_length.size());
43 std::vector<double> arc_lengths;
44 arc_lengths.reserve(arcs_with_length.size());
45 for (
const auto& arc : arcs_with_length) {
46 graph.AddArc(arc.from, arc.to);
47 arc_lengths.push_back(arc.length);
49 std::vector<ArcIndex> permutation;
50 graph.Build(&permutation);
53 std::vector<ArcIndex> original_arc_indices(permutation.size());
54 if (!permutation.empty()) {
55 for (
ArcIndex i = 0;
i < permutation.size(); ++
i) {
56 original_arc_indices[permutation[
i]] =
i;
60 absl::StatusOr<std::vector<NodeIndex>> topological_order =
62 CHECK_OK(topological_order) <<
"arcs_with_length form a cycle.";
64 return ShortestPathOnDagProblem{
65 .graph = std::move(graph),
66 .arc_lengths = std::move(arc_lengths),
67 .original_arc_indices = std::move(original_arc_indices),
68 .topological_order = std::move(topological_order).value()};
71void GetOriginalArcPath(absl::Span<const ArcIndex> original_arc_indices,
72 std::vector<ArcIndex>& arc_path) {
73 if (original_arc_indices.empty()) {
76 for (
int i = 0;
i < arc_path.size(); ++
i) {
77 arc_path[
i] = original_arc_indices[arc_path[
i]];
84 const int num_nodes, absl::Span<const ArcWithLength> arcs_with_length,
85 const int source,
const int destination) {
86 const ShortestPathOnDagProblem problem =
87 ReadProblem(num_nodes, arcs_with_length);
90 &problem.graph, &problem.arc_lengths, problem.topological_order);
93 if (!shortest_path_on_dag.
IsReachable(destination)) {
94 return PathWithLength{.length = std::numeric_limits<double>::infinity()};
97 std::vector<int> arc_path = shortest_path_on_dag.
ArcPathTo(destination);
98 GetOriginalArcPath(problem.original_arc_indices, arc_path);
100 .length = shortest_path_on_dag.
LengthTo(destination),
101 .arc_path = std::move(arc_path),
102 .node_path = shortest_path_on_dag.
NodePathTo(destination)};
106 const int num_nodes, absl::Span<const ArcWithLength> arcs_with_length,
107 const int source,
const int destination,
const int path_count) {
108 const ShortestPathOnDagProblem problem =
109 ReadProblem(num_nodes, arcs_with_length);
112 &problem.graph, &problem.arc_lengths, problem.topological_order,
116 if (!shortest_paths_on_dag.
IsReachable(destination)) {
117 return {
PathWithLength{.length = std::numeric_limits<double>::infinity()}};
120 std::vector<double> lengths = shortest_paths_on_dag.
LengthsTo(destination);
121 std::vector<std::vector<GraphType::ArcIndex>> arc_paths =
122 shortest_paths_on_dag.
ArcPathsTo(destination);
123 std::vector<std::vector<GraphType::NodeIndex>> node_paths =
125 std::vector<PathWithLength> paths;
126 paths.reserve(lengths.size());
127 for (
int k = 0; k < lengths.size(); ++k) {
128 GetOriginalArcPath(problem.original_arc_indices, arc_paths[k]);
130 .arc_path = std::move(arc_paths[k]),
131 .node_path = std::move(node_paths[k])});
bool IsReachable(NodeIndex node) const
void RunKShortestPathOnDag(absl::Span< const NodeIndex > sources)
std::vector< std::vector< ArcIndex > > ArcPathsTo(NodeIndex node) const
std::vector< std::vector< NodeIndex > > NodePathsTo(NodeIndex node) const
std::vector< double > LengthsTo(NodeIndex node) const
double LengthTo(NodeIndex node) const
Returns the length of the shortest path from node's source to node.
bool IsReachable(NodeIndex node) const
std::vector< ArcIndex > ArcPathTo(NodeIndex node) const
void RunShortestPathOnDag(absl::Span< const NodeIndex > sources)
std::vector< NodeIndex > NodePathTo(NodeIndex node) const
In SWIG mode, we don't want anything besides these top-level includes.
std::vector< PathWithLength > KShortestPathsOnDag(const int num_nodes, absl::Span< const ArcWithLength > arcs_with_length, const int source, const int destination, const int path_count)
PathWithLength ShortestPathsOnDag(const int num_nodes, absl::Span< const ArcWithLength > arcs_with_length, const int source, const int destination)
absl::StatusOr< std::vector< int > > FastTopologicalSort(const AdjacencyLists &adj)
void Permute(const IntVector &permutation, Array *array_to_permute)