diff --git a/doc/dijkstra_shortest_paths.html b/doc/dijkstra_shortest_paths.html index fe6713c24..c8cd915d3 100644 --- a/doc/dijkstra_shortest_paths.html +++ b/doc/dijkstra_shortest_paths.html @@ -21,15 +21,19 @@

(Python)

-// named parameter version
+//////////////////////////////////////////
+// functions that take one start vertex //
+//////////////////////////////////////////
+
+// named parameter version for a single start vertex
 template <typename Graph, typename P, typename T, typename R>
-void
-dijkstra_shortest_paths(Graph& g,
-  typename graph_traits<Graph>::vertex_descriptor s,
-  const bgl_named_params<P, T, R>& params);
+void dijkstra_shortest_paths
+  (const Graph& g,
+   typename graph_traits<Graph>::vertex_descriptor s,
+   const bgl_named_params<P, T, R>& params);
 
-// non-named parameter version
-template <typename Graph, typename DijkstraVisitor, 
+// non-named parameter version for a single start vertex
+template <typename Graph, typename DijkstraVisitor,
 	  typename PredecessorMap, typename DistanceMap,
 	  typename WeightMap, typename VertexIndexMap, typename CompareFunction, typename CombineFunction, 
 	  typename DistInf, typename DistZero, typename ColorMap = default>
@@ -46,14 +50,51 @@ 

(Python) class PredecessorMap, class DistanceMap, class WeightMap, class IndexMap, class Compare, class Combine, class DistZero, class ColorMap> -void -dijkstra_shortest_paths_no_init +void dijkstra_shortest_paths_no_init (const Graph& g, typename graph_traits<Graph>::vertex_descriptor s, PredecessorMap predecessor, DistanceMap distance, WeightMap weight, IndexMap index_map, Compare compare, Combine combine, DistZero zero, DijkstraVisitor vis, ColorMap color = default); + + +///////////////////////////////////////////////// +// functions that take multiple start vertices // +///////////////////////////////////////////////// + +// named parameter version for multiple start vertices +template <typename Graph, typename SourceInputIter, typename P, typename T, typename R> +void dijkstra_shortest_paths + (const Graph& g, + SourceInputIter s_begin, SourceInputIter s_end, + const bgl_named_params<P, T, R>& params); + +// non-named parameter version for multiple start vertices +template <typename Graph, typename SourceInputIter, typename DijkstraVisitor, + typename PredecessorMap, typename DistanceMap, + typename WeightMap, typename VertexIndexMap, typename CompareFunction, typename CombineFunction, + typename DistInf, typename DistZero, typename ColorMap = default> +void dijkstra_shortest_paths + (const Graph& g, + SourceInputIter s_begin, SourceInputIter s_end, + PredecessorMap predecessor, DistanceMap distance, WeightMap weight, + VertexIndexMap index_map, + CompareFunction compare, CombineFunction combine, DistInf inf, DistZero zero, + DijkstraVisitor vis, ColorMap color = default) + +// version that does not initialize the property maps (except for the default color map) +template <class Graph, class SourceInputIter, class DijkstraVisitor, + class PredecessorMap, class DistanceMap, + class WeightMap, class IndexMap, class Compare, class Combine, + class DistZero, class ColorMap> +void dijkstra_shortest_paths_no_init + (const Graph& g, + SourceInputIter s_begin, SourceInputIter s_end, + PredecessorMap predecessor, DistanceMap distance, WeightMap weight, + IndexMap index_map, + Compare compare, Combine combine, DistZero zero, + DijkstraVisitor vis, ColorMap color = default);

@@ -67,6 +108,8 @@

(Python) problem see Section Shortest-Paths Algorithms for some background to the shortest-path problem. +For some cases the Dijkstra algorithm can also be applied to a multiple-source +shortest-paths problem, see the section below for more details.

@@ -186,6 +229,38 @@

Where Defined

boost/graph/dijkstra_shortest_paths.hpp +

Multiple Sources

+With some restrictions the Dijkstra algorithm can be used for the +multiple-source shortest path problem. + +The following cases can be identified: + +

Multiple Sources and Single Target

+

+Use reverse_graph to +transfer the problem into a single-source and multiple-targets +shortest path problem. Then you can use the Dijkstra algorithms that +take a single source vertex as input. +

+ +

+Alternatively, when you are only interested in the results (distance +and route) for the source vertex closest to the target, use the +Dijkstra algorithm that takes multiple sources as input. +

+ +

Multiple Sources and Multiple Targets

+

+You can call the Dijkstra algorithm multiple times with just one +source vertex. +

+ +

+Alternatively, when you are only interested in the results (distance +and route) for the source vertex closest to a target, use the Dijkstra +algorithm that takes multiple sources as input. +

+

Parameters

IN: const Graph& g @@ -206,6 +281,18 @@

Parameters

Python: The parameter is named root_vertex. +IN: SourceInputIter s_begin, SourceInputIter s_end +
+ Range [s_begin, s_end) of source vertices denoted by two input + iterators that are used for a multiple-source shortest path problem. + The distance to a target vertex will be calculated from the source + vertex in the range [s_begin, s_end) that is closest to the target, + the shortest path will then have this source vertex as root. + As a result, using these parameters you can not create an order of + the distances from all source vertices to a target vertex, you can + only retrieve the information for the closest target vertex. +
+

Named Parameters

IN: weight_map(WeightMap w_map) @@ -433,7 +520,9 @@

Example

See example/dijkstra-example.cpp for an example of using Dijkstra's -algorithm. +algorithm and +dijkstra-example-multiple-sources.cpp for using multiple source +vertices.

See also

dijkstra_shortest_paths_no_color_map for a version of Dijkstra's shortest path that does not use a color map. diff --git a/doc/dijkstra_shortest_paths_no_color_map.html b/doc/dijkstra_shortest_paths_no_color_map.html index 05c3aec51..0aadd5ee6 100644 --- a/doc/dijkstra_shortest_paths_no_color_map.html +++ b/doc/dijkstra_shortest_paths_no_color_map.html @@ -21,14 +21,18 @@

-// named parameter version
+//////////////////////////////////////////
+// functions that take one start vertex //
+//////////////////////////////////////////
+
+// named parameter version for a single start vertex
 template <typename Graph, typename Param, typename Tag, typename Rest>
 void dijkstra_shortest_paths_no_color_map
   (const Graph& graph,
    typename graph_traits<Graph>::vertex_descriptor start_vertex,
    const bgl_named_params& params);
    
-// non-named parameter version
+// non-named parameter version for a single start vertex
 template <typename Graph, typename DijkstraVisitor, 
 	  typename PredecessorMap, typename DistanceMap,
 	  typename WeightMap, typename VertexIndexMap, typename DistanceCompare, typename DistanceWeightCombine, 
@@ -53,6 +57,44 @@ 

VertexIndexMap index_map, DistanceCompare distance_compare, DistanceWeightCombine distance_weight_combine, DistanceInfinity distance_infinity, DistanceZero distance_zero); + + +///////////////////////////////////////////////// +// functions that take multiple start vertices // +///////////////////////////////////////////////// + +// named parameter version for multiple start vertices +template <typename Graph, typename SourceInputIter, typename Param, typename Tag, typename Rest> +void dijkstra_shortest_paths_no_color_map + (const Graph& graph, + SourceInputIter s_begin, SourceInputIter s_end, + const bgl_named_params& params); + +// non-named parameter version for multiple start vertices +template <typename Graph, typename SourceInputIter, typename DijkstraVisitor, + typename PredecessorMap, typename DistanceMap, + typename WeightMap, typename VertexIndexMap, typename DistanceCompare, typename DistanceWeightCombine, + typename DistanceInfinity, typename DistanceZero> +void dijkstra_shortest_paths_no_color_map + (const Graph& graph, + SourceInputIter s_begin, SourceInputIter s_end, + PredecessorMap predecessor_map, DistanceMap distance_map, WeightMap weight_map, + VertexIndexMap index_map, + DistanceCompare distance_compare, DistanceWeightCombine distance_weight_combine, + DistanceInfinity distance_infinity, DistanceZero distance_zero); + +// version that does not initialize the property maps +template <typename Graph, typename SourceInputIter, typename DijkstraVisitor, + typename PredecessorMap, typename DistanceMap, + typename WeightMap, typename VertexIndexMap, typename DistanceCompare, typename DistanceWeightCombine, + typename DistanceInfinity, typename DistanceZero> +void dijkstra_shortest_paths_no_color_map_no_init + (const Graph& graph, + SourceInputIter s_begin, SourceInputIter s_end, + PredecessorMap predecessor_map, DistanceMap distance_map, WeightMap weight_map, + VertexIndexMap index_map, + DistanceCompare distance_compare, DistanceWeightCombine distance_weight_combine, + DistanceInfinity distance_infinity, DistanceZero distance_zero);

@@ -66,6 +108,8 @@

problem see Section Shortest-Paths Algorithms for some background to the shortest-path problem. +For some cases the Dijkstra algorithm can also be applied to a multiple-source +shortest-paths problem, see the section below for more details.

@@ -162,6 +206,38 @@

Where Defined

boost/graph/dijkstra_shortest_paths_no_color_map.hpp +

Multiple Sources

+With some restrictions the Dijkstra algorithm can be used for the +multiple-source shortest path problem. + +The following cases can be identified: + +

Multiple Sources and Single Target

+

+Use reverse_graph to +transfer the problem into a single-source and multiple-targets +shortest path problem. Then you can use the Dijkstra algorithms that +take a single source vertex as input. +

+ +

+Alternatively, when you are only interested in the results (distance +and route) for the source vertex closest to the target, use the +Dijkstra algorithm that takes multiple sources as input. +

+ +

Multiple Sources and Multiple Targets

+

+You can call the Dijkstra algorithm multiple times with just one +source vertex. +

+ +

+Alternatively, when you are only interested in the results (distance +and route) for the source vertex closest to a target, use the Dijkstra +algorithm that takes multiple sources as input. +

+

Parameters

IN: const Graph& graph @@ -178,6 +254,18 @@

Parameters

and the shortest paths tree will be rooted at this vertex.
+IN: SourceInputIter s_begin, SourceInputIter s_end +
+ Range [s_begin, s_end) of source vertices denoted by two input + iterators that are used for a multiple-source shortest path problem. + The distance to a target vertex will be calculated from the source + vertex in the range [s_begin, s_end) that is closest to the target, + the shortest path will then have this source vertex as root. + As a result, using these parameters you can not create an order of + the distances from all source vertices to a target vertex, you can + only retrieve the information for the closest target vertex. +
+

Named Parameters

IN: weight_map(WeightMap weight_map) @@ -356,7 +444,10 @@

Example

See -example/dijkstra-no-color-map-example.cpp for an example of using Dijkstra's algorithm. +example/dijkstra-no-color-map-example.cpp for an example of using Dijkstra's algorithm +and +dijkstra-no-color-map-example-multiple-sources.cpp for using multiple source +vertices.

See also

dijkstra_shortest_paths for a version of Dijkstra's shortest path that uses a color map. diff --git a/example/Jamfile.v2 b/example/Jamfile.v2 index f1bc9d994..428806eeb 100644 --- a/example/Jamfile.v2 +++ b/example/Jamfile.v2 @@ -55,8 +55,10 @@ run dfs.cpp ; run dfs_parenthesis.cpp ; run dfs-example.cpp ; run dijkstra-example.cpp ; +run dijkstra-example-multiple-sources.cpp ; run dijkstra-example-listS.cpp ; run dijkstra-no-color-map-example.cpp ; +run dijkstra-no-color-map-example-multiple-sources.cpp ; run directed_graph.cpp ; exe eccentricity : eccentricity.cpp ; run edge_basics.cpp ; diff --git a/example/dijkstra-example-multiple-sources.cpp b/example/dijkstra-example-multiple-sources.cpp new file mode 100644 index 000000000..019b45660 --- /dev/null +++ b/example/dijkstra-example-multiple-sources.cpp @@ -0,0 +1,79 @@ +//======================================================================= +// Copyright 2001 Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee, +// Copyright 2019 Matthias Fuchs +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#include +#include +#include + +#include +#include +#include +#include + +using namespace boost; + +int +main(int, char *[]) +{ + typedef adjacency_list < listS, vecS, directedS, + no_property, property < edge_weight_t, int > > graph_t; + typedef graph_traits < graph_t >::vertex_descriptor vertex_descriptor; + typedef std::pair Edge; + + const int num_nodes = 7; + enum nodes { A, B, C, D, E, F, G }; + char name[] = "ABCDEFG"; + Edge edge_array[] = { Edge(A, C), Edge(A, B), Edge(B, A), + Edge(B, C), Edge(A, D), Edge(D, A), Edge(D, E), Edge(D, F), Edge(B, F), + Edge(F, B), Edge(F, G), Edge(G, F), Edge(G, E), Edge(E, G) + }; + int weights[] = { 4, 1, 2, 3, 1, 1, 3, 2, 1, 2, 5, 1, 1, 1 }; + int num_arcs = sizeof(edge_array) / sizeof(Edge); + graph_t g(edge_array, edge_array + num_arcs, weights, num_nodes); + property_map::type weightmap = get(edge_weight, g); + std::vector p(num_vertices(g)); + std::vector d(num_vertices(g)); + vertex_descriptor start_nodes[] = { vertex(A, g), vertex(B, g) }; + + dijkstra_shortest_paths(g, start_nodes, start_nodes + 2, + predecessor_map(boost::make_iterator_property_map(p.begin(), get(boost::vertex_index, g))). + distance_map(boost::make_iterator_property_map(d.begin(), get(boost::vertex_index, g)))); + + std::cout << "distances and parents:" << std::endl; + graph_traits < graph_t >::vertex_iterator vi, vend; + for (boost::tie(vi, vend) = vertices(g); vi != vend; ++vi) { + std::cout << "distance(" << name[*vi] << ") = " << d[*vi] << ", "; + std::cout << "parent(" << name[*vi] << ") = " << name[p[*vi]] << std:: + endl; + } + std::cout << std::endl; + + std::ofstream dot_file("figs/dijkstra-eg-multiple-sources.dot"); + + dot_file << "digraph D {\n" + << " rankdir=LR\n" + << " size=\"4,3\"\n" + << " ratio=\"fill\"\n" + << " edge[style=\"bold\"]\n" << " node[shape=\"circle\"]\n"; + + graph_traits < graph_t >::edge_iterator ei, ei_end; + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) { + graph_traits < graph_t >::edge_descriptor e = *ei; + graph_traits < graph_t >::vertex_descriptor + u = source(e, g), v = target(e, g); + dot_file << name[u] << " -> " << name[v] + << "[label=\"" << get(weightmap, e) << "\""; + if (p[v] == u) + dot_file << ", color=\"black\""; + else + dot_file << ", color=\"grey\""; + dot_file << "]"; + } + dot_file << "}"; + return EXIT_SUCCESS; +} diff --git a/example/dijkstra-no-color-map-example-multiple-sources.cpp b/example/dijkstra-no-color-map-example-multiple-sources.cpp new file mode 100644 index 000000000..6df5f2f50 --- /dev/null +++ b/example/dijkstra-no-color-map-example-multiple-sources.cpp @@ -0,0 +1,83 @@ +//======================================================================= +// Copyright 2001 Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee +// Copyright 2009 Trustees of Indiana University. +// Copyright 2001 Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee, +// Copyright 2019 Matthias Fuchs +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// NOTE: Based off of dijkstra-example.cpp +//======================================================================= +#include +#include +#include + +#include +#include +#include +#include + +using namespace boost; + +int +main(int, char *[]) +{ + typedef adjacency_list < listS, vecS, directedS, + no_property, property < edge_weight_t, int > > graph_t; + typedef graph_traits < graph_t >::vertex_descriptor vertex_descriptor; + typedef std::pair Edge; + + const int num_nodes = 7; + enum nodes { A, B, C, D, E, F, G }; + char name[] = "ABCDEFG"; + Edge edge_array[] = { Edge(A, C), Edge(A, B), Edge(B, A), + Edge(B, C), Edge(A, D), Edge(D, A), Edge(D, E), Edge(D, F), Edge(B, F), + Edge(F, B), Edge(F, G), Edge(G, F), Edge(G, E), Edge(E, G) + }; + int weights[] = { 4, 1, 2, 3, 1, 1, 3, 2, 1, 2, 5, 1, 1, 1 }; + int num_arcs = sizeof(edge_array) / sizeof(Edge); + graph_t g(edge_array, edge_array + num_arcs, weights, num_nodes); + property_map::type weightmap = get(edge_weight, g); + std::vector p(num_vertices(g)); + std::vector d(num_vertices(g)); + vertex_descriptor start_nodes[] = { vertex(A, g), vertex(B, g) }; + + dijkstra_shortest_paths_no_color_map(g, start_nodes, start_nodes + 2, + predecessor_map(boost::make_iterator_property_map(p.begin(), get(boost::vertex_index, g))). + distance_map(boost::make_iterator_property_map(d.begin(), get(boost::vertex_index, g)))); + + std::cout << "distances and parents:" << std::endl; + graph_traits < graph_t >::vertex_iterator vi, vend; + for (boost::tie(vi, vend) = vertices(g); vi != vend; ++vi) { + std::cout << "distance(" << name[*vi] << ") = " << d[*vi] << ", "; + std::cout << "parent(" << name[*vi] << ") = " << name[p[*vi]] << std:: + endl; + } + std::cout << std::endl; + + std::ofstream dot_file("figs/dijkstra-no-color-map-eg.dot"); + + dot_file << "digraph D {\n" + << " rankdir=LR\n" + << " size=\"4,3\"\n" + << " ratio=\"fill\"\n" + << " edge[style=\"bold\"]\n" << " node[shape=\"circle\"]\n"; + + graph_traits < graph_t >::edge_iterator ei, ei_end; + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) { + graph_traits < graph_t >::edge_descriptor e = *ei; + graph_traits < graph_t >::vertex_descriptor + u = source(e, g), v = target(e, g); + dot_file << name[u] << " -> " << name[v] + << "[label=\"" << get(weightmap, e) << "\""; + if (p[v] == u) + dot_file << ", color=\"black\""; + else + dot_file << ", color=\"grey\""; + dot_file << "]"; + } + dot_file << "}"; + return EXIT_SUCCESS; +} diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp index 9ee2cbd6e..5d63ffd23 100644 --- a/include/boost/graph/dijkstra_shortest_paths.hpp +++ b/include/boost/graph/dijkstra_shortest_paths.hpp @@ -517,12 +517,12 @@ namespace boost { // Handle defaults for PredecessorMap and // Distance Compare, Combine, Inf and Zero - template + template inline void dijkstra_dispatch2 (const VertexListGraph& g, - typename graph_traits::vertex_descriptor s, + SourceInputIter s_begin, SourceInputIter s_end, DistanceMap distance, WeightMap weight, IndexMap index_map, const Params& params) { @@ -534,7 +534,7 @@ namespace boost { (std::numeric_limits::max)()); dijkstra_shortest_paths - (g, s, + (g, s_begin, s_end, choose_param(get_param(params, vertex_predecessor), p_map), distance, weight, index_map, choose_param(get_param(params, distance_compare_t()), @@ -549,12 +549,12 @@ namespace boost { params); } - template + template inline void dijkstra_dispatch1 (const VertexListGraph& g, - typename graph_traits::vertex_descriptor s, + SourceInputIter s_begin, SourceInputIter s_end, DistanceMap distance, WeightMap weight, IndexMap index_map, const Params& params) { @@ -565,31 +565,44 @@ namespace boost { std::vector distance_map(n); detail::dijkstra_dispatch2 - (g, s, choose_param(distance, make_iterator_property_map - (distance_map.begin(), index_map, - distance_map[0])), + (g, s_begin, s_end, + choose_param(distance, make_iterator_property_map + (distance_map.begin(), index_map, + distance_map[0])), weight, index_map, params); } } // namespace detail - // Named Parameter Variant - template + // Named parameter version for multiple start vertices + template inline void dijkstra_shortest_paths (const VertexListGraph& g, - typename graph_traits::vertex_descriptor s, + SourceInputIter s_begin, SourceInputIter s_end, const bgl_named_params& params) { // Default for edge weight and vertex index map is to ask for them // from the graph. Default for the visitor is null_visitor. detail::dijkstra_dispatch1 - (g, s, + (g, s_begin, s_end, get_param(params, vertex_distance), choose_const_pmap(get_param(params, edge_weight), g, edge_weight), choose_const_pmap(get_param(params, vertex_index), g, vertex_index), params); } + // Named parameter version for a single start vertex + template + inline void + dijkstra_shortest_paths + (const VertexListGraph& g, + typename graph_traits::vertex_descriptor s, + const bgl_named_params& params) + { + dijkstra_shortest_paths(g, &s, &s + 1, params); + } + } // namespace boost #include BOOST_GRAPH_MPI_INCLUDE() diff --git a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp index eb96c0d88..cc87c4af4 100644 --- a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp +++ b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp @@ -19,15 +19,16 @@ namespace boost { - // No init version + // No init version for multiple start vertices template void dijkstra_shortest_paths_no_color_map_no_init (const Graph& graph, - typename graph_traits::vertex_descriptor start_vertex, + SourceInputIter s_begin, SourceInputIter s_end, PredecessorMap predecessor_map, DistanceMap distance_map, WeightMap weight_map, @@ -61,11 +62,15 @@ namespace boost { index_in_heap_map_holder); VertexQueue vertex_queue(distance_map, index_in_heap, distance_compare); - // Add vertex to the queue - vertex_queue.push(start_vertex); + // Add start vertices to the queue + for (SourceInputIter it = s_begin; it != s_end; ++it) { + vertex_queue.push(*it); + } - // Starting vertex will always be the first discovered vertex - visitor.discover_vertex(start_vertex, graph); + // Starting vertices will always be the first discovered vertices + for (SourceInputIter it = s_begin; it != s_end; ++it) { + visitor.discover_vertex(*it, graph); + } while (!vertex_queue.empty()) { Vertex min_vertex = vertex_queue.top(); @@ -119,13 +124,13 @@ namespace boost { } // end while queue not empty } - // Full init version + // No init version for a single start vertex template - void dijkstra_shortest_paths_no_color_map + void dijkstra_shortest_paths_no_color_map_no_init (const Graph& graph, typename graph_traits::vertex_descriptor start_vertex, PredecessorMap predecessor_map, @@ -137,6 +142,33 @@ namespace boost { DistanceInfinity distance_infinity, DistanceZero distance_zero, DijkstraVisitor visitor) + { + dijkstra_shortest_paths_no_color_map_no_init(graph, + &start_vertex, &start_vertex + 1, + predecessor_map, distance_map, weight_map, index_map, + distance_compare, distance_weight_combine, distance_infinity, + distance_zero, visitor); + } + + // Full init version for multiple start vertices + template + void dijkstra_shortest_paths_no_color_map + (const Graph& graph, + SourceInputIter s_begin, SourceInputIter s_end, + PredecessorMap predecessor_map, + DistanceMap distance_map, + WeightMap weight_map, + VertexIndexMap index_map, + DistanceCompare distance_compare, + DistanceWeightCombine distance_weight_combine, + DistanceInfinity distance_infinity, + DistanceZero distance_zero, + DijkstraVisitor visitor) { // Initialize vertices BGL_FORALL_VERTICES_T(current_vertex, graph, Graph) { @@ -149,26 +181,55 @@ namespace boost { put(predecessor_map, current_vertex, current_vertex); } - // Set distance for start_vertex to zero - put(distance_map, start_vertex, distance_zero); + // Set distance for start vertices to zero + for (SourceInputIter it = s_begin; it != s_end; ++it) { + put(distance_map, *it, distance_zero); + } // Pass everything on to the no_init version dijkstra_shortest_paths_no_color_map_no_init(graph, - start_vertex, predecessor_map, distance_map, weight_map, - index_map, distance_compare, distance_weight_combine, - distance_infinity, distance_zero, visitor); + s_begin, s_end, predecessor_map, distance_map, + weight_map, index_map, distance_compare, + distance_weight_combine, distance_infinity, distance_zero, + visitor); + } + + // Full init version for a single start vertex + template + void dijkstra_shortest_paths_no_color_map + (const Graph& graph, + typename graph_traits::vertex_descriptor start_vertex, + PredecessorMap predecessor_map, + DistanceMap distance_map, + WeightMap weight_map, + VertexIndexMap index_map, + DistanceCompare distance_compare, + DistanceWeightCombine distance_weight_combine, + DistanceInfinity distance_infinity, + DistanceZero distance_zero, + DijkstraVisitor visitor) + { + dijkstra_shortest_paths_no_color_map(graph, + &start_vertex, &start_vertex + 1, + predecessor_map, distance_map, weight_map, index_map, + distance_compare, distance_weight_combine, distance_infinity, + distance_zero, visitor); } namespace detail { // Handle defaults for PredecessorMap, DistanceCompare, // DistanceWeightCombine, DistanceInfinity and DistanceZero - template + template inline void dijkstra_no_color_map_dispatch2 (const Graph& graph, - typename graph_traits::vertex_descriptor start_vertex, + SourceInputIter s_begin, SourceInputIter s_end, DistanceMap distance_map, WeightMap weight_map, VertexIndexMap index_map, const Params& params) { @@ -180,7 +241,7 @@ namespace boost { choose_param(get_param(params, distance_inf_t()), (std::numeric_limits::max)()); dijkstra_shortest_paths_no_color_map - (graph, start_vertex, + (graph, s_begin, s_end, choose_param(get_param(params, vertex_predecessor), predecessor_map), distance_map, weight_map, index_map, choose_param(get_param(params, distance_compare_t()), @@ -194,12 +255,12 @@ namespace boost { make_dijkstra_visitor(null_visitor()))); } - template + template inline void dijkstra_no_color_map_dispatch1 (const Graph& graph, - typename graph_traits::vertex_descriptor start_vertex, + SourceInputIter s_begin, SourceInputIter s_end, DistanceMap distance_map, WeightMap weight_map, IndexMap index_map, const Params& params) { @@ -211,31 +272,44 @@ namespace boost { std::vector default_distance_map(vertex_count); detail::dijkstra_no_color_map_dispatch2 - (graph, start_vertex, choose_param(distance_map, + (graph, s_begin, s_end, choose_param(distance_map, make_iterator_property_map(default_distance_map.begin(), index_map, default_distance_map[0])), weight_map, index_map, params); } } // namespace detail - // Named parameter version - template + // Named parameter version for multiple start vertices + template inline void dijkstra_shortest_paths_no_color_map (const Graph& graph, - typename graph_traits::vertex_descriptor start_vertex, + SourceInputIter s_begin, SourceInputIter s_end, const bgl_named_params& params) { // Default for edge weight and vertex index map is to ask for them // from the graph. Default for the visitor is null_visitor. detail::dijkstra_no_color_map_dispatch1 - (graph, start_vertex, + (graph, s_begin, s_end, get_param(params, vertex_distance), choose_const_pmap(get_param(params, edge_weight), graph, edge_weight), choose_const_pmap(get_param(params, vertex_index), graph, vertex_index), params); } + // Named parameter version for a single start vertex + template + inline void + dijkstra_shortest_paths_no_color_map + (const Graph& graph, + typename graph_traits::vertex_descriptor start_vertex, + const bgl_named_params& params) + { + dijkstra_shortest_paths_no_color_map(graph, + &start_vertex, &start_vertex + 1, params); + } + } // namespace boost #endif // BOOST_GRAPH_DIJKSTRA_NO_COLOR_MAP_HPP diff --git a/test/dijkstra_no_color_map_compare.cpp b/test/dijkstra_no_color_map_compare.cpp index 89a4bcc70..b33a6324e 100644 --- a/test/dijkstra_no_color_map_compare.cpp +++ b/test/dijkstra_no_color_map_compare.cpp @@ -74,6 +74,102 @@ void run_dijkstra_test(const Graph& graph) no_color_map_vertex_double_map.begin())); } +template +void run_dijkstra_multiple_start_vertices_test(const Graph& graph) +{ + /* + Calculate from two start vertices A and B (MULTIPLE). + Also calculate with a single start vertex A (CALC_A) and B (CALC_B). + When the distance from A to a target X is shorter than from B to X + compare MULTIPLE with CALC_B and vice versa. + In case distance A -> X and B -> X are equal check that any of + CALC_A/CALC_B matches MULTIPLE. + */ + using namespace boost; + + // Set up property maps + typedef typename graph_traits::vertex_descriptor vertex_t; + + typedef typename std::map vertex_map_t; + typedef associative_property_map predecessor_map_t; + vertex_map_t vertex_predecessor_map_1, + vertex_predecessor_map_2, + vertex_predecessor_map_12, + vertex_predecessor_map_12_color; + predecessor_map_t predecessors_1(vertex_predecessor_map_1), + predecessors_2(vertex_predecessor_map_2), + predecessors_12(vertex_predecessor_map_12), + predecessors_12_color(vertex_predecessor_map_12_color); + + typedef typename std::map vertex_double_map_t; + typedef associative_property_map distance_map_t; + vertex_double_map_t vertex_distance_map_1, + vertex_distance_map_2, + vertex_distance_map_12, + vertex_distance_map_12_color; + distance_map_t distances_1(vertex_distance_map_1), + distances_2(vertex_distance_map_2), + distances_12(vertex_distance_map_12), + distances_12_color(vertex_distance_map_12_color); + + // calculate from two start vertices + vertex_t start_vertex_1 = vertex(0, graph); + vertex_t start_vertex_2 = vertex(num_vertices(graph) / 2, graph); + std::vector start_vertices; + start_vertices.push_back(start_vertex_1); + start_vertices.push_back(start_vertex_2); + + // Run dijkstra algorithms + dijkstra_shortest_paths_no_color_map( + graph, start_vertex_1, + predecessor_map(predecessors_1) + .distance_map(distances_1)); + dijkstra_shortest_paths_no_color_map( + graph, start_vertex_2, + predecessor_map(predecessors_2) + .distance_map(distances_2)); + dijkstra_shortest_paths_no_color_map( + graph, start_vertices.begin(), start_vertices.end(), + predecessor_map(predecessors_12) + .distance_map(distances_12)); + dijkstra_shortest_paths( + graph, start_vertices.begin(), start_vertices.end(), + predecessor_map(predecessors_12_color) + .distance_map(distances_12_color)); + + // Check the results + typedef typename vertex_map_t::const_iterator vertex_map_t_iter; + vertex_map_t_iter it_pred1 = vertex_predecessor_map_1.begin(), + it_pred2 = vertex_predecessor_map_2.begin(), + it_pred12 = vertex_predecessor_map_12.begin(), + it_pred12_color = vertex_predecessor_map_12_color.begin(); + + typedef typename vertex_double_map_t::const_iterator vertex_double_map_t_iter; + vertex_double_map_t_iter it_dist1 = vertex_distance_map_1.begin(), + it_dist2 = vertex_distance_map_2.begin(), + it_dist12 = vertex_distance_map_12.begin(), + it_dist12_color = vertex_distance_map_12_color.begin(); + + while (it_pred1 != vertex_predecessor_map_1.end()) { + BOOST_CHECK(*it_pred12 == *it_pred12_color); + BOOST_CHECK(*it_dist12 == *it_dist12_color); + + if (it_dist1->second < it_dist2->second) { + BOOST_CHECK(*it_pred1 == *it_pred12); + BOOST_CHECK(*it_dist1 == *it_dist12); + } else if (it_dist2->second < it_dist1->second) { + BOOST_CHECK(*it_pred2 == *it_pred12); + BOOST_CHECK(*it_dist2 == *it_dist12); + } else { + BOOST_CHECK(*it_pred1 == *it_pred12 || *it_pred2 == *it_pred12); + BOOST_CHECK(*it_dist1 == *it_dist12); + } + + ++it_pred1, ++it_pred2, ++it_pred12, ++it_pred12_color; + ++it_dist1, ++it_dist2, ++it_dist12, ++it_dist12_color; + } +} + int test_main(int argc, char* argv[]) { using namespace boost; @@ -120,6 +216,7 @@ int test_main(int argc, char* argv[]) " vertices and " << num_edges(graph) << " edges " << std::endl; run_dijkstra_test(graph); + run_dijkstra_multiple_start_vertices_test(graph); return 0; }