11#include <boost/graph/dijkstra_shortest_paths.hpp>
12#include <boost/graph/bellman_ford_shortest_paths.hpp>
13#include <boost/graph/dag_shortest_paths.hpp>
14#include <boost/graph/floyd_warshall_shortest.hpp>
39template <
typename NodeID,
typename Distance =
double>
48 const auto it =
distance.find(target);
49 return it !=
distance.end() && it->second != std::numeric_limits<Distance>::max();
60 std::vector<NodeID>
path_to(
const NodeID& target)
const {
61 const auto distance_it =
distance.find(target);
63 throw std::runtime_error(
"Path reconstruction failed: target node not found in result.");
65 if (distance_it->second == std::numeric_limits<Distance>::max()) {
66 throw std::runtime_error(
"Path reconstruction failed: target node is unreachable.");
69 std::vector<NodeID> path;
70 NodeID current = target;
75 path.push_back(current);
79 throw std::runtime_error(
"Path reconstruction failed: predecessor map is incomplete.");
81 if (pred_it->second == current) {
85 current = pred_it->second;
87 if (hops > max_hops) {
88 throw std::runtime_error(
"Path reconstruction failed: predecessor cycle detected.");
92 std::reverse(path.begin(), path.end());
97template <
typename Distance>
98Distance normalize_weighted_distance(Distance value) {
99 if constexpr (std::is_integral_v<Distance> && std::is_signed_v<Distance>) {
100 if (value == std::numeric_limits<Distance>::lowest()) {
101 return std::numeric_limits<Distance>::max();
107template <
typename Distance>
108using shortest_path_calc_type = std::conditional_t<std::is_integral_v<Distance>, double, Distance>;
110template <
typename Distance,
typename CalcDistance>
111Distance convert_shortest_path_distance(CalcDistance value) {
112 if constexpr (std::is_same_v<CalcDistance, Distance>) {
113 return normalize_weighted_distance(value);
115 if constexpr (std::is_integral_v<Distance> && std::is_floating_point_v<CalcDistance>) {
116 if (!std::isfinite(value) || value >=
static_cast<CalcDistance
>(std::numeric_limits<Distance>::max())) {
117 return std::numeric_limits<Distance>::max();
119 if (value <=
static_cast<CalcDistance
>(std::numeric_limits<Distance>::lowest())) {
120 return std::numeric_limits<Distance>::lowest();
123 if (value == std::numeric_limits<CalcDistance>::max()) {
124 return std::numeric_limits<Distance>::max();
126 return static_cast<Distance
>(value);
132template <
typename GraphWrapper>
141[[deprecated(
"Use G.shortest_path(source, target) instead.")]]
142auto shortest_path(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id) {
143 return G.shortest_path(source_id, target_id);
146template <
typename GraphWrapper>
147requires(GraphWrapper::has_builtin_edge_weight)
156[[deprecated(
"Use G.dijkstra_path(source, target) instead.")]]
157auto dijkstra_path(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id) {
158 return G.dijkstra_path(source_id, target_id);
161template <
typename GraphWrapper>
162requires(GraphWrapper::has_builtin_edge_weight)
171[[deprecated(
"Use G.dijkstra_shortest_paths(source) instead.")]]
172auto dijkstra_shortest_paths(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id) {
173 return G.dijkstra_shortest_paths(source_id);
176template <
typename GraphWrapper>
177requires(GraphWrapper::has_builtin_edge_weight)
186[[deprecated(
"Use G.dijkstra_shortest_paths(source) instead.")]]
187auto single_source_dijkstra(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id) {
188 return G.dijkstra_shortest_paths(source_id);
191template <
typename GraphWrapper>
201[[deprecated(
"Use G.shortest_path(source, target, weight) instead.")]]
202auto shortest_path(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id,
const std::string& weight) {
203 return G.shortest_path(source_id, target_id, weight);
206template <
typename GraphWrapper>
207requires(GraphWrapper::has_builtin_edge_weight)
217[[deprecated(
"Use G.dijkstra_path(source, target, weight) instead.")]]
218auto dijkstra_path(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id,
const std::string& weight) {
219 return G.dijkstra_path(source_id, target_id, weight);
222template <
typename GraphWrapper>
231[[deprecated(
"Use G.shortest_path_length(source, target) instead.")]]
232double shortest_path_length(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id) {
233 return G.shortest_path_length(source_id, target_id);
236template <
typename GraphWrapper>
246[[deprecated(
"Use G.shortest_path_length(source, target, weight) instead.")]]
247double shortest_path_length(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id,
const std::string& weight) {
248 return G.shortest_path_length(source_id, target_id, weight);
251template <
typename GraphWrapper>
252requires(GraphWrapper::has_builtin_edge_weight)
260[[deprecated(
"Use G.dijkstra_path_length(source) instead.")]]
261auto dijkstra_path_length(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id) {
262 return G.dijkstra_path_length(source_id);
265template <
typename GraphWrapper>
266requires(GraphWrapper::has_builtin_edge_weight)
276[[deprecated(
"Use G.dijkstra_path_length(source, target) instead.")]]
277auto dijkstra_path_length(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id) {
278 return G.dijkstra_path_length(source_id, target_id);
281template <
typename GraphWrapper>
282requires(GraphWrapper::has_builtin_edge_weight)
293[[deprecated(
"Use G.dijkstra_path_length(source, target, weight) instead.")]]
294auto dijkstra_path_length(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id,
const std::string& weight) {
295 return G.dijkstra_path_length(source_id, target_id, weight);
299template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
301 if (id_to_bgl.find(source_id) == id_to_bgl.end() || id_to_bgl.find(target_id) == id_to_bgl.end()) {
302 throw std::runtime_error(
"Shortest-path lookup failed: source or target node not found.");
305 const VertexDesc source = id_to_bgl.at(source_id);
306 const VertexDesc target = id_to_bgl.at(target_id);
308 if (source == target) {
309 return std::vector<NodeID>{source_id};
312 const size_t n = boost::num_vertices(g);
313 const auto source_index = get_vertex_index(source);
314 const auto target_index = get_vertex_index(target);
315 std::vector<bool> visited(n,
false);
316 std::vector<VertexDesc> pred(n);
317 std::queue<VertexDesc> q;
319 for (
auto [v, vend] = boost::vertices(g); v != vend; ++v) {
320 pred[get_vertex_index(*v)] = *v;
323 visited[source_index] =
true;
327 const VertexDesc current = q.front();
330 for (
auto [e, eend] = boost::out_edges(current, g); e != eend; ++e) {
331 const VertexDesc next = boost::target(*e, g);
332 const auto next_index = get_vertex_index(next);
333 if (!visited[next_index]) {
334 visited[next_index] =
true;
335 pred[next_index] = current;
336 if (next == target) {
345 if (!visited[target_index]) {
346 throw std::runtime_error(
"Shortest-path lookup failed: target node is unreachable.");
349 std::vector<NodeID> path;
350 for (VertexDesc curr = target; curr != source; curr = pred[get_vertex_index(curr)]) {
351 path.push_back(get_node_id(curr));
353 path.push_back(get_node_id(source));
354 std::reverse(path.begin(), path.end());
358template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
360 if (weight.empty()) {
363 if (weight ==
"weight") {
364 if constexpr (Weighted) {
365 return dijkstra_path(source_id, target_id);
367 throw std::runtime_error(
"Weight lookup failed: only the built-in edge weight property named 'weight' is supported.");
370 throw std::runtime_error(
"Weight lookup failed: only the built-in edge weight property named 'weight' is supported.");
373template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
377 throw std::runtime_error(
"Shortest-path lookup failed: target node is unreachable.");
379 return static_cast<double>(path.size() - 1);
382template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
384 if (weight.empty()) {
387 if (weight ==
"weight") {
388 if constexpr (Weighted) {
389 return dijkstra_path_length(source_id, target_id);
391 throw std::runtime_error(
"Weight lookup failed: only the built-in edge weight property named 'weight' is supported.");
394 throw std::runtime_error(
"Weight lookup failed: only the built-in edge weight property named 'weight' is supported.");
397template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
401 if (id_to_bgl.find(source_id) == id_to_bgl.end() || id_to_bgl.find(target_id) == id_to_bgl.end()) {
402 throw std::runtime_error(
"Shortest-path lookup failed: source or target node not found.");
405 const VertexDesc source = id_to_bgl.at(source_id);
406 const VertexDesc target = id_to_bgl.at(target_id);
407 const size_t n = boost::num_vertices(g);
408 const auto target_index = get_vertex_index(target);
409 std::vector<EdgeWeight> dist(n);
410 std::vector<VertexDesc> pred(n);
412 boost::dijkstra_shortest_paths(
415 boost::distance_map(boost::make_iterator_property_map(dist.begin(), vertex_index_map))
416 .predecessor_map(boost::make_iterator_property_map(pred.begin(), vertex_index_map))
417 .vertex_index_map(vertex_index_map)
420 if (pred[target_index] == target && source != target) {
421 throw std::runtime_error(
"Shortest-path lookup failed: target node is unreachable.");
424 std::vector<NodeID> path;
425 for (VertexDesc curr = target; curr != source; curr = pred[get_vertex_index(curr)]) {
426 path.push_back(get_node_id(curr));
428 path.push_back(get_node_id(source));
429 std::reverse(path.begin(), path.end());
433template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
437 if (weight.empty() || weight ==
"weight") {
438 return dijkstra_path(source_id, target_id);
440 throw std::runtime_error(
"Weight lookup failed: only the built-in edge weight property named 'weight' is supported.");
443template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
447 if (id_to_bgl.find(source_id) == id_to_bgl.end()) {
448 throw std::runtime_error(
"Shortest-path lookup failed: source node not found.");
451 const VertexDesc source = id_to_bgl.at(source_id);
452 const size_t n = boost::num_vertices(g);
453 std::vector<EdgeWeight> dist(n, std::numeric_limits<EdgeWeight>::max());
454 std::vector<VertexDesc> pred(n);
455 for (
auto [v, vend] = boost::vertices(g); v != vend; ++v) {
456 pred[get_vertex_index(*v)] = *v;
459 boost::dijkstra_shortest_paths(
462 boost::distance_map(boost::make_iterator_property_map(dist.begin(), vertex_index_map))
463 .predecessor_map(boost::make_iterator_property_map(pred.begin(), vertex_index_map))
464 .vertex_index_map(vertex_index_map)
468 for (
auto [v, vend] = boost::vertices(g); v != vend; ++v) {
469 const auto index = get_vertex_index(*v);
470 const auto&
id = get_node_id(*v);
477template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
481 return dijkstra_shortest_paths(source_id).distance;
484template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
488 const auto distances = dijkstra_path_length(source_id);
489 const auto it = distances.find(target_id);
490 if (it == distances.end()) {
491 throw std::runtime_error(
"Shortest-path lookup failed: target node not found.");
496template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
500 if (weight.empty() || weight ==
"weight") {
501 return dijkstra_path_length(source_id, target_id);
503 throw std::runtime_error(
"Weight lookup failed: only the built-in edge weight property named 'weight' is supported.");
506template <
typename GraphWrapper>
507requires(GraphWrapper::has_builtin_edge_weight)
516[[deprecated(
"Use G.bellman_ford_path(source, target) instead.")]]
517auto bellman_ford_path(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id) {
518 return G.bellman_ford_path(source_id, target_id);
521template <
typename GraphWrapper>
522requires(GraphWrapper::has_builtin_edge_weight)
531[[deprecated(
"Use G.bellman_ford_shortest_paths(source) instead.")]]
532auto bellman_ford_shortest_paths(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id) {
533 return G.bellman_ford_shortest_paths(source_id);
536template <
typename GraphWrapper>
537requires(GraphWrapper::has_builtin_edge_weight)
546[[deprecated(
"Use G.bellman_ford_shortest_paths(source) instead.")]]
547auto single_source_bellman_ford(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id) {
548 return G.bellman_ford_shortest_paths(source_id);
551template <
typename GraphWrapper>
552requires(GraphWrapper::has_builtin_edge_weight)
562[[deprecated(
"Use G.bellman_ford_path(source, target, weight) instead.")]]
563auto bellman_ford_path(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id,
const std::string& weight) {
564 return G.bellman_ford_path(source_id, target_id, weight);
567template <
typename GraphWrapper>
568requires(GraphWrapper::has_builtin_edge_weight)
578[[deprecated(
"Use G.bellman_ford_path_length(source, target) instead.")]]
579auto bellman_ford_path_length(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id) {
580 return G.bellman_ford_path_length(source_id, target_id);
583template <
typename GraphWrapper>
584requires(GraphWrapper::has_builtin_edge_weight)
595[[deprecated(
"Use G.bellman_ford_path_length(source, target, weight) instead.")]]
596auto bellman_ford_path_length(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id,
const typename GraphWrapper::NodeType& target_id,
const std::string& weight) {
597 return G.bellman_ford_path_length(source_id, target_id, weight);
600template <
typename GraphWrapper>
601requires(GraphWrapper::has_builtin_edge_weight)
610[[deprecated(
"Use G.dag_shortest_paths(source) instead.")]]
611auto dag_shortest_paths(
const GraphWrapper& G,
const typename GraphWrapper::NodeType& source_id) {
612 return G.dag_shortest_paths(source_id);
615template <
typename GraphWrapper>
616requires(GraphWrapper::has_builtin_edge_weight)
624[[deprecated(
"Use G.floyd_warshall_all_pairs_shortest_paths() instead.")]]
625auto floyd_warshall_all_pairs_shortest_paths(
const GraphWrapper& G) {
626 return G.floyd_warshall_all_pairs_shortest_paths();
629template <
typename GraphWrapper>
630requires(GraphWrapper::has_builtin_edge_weight)
638[[deprecated(
"Use G.floyd_warshall_all_pairs_shortest_paths_map() instead.")]]
639auto floyd_warshall_all_pairs_shortest_paths_map(
const GraphWrapper& G) {
640 return G.floyd_warshall_all_pairs_shortest_paths_map();
644template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
648 if (id_to_bgl.find(source_id) == id_to_bgl.end() || id_to_bgl.find(target_id) == id_to_bgl.end()) {
649 throw std::runtime_error(
"Shortest-path lookup failed: source or target node not found.");
652 const VertexDesc source = id_to_bgl.at(source_id);
653 const VertexDesc target = id_to_bgl.at(target_id);
654 const size_t n = boost::num_vertices(g);
655 const auto source_index = get_vertex_index(source);
656 const auto target_index = get_vertex_index(target);
657 std::vector<EdgeWeight> dist(n, std::numeric_limits<EdgeWeight>::max());
658 std::vector<VertexDesc> pred(n);
659 for (
auto [v, vend] = boost::vertices(g); v != vend; ++v) pred[get_vertex_index(*v)] = *v;
660 dist[source_index] = EdgeWeight{};
662 const bool ok = boost::bellman_ford_shortest_paths(
665 boost::weight_map(boost::get(boost::edge_weight, g))
666 .distance_map(boost::make_iterator_property_map(dist.begin(), vertex_index_map))
667 .predecessor_map(boost::make_iterator_property_map(pred.begin(), vertex_index_map))
670 if (!ok)
throw std::runtime_error(
"Bellman-Ford failed: negative cycle detected.");
671 if (dist[target_index] == std::numeric_limits<EdgeWeight>::max())
throw std::runtime_error(
"Shortest-path lookup failed: target node is unreachable.");
673 std::vector<NodeID> path;
674 for (VertexDesc curr = target; curr != source; curr = pred[get_vertex_index(curr)]) path.push_back(get_node_id(curr));
675 path.push_back(get_node_id(source));
676 std::reverse(path.begin(), path.end());
680template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
684 if (id_to_bgl.find(source_id) == id_to_bgl.end()) {
685 throw std::runtime_error(
"Shortest-path lookup failed: source node not found.");
688 const VertexDesc source = id_to_bgl.at(source_id);
689 const size_t n = boost::num_vertices(g);
690 const auto source_index = get_vertex_index(source);
691 std::vector<EdgeWeight> dist(n, std::numeric_limits<EdgeWeight>::max());
692 std::vector<VertexDesc> pred(n);
693 for (
auto [v, vend] = boost::vertices(g); v != vend; ++v) pred[get_vertex_index(*v)] = *v;
694 dist[source_index] = EdgeWeight{};
696 const bool ok = boost::bellman_ford_shortest_paths(
699 boost::weight_map(boost::get(boost::edge_weight, g))
700 .distance_map(boost::make_iterator_property_map(dist.begin(), vertex_index_map))
701 .predecessor_map(boost::make_iterator_property_map(pred.begin(), vertex_index_map))
704 if (!ok)
throw std::runtime_error(
"Bellman-Ford failed: negative cycle detected.");
707 for (
auto [v, vend] = boost::vertices(g); v != vend; ++v) {
708 const auto index = get_vertex_index(*v);
709 const auto&
id = get_node_id(*v);
716template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
720 if (weight.empty() || weight ==
"weight")
return bellman_ford_path(source_id, target_id);
721 throw std::runtime_error(
"Weight lookup failed: only the built-in edge weight property named 'weight' is supported.");
724template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
729 const auto path = bellman_ford_path(source_id, target_id);
730 for (
size_t i = 0; i + 1 < path.size(); ++i) total += get_edge_weight(path[i], path[i + 1]);
734template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
738 if (weight.empty() || weight ==
"weight")
return bellman_ford_path_length(source_id, target_id);
739 throw std::runtime_error(
"Weight lookup failed: only the built-in edge weight property named 'weight' is supported.");
742template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
746 using CalcDistance = shortest_path_calc_type<EdgeWeight>;
747 if (id_to_bgl.find(source_id) == id_to_bgl.end())
throw std::runtime_error(
"Shortest-path lookup failed: source node not found.");
749 const VertexDesc source = id_to_bgl.at(source_id);
750 const size_t n = boost::num_vertices(g);
751 std::vector<CalcDistance> dist(n, std::numeric_limits<CalcDistance>::max());
752 std::vector<VertexDesc> pred(n);
753 for (
auto [v, vend] = boost::vertices(g); v != vend; ++v) pred[get_vertex_index(*v)] = *v;
755 boost::dag_shortest_paths(
757 boost::distance_map(boost::make_iterator_property_map(dist.begin(), vertex_index_map))
758 .predecessor_map(boost::make_iterator_property_map(pred.begin(), vertex_index_map))
759 .distance_compare(std::less<CalcDistance>())
760 .distance_combine(boost::closed_plus<CalcDistance>(std::numeric_limits<CalcDistance>::max()))
761 .distance_inf(std::numeric_limits<CalcDistance>::max())
762 .distance_zero(CalcDistance{})
765 std::vector<EdgeWeight> normalized_dist(n);
766 for (
size_t i = 0; i < n; ++i) normalized_dist[i] = convert_shortest_path_distance<EdgeWeight>(dist[i]);
769 for (
auto [v, vend] = boost::vertices(g); v != vend; ++v) {
770 const auto index = get_vertex_index(*v);
771 const auto&
id = get_node_id(*v);
772 result.
distance[id] = normalized_dist[index];
778template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
782 using CalcDistance = std::conditional_t<std::is_integral_v<EdgeWeight>,
long long, EdgeWeight>;
783 const size_t n = boost::num_vertices(g);
784 const CalcDistance inf = std::numeric_limits<CalcDistance>::max() / 4;
785 std::vector<std::vector<CalcDistance>> internal_matrix(n, std::vector<CalcDistance>(n, inf));
786 for (
size_t i = 0; i < n; ++i) internal_matrix[i][i] = CalcDistance{};
788 for (
auto [e, eend] = boost::edges(g); e != eend; ++e) {
789 const size_t u = get_vertex_index(boost::source(*e, g));
790 const size_t v = get_vertex_index(boost::target(*e, g));
791 const CalcDistance w =
static_cast<CalcDistance
>(boost::get(boost::edge_weight, g, *e));
792 internal_matrix[u][v] = std::min(internal_matrix[u][v], w);
793 if constexpr (!Directed) internal_matrix[v][u] = std::min(internal_matrix[v][u], w);
796 for (
size_t k = 0; k < n; ++k)
for (
size_t i = 0; i < n; ++i)
if (internal_matrix[i][k] != inf)
797 for (
size_t j = 0; j < n; ++j)
if (internal_matrix[k][j] != inf) {
798 const CalcDistance through_k = internal_matrix[i][k] + internal_matrix[k][j];
799 if (through_k < internal_matrix[i][j]) internal_matrix[i][j] = through_k;
802 std::vector<size_t> order(n);
803 for (
size_t i = 0; i < n; ++i) order[i] = i;
804 if constexpr (std::is_arithmetic_v<NodeID> || std::is_same_v<NodeID, std::string>) {
805 std::sort(order.begin(), order.end(), [&](
size_t lhs,
size_t rhs) { return bgl_to_id[lhs] < bgl_to_id[rhs]; });
808 std::vector<std::vector<EdgeWeight>> matrix(n, std::vector<EdgeWeight>(n));
809 for (
size_t i = 0; i < n; ++i)
for (
size_t j = 0; j < n; ++j)
810 matrix[i][j] = internal_matrix[order[i]][order[j]] == inf ? std::numeric_limits<EdgeWeight>::max() :
static_cast<EdgeWeight
>(internal_matrix[order[i]][order[j]]);
814template <
typename NodeID,
typename EdgeWeight,
bool Directed,
bool Multi,
bool Weighted,
typename OutEdgeSelector,
typename VertexSelector>
818 const size_t n = boost::num_vertices(g);
819 std::vector<size_t> order(n);
820 for (
size_t i = 0; i < n; ++i) order[i] = i;
821 if constexpr (std::is_arithmetic_v<NodeID> || std::is_same_v<NodeID, std::string>) {
822 std::sort(order.begin(), order.end(), [&](
size_t lhs,
size_t rhs) { return bgl_to_id[lhs] < bgl_to_id[rhs]; });
824 const auto matrix = floyd_warshall_all_pairs_shortest_paths();
825 std::map<NodeID, std::map<NodeID, EdgeWeight>> result;
826 for (
size_t i = 0; i < n; ++i) {
827 for (
size_t j = 0; j < n; ++j) {
828 result[bgl_to_id[order[i]]][bgl_to_id[order[j]]] = matrix[i][j];
Graph wrapper around Boost Graph Library with Python-inspired helpers.
Definition graph.hpp:272
auto shortest_path(const NodeID &source_id, const NodeID &target_id) const
Computes an unweighted shortest path between two nodes.
Definition shortest_paths.hpp:300
double shortest_path_length(const NodeID &source_id, const NodeID &target_id) const
Returns the length of an unweighted shortest path.
Definition shortest_paths.hpp:374
Core graph wrapper, proxy surface, and public alias presets.
auto shortest_path(const GraphWrapper &G, const typename GraphWrapper::NodeType &source_id, const typename GraphWrapper::NodeType &target_id)
Deprecated free-function alias for G.shortest_path(source, target).
Definition shortest_paths.hpp:142
double shortest_path_length(const GraphWrapper &G, const typename GraphWrapper::NodeType &source_id, const typename GraphWrapper::NodeType &target_id)
Deprecated free-function alias for G.shortest_path_length(source, target).
Definition shortest_paths.hpp:232
Result container for single-source shortest-path routines.
Definition shortest_paths.hpp:40
std::vector< NodeID > path_to(const NodeID &target) const
Reconstructs the path from the original source to target.
Definition shortest_paths.hpp:60
bool has_path_to(const NodeID &target) const
Returns true when the target exists in the result and is reachable.
Definition shortest_paths.hpp:47
std::map< NodeID, NodeID > predecessor
Predecessor tree keyed by target node ID.
Definition shortest_paths.hpp:44
std::map< NodeID, Distance > distance
Final shortest-path distance for each node known to the result.
Definition shortest_paths.hpp:42