bellman_ford_shortest_paths.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. //
  2. //=======================================================================
  3. // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
  4. // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
  5. //
  6. // Distributed under the Boost Software License, Version 1.0. (See
  7. // accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //=======================================================================
  10. //
  11. /*
  12. This file implements the function
  13. template <class EdgeListGraph, class Size, class P, class T, class R>
  14. bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N,
  15. const bgl_named_params<P, T, R>& params)
  16. */
  17. #ifndef BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP
  18. #define BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP
  19. #include <boost/config.hpp>
  20. #include <boost/graph/graph_traits.hpp>
  21. #include <boost/graph/graph_concepts.hpp>
  22. #include <boost/graph/properties.hpp>
  23. #include <boost/graph/relax.hpp>
  24. #include <boost/graph/visitors.hpp>
  25. #include <boost/graph/named_function_params.hpp>
  26. #include <boost/concept/assert.hpp>
  27. namespace boost
  28. {
  29. template < class Visitor, class Graph > struct BellmanFordVisitorConcept
  30. {
  31. void constraints()
  32. {
  33. BOOST_CONCEPT_ASSERT((CopyConstructibleConcept< Visitor >));
  34. vis.examine_edge(e, g);
  35. vis.edge_relaxed(e, g);
  36. vis.edge_not_relaxed(e, g);
  37. vis.edge_minimized(e, g);
  38. vis.edge_not_minimized(e, g);
  39. }
  40. Visitor vis;
  41. Graph g;
  42. typename graph_traits< Graph >::edge_descriptor e;
  43. };
  44. template < class Visitors = null_visitor > class bellman_visitor
  45. {
  46. public:
  47. bellman_visitor() {}
  48. bellman_visitor(Visitors vis) : m_vis(vis) {}
  49. template < class Edge, class Graph > void examine_edge(Edge u, Graph& g)
  50. {
  51. invoke_visitors(m_vis, u, g, on_examine_edge());
  52. }
  53. template < class Edge, class Graph > void edge_relaxed(Edge u, Graph& g)
  54. {
  55. invoke_visitors(m_vis, u, g, on_edge_relaxed());
  56. }
  57. template < class Edge, class Graph > void edge_not_relaxed(Edge u, Graph& g)
  58. {
  59. invoke_visitors(m_vis, u, g, on_edge_not_relaxed());
  60. }
  61. template < class Edge, class Graph > void edge_minimized(Edge u, Graph& g)
  62. {
  63. invoke_visitors(m_vis, u, g, on_edge_minimized());
  64. }
  65. template < class Edge, class Graph >
  66. void edge_not_minimized(Edge u, Graph& g)
  67. {
  68. invoke_visitors(m_vis, u, g, on_edge_not_minimized());
  69. }
  70. protected:
  71. Visitors m_vis;
  72. };
  73. template < class Visitors >
  74. bellman_visitor< Visitors > make_bellman_visitor(Visitors vis)
  75. {
  76. return bellman_visitor< Visitors >(vis);
  77. }
  78. typedef bellman_visitor<> default_bellman_visitor;
  79. template < class EdgeListGraph, class Size, class WeightMap,
  80. class PredecessorMap, class DistanceMap, class BinaryFunction,
  81. class BinaryPredicate, class BellmanFordVisitor >
  82. bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N, WeightMap weight,
  83. PredecessorMap pred, DistanceMap distance, BinaryFunction combine,
  84. BinaryPredicate compare, BellmanFordVisitor v)
  85. {
  86. BOOST_CONCEPT_ASSERT((EdgeListGraphConcept< EdgeListGraph >));
  87. typedef graph_traits< EdgeListGraph > GTraits;
  88. typedef typename GTraits::edge_descriptor Edge;
  89. typedef typename GTraits::vertex_descriptor Vertex;
  90. BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept< DistanceMap, Vertex >));
  91. BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< WeightMap, Edge >));
  92. typename GTraits::edge_iterator i, end;
  93. for (Size k = 0; k < N; ++k)
  94. {
  95. bool at_least_one_edge_relaxed = false;
  96. for (boost::tie(i, end) = edges(g); i != end; ++i)
  97. {
  98. v.examine_edge(*i, g);
  99. if (relax(*i, g, weight, pred, distance, combine, compare))
  100. {
  101. at_least_one_edge_relaxed = true;
  102. v.edge_relaxed(*i, g);
  103. }
  104. else
  105. v.edge_not_relaxed(*i, g);
  106. }
  107. if (!at_least_one_edge_relaxed)
  108. break;
  109. }
  110. for (boost::tie(i, end) = edges(g); i != end; ++i)
  111. if (compare(combine(get(distance, source(*i, g)), get(weight, *i)),
  112. get(distance, target(*i, g))))
  113. {
  114. v.edge_not_minimized(*i, g);
  115. return false;
  116. }
  117. else
  118. v.edge_minimized(*i, g);
  119. return true;
  120. }
  121. namespace detail
  122. {
  123. template < typename VertexAndEdgeListGraph, typename Size,
  124. typename WeightMap, typename PredecessorMap, typename DistanceMap,
  125. typename P, typename T, typename R >
  126. bool bellman_dispatch2(VertexAndEdgeListGraph& g,
  127. typename graph_traits< VertexAndEdgeListGraph >::vertex_descriptor s,
  128. Size N, WeightMap weight, PredecessorMap pred, DistanceMap distance,
  129. const bgl_named_params< P, T, R >& params)
  130. {
  131. typedef typename property_traits< DistanceMap >::value_type D;
  132. bellman_visitor<> null_vis;
  133. typedef typename property_traits< WeightMap >::value_type weight_type;
  134. typename graph_traits< VertexAndEdgeListGraph >::vertex_iterator v,
  135. v_end;
  136. for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v)
  137. {
  138. put(distance, *v, (std::numeric_limits< weight_type >::max)());
  139. put(pred, *v, *v);
  140. }
  141. put(distance, s, weight_type(0));
  142. return bellman_ford_shortest_paths(g, N, weight, pred, distance,
  143. choose_param(
  144. get_param(params, distance_combine_t()), closed_plus< D >()),
  145. choose_param(
  146. get_param(params, distance_compare_t()), std::less< D >()),
  147. choose_param(get_param(params, graph_visitor), null_vis));
  148. }
  149. template < typename VertexAndEdgeListGraph, typename Size,
  150. typename WeightMap, typename PredecessorMap, typename DistanceMap,
  151. typename P, typename T, typename R >
  152. bool bellman_dispatch2(VertexAndEdgeListGraph& g, param_not_found, Size N,
  153. WeightMap weight, PredecessorMap pred, DistanceMap distance,
  154. const bgl_named_params< P, T, R >& params)
  155. {
  156. typedef typename property_traits< DistanceMap >::value_type D;
  157. bellman_visitor<> null_vis;
  158. return bellman_ford_shortest_paths(g, N, weight, pred, distance,
  159. choose_param(
  160. get_param(params, distance_combine_t()), closed_plus< D >()),
  161. choose_param(
  162. get_param(params, distance_compare_t()), std::less< D >()),
  163. choose_param(get_param(params, graph_visitor), null_vis));
  164. }
  165. template < class EdgeListGraph, class Size, class WeightMap,
  166. class DistanceMap, class P, class T, class R >
  167. bool bellman_dispatch(EdgeListGraph& g, Size N, WeightMap weight,
  168. DistanceMap distance, const bgl_named_params< P, T, R >& params)
  169. {
  170. dummy_property_map dummy_pred;
  171. return detail::bellman_dispatch2(g, get_param(params, root_vertex_t()),
  172. N, weight,
  173. choose_param(get_param(params, vertex_predecessor), dummy_pred),
  174. distance, params);
  175. }
  176. } // namespace detail
  177. template < class EdgeListGraph, class Size, class P, class T, class R >
  178. bool bellman_ford_shortest_paths(
  179. EdgeListGraph& g, Size N, const bgl_named_params< P, T, R >& params)
  180. {
  181. return detail::bellman_dispatch(g, N,
  182. choose_const_pmap(get_param(params, edge_weight), g, edge_weight),
  183. choose_pmap(get_param(params, vertex_distance), g, vertex_distance),
  184. params);
  185. }
  186. template < class EdgeListGraph, class Size >
  187. bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N)
  188. {
  189. bgl_named_params< int, int > params(0);
  190. return bellman_ford_shortest_paths(g, N, params);
  191. }
  192. template < class VertexAndEdgeListGraph, class P, class T, class R >
  193. bool bellman_ford_shortest_paths(
  194. VertexAndEdgeListGraph& g, const bgl_named_params< P, T, R >& params)
  195. {
  196. BOOST_CONCEPT_ASSERT((VertexListGraphConcept< VertexAndEdgeListGraph >));
  197. return detail::bellman_dispatch(g, num_vertices(g),
  198. choose_const_pmap(get_param(params, edge_weight), g, edge_weight),
  199. choose_pmap(get_param(params, vertex_distance), g, vertex_distance),
  200. params);
  201. }
  202. } // namespace boost
  203. #endif // BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP