From 186d6baaaa07504c3cdafb3623af4d17e2e68330 Mon Sep 17 00:00:00 2001 From: Jeremiah Willcock Date: Tue, 26 May 2009 15:42:40 +0000 Subject: [PATCH] Added no-color-map version of Dijkstra's algorithm from Michael Hansen [SVN r53282] --- .../dijkstra_shortest_paths_no_color_map.hpp | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp diff --git a/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp new file mode 100644 index 00000000..268a70b9 --- /dev/null +++ b/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp @@ -0,0 +1,147 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2009 Trustees of Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Michael Hansen +// +// 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) +//======================================================================= + +#ifndef BOOST_GRAPH_DIJKSTRA_NO_COLOR_MAP_HPP +#define BOOST_GRAPH_DIJKSTRA_NO_COLOR_MAP_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { + +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 vertex_index_map, + DistanceCompare distance_compare, + DistanceWeightCombine distance_weight_combine, + DistanceInfinity distance_infinity, + DistanceZero distance_zero, + DijkstraVisitor visitor) +{ + typedef typename graph_traits::vertex_descriptor Vertex; + typedef typename property_traits::value_type Distance; + typedef typename property_traits::value_type Weight; + + typedef indirect_cmp DistanceIndirectCompare; + DistanceIndirectCompare + distance_indirect_compare(distance_map, distance_compare); + + // Choose vertex queue type +#if BOOST_GRAPH_DIJKSTRA_USE_RELAXED_HEAP + typedef relaxed_heap + VertexQueue; + VertexQueue vertex_queue(num_vertices(graph), + distance_indirect_compare, + vertex_index_map); +#else + // Default - use d-ary heap (d = 4) + typedef + detail::vertex_property_map_generator + IndexInHeapMapHelper; + typedef typename IndexInHeapMapHelper::type IndexInHeapMap; + typedef + d_ary_heap_indirect + VertexQueue; + + boost::scoped_array index_in_heap_map_holder; + IndexInHeapMap index_in_heap = + IndexInHeapMapHelper::build(graph, vertex_index_map, + index_in_heap_map_holder); + VertexQueue vertex_queue(distance_map, index_in_heap, distance_compare); +#endif + + // 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); + + // 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); + + while (!vertex_queue.empty()) { + Vertex min_vertex = vertex_queue.top(); + vertex_queue.pop(); + + visitor.examine_vertex(min_vertex, graph); + + // Check if any other vertices can be reached + Distance min_vertex_distance = get(distance_map, min_vertex); + + if (!distance_compare(min_vertex_distance, distance_infinity)) { + // This is the minimum vertex, so all other vertices are unreachable + return; + } + + // Examine neighbors of min_vertex + typedef typename graph_traits::edge_descriptor Edge; + typename graph_traits::out_edge_iterator edge_iter, edge_iter_end; + BGL_FORALL_OUT_EDGES_T(current_edge, min_vertex, graph, Graph) { + visitor.examine_edge(current_edge, graph); + + // Check if the edge has a negative weight + if (distance_compare(get(weight_map, current_edge), distance_zero)) { + boost::throw_exception(negative_edge()); + } + + Vertex neighbor_vertex = target(current_edge, graph); + Distance neighbor_vertex_distance = get(distance_map, neighbor_vertex); + bool is_neighbor_undiscovered = + !distance_compare(neighbor_vertex_distance, distance_infinity); + + // Attempt to relax the edge + bool was_edge_relaxed = relax(current_edge, graph, weight_map, + predecessor_map, distance_map, + distance_weight_combine, distance_compare); + + if (was_edge_relaxed) { + vertex_queue.update(neighbor_vertex); + visitor.edge_relaxed(current_edge, graph); + } else { + visitor.edge_not_relaxed(current_edge, graph); + } + + if (is_neighbor_undiscovered) { + visitor.discover_vertex(neighbor_vertex, graph); + vertex_queue.push(neighbor_vertex); + } + } // end out edge iteration + + visitor.finish_vertex(min_vertex, graph); + } // end while queue not empty +} + +} // namespace boost + +#endif // BOOST_GRAPH_DIJKSTRA_NO_COLOR_MAP_HPP