diff --git a/include/boost/graph/dijkstra_shortest_paths.hpp b/include/boost/graph/dijkstra_shortest_paths.hpp index 10e40f82..e1b6418f 100644 --- a/include/boost/graph/dijkstra_shortest_paths.hpp +++ b/include/boost/graph/dijkstra_shortest_paths.hpp @@ -541,12 +541,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) { @@ -558,7 +558,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()), @@ -573,12 +573,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) { @@ -589,31 +589,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 #ifdef BOOST_GRAPH_USE_MPI 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 b1a9ef58..6b40775a 100644 --- a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp +++ b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp @@ -20,15 +20,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, @@ -69,12 +70,16 @@ namespace boost { index_in_heap_map_holder); VertexQueue vertex_queue(distance_map, index_in_heap, distance_compare); #endif + + // Add start vertices to the queue + for (SourceInputIter it = s_begin; it != s_end; ++it) { + vertex_queue.push(*it); + } - // Add vertex to the queue - vertex_queue.push(start_vertex); - - // 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(); @@ -128,13 +133,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, @@ -147,37 +152,93 @@ namespace boost { 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) { visitor.initialize_vertex(current_vertex, graph); - + // Default all distances to infinity put(distance_map, current_vertex, distance_infinity); - + // Default all vertex predecessors to the vertex itself 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) { @@ -189,7 +250,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()), @@ -203,12 +264,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) { @@ -220,31 +281,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 739b899e..a0290d5d 100644 --- a/test/dijkstra_no_color_map_compare.cpp +++ b/test/dijkstra_no_color_map_compare.cpp @@ -67,6 +67,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; @@ -113,6 +209,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; }