bellman_ford_shortest_paths.hpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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. template <class Visitor, class Graph>
  29. struct BellmanFordVisitorConcept {
  30. void constraints() {
  31. BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept<Visitor> ));
  32. vis.examine_edge(e, g);
  33. vis.edge_relaxed(e, g);
  34. vis.edge_not_relaxed(e, g);
  35. vis.edge_minimized(e, g);
  36. vis.edge_not_minimized(e, g);
  37. }
  38. Visitor vis;
  39. Graph g;
  40. typename graph_traits<Graph>::edge_descriptor e;
  41. };
  42. template <class Visitors = null_visitor>
  43. class bellman_visitor {
  44. public:
  45. bellman_visitor() { }
  46. bellman_visitor(Visitors vis) : m_vis(vis) { }
  47. template <class Edge, class Graph>
  48. void examine_edge(Edge u, Graph& g) {
  49. invoke_visitors(m_vis, u, g, on_examine_edge());
  50. }
  51. template <class Edge, class Graph>
  52. void edge_relaxed(Edge u, Graph& g) {
  53. invoke_visitors(m_vis, u, g, on_edge_relaxed());
  54. }
  55. template <class Edge, class Graph>
  56. void edge_not_relaxed(Edge u, Graph& g) {
  57. invoke_visitors(m_vis, u, g, on_edge_not_relaxed());
  58. }
  59. template <class Edge, class Graph>
  60. void edge_minimized(Edge u, Graph& g) {
  61. invoke_visitors(m_vis, u, g, on_edge_minimized());
  62. }
  63. template <class Edge, class Graph>
  64. void edge_not_minimized(Edge u, Graph& g) {
  65. invoke_visitors(m_vis, u, g, on_edge_not_minimized());
  66. }
  67. protected:
  68. Visitors m_vis;
  69. };
  70. template <class Visitors>
  71. bellman_visitor<Visitors>
  72. make_bellman_visitor(Visitors vis) {
  73. return bellman_visitor<Visitors>(vis);
  74. }
  75. typedef bellman_visitor<> default_bellman_visitor;
  76. template <class EdgeListGraph, class Size, class WeightMap,
  77. class PredecessorMap, class DistanceMap,
  78. class BinaryFunction, class BinaryPredicate,
  79. class BellmanFordVisitor>
  80. bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N,
  81. WeightMap weight,
  82. PredecessorMap pred,
  83. DistanceMap distance,
  84. BinaryFunction combine,
  85. BinaryPredicate compare,
  86. BellmanFordVisitor v)
  87. {
  88. BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<EdgeListGraph> ));
  89. typedef graph_traits<EdgeListGraph> GTraits;
  90. typedef typename GTraits::edge_descriptor Edge;
  91. typedef typename GTraits::vertex_descriptor Vertex;
  92. BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<DistanceMap, Vertex> ));
  93. BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<WeightMap, Edge> ));
  94. typename GTraits::edge_iterator i, end;
  95. for (Size k = 0; k < N; ++k) {
  96. bool at_least_one_edge_relaxed = false;
  97. for (boost::tie(i, end) = edges(g); i != end; ++i) {
  98. v.examine_edge(*i, g);
  99. if (relax(*i, g, weight, pred, distance, combine, compare)) {
  100. at_least_one_edge_relaxed = true;
  101. v.edge_relaxed(*i, g);
  102. } else
  103. v.edge_not_relaxed(*i, g);
  104. }
  105. if (!at_least_one_edge_relaxed)
  106. break;
  107. }
  108. for (boost::tie(i, end) = edges(g); i != end; ++i)
  109. if (compare(combine(get(distance, source(*i, g)), get(weight, *i)),
  110. get(distance, target(*i,g))))
  111. {
  112. v.edge_not_minimized(*i, g);
  113. return false;
  114. } else
  115. v.edge_minimized(*i, g);
  116. return true;
  117. }
  118. namespace detail {
  119. template<typename VertexAndEdgeListGraph, typename Size,
  120. typename WeightMap, typename PredecessorMap, typename DistanceMap,
  121. typename P, typename T, typename R>
  122. bool
  123. bellman_dispatch2
  124. (VertexAndEdgeListGraph& g,
  125. typename graph_traits<VertexAndEdgeListGraph>::vertex_descriptor s,
  126. Size N, WeightMap weight, PredecessorMap pred, DistanceMap distance,
  127. const bgl_named_params<P, T, R>& params)
  128. {
  129. typedef typename property_traits<DistanceMap>::value_type D;
  130. bellman_visitor<> null_vis;
  131. typedef typename property_traits<WeightMap>::value_type weight_type;
  132. typename graph_traits<VertexAndEdgeListGraph>::vertex_iterator v, v_end;
  133. for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v) {
  134. put(distance, *v, (std::numeric_limits<weight_type>::max)());
  135. put(pred, *v, *v);
  136. }
  137. put(distance, s, weight_type(0));
  138. return bellman_ford_shortest_paths
  139. (g, N, weight, pred, distance,
  140. choose_param(get_param(params, distance_combine_t()),
  141. closed_plus<D>()),
  142. choose_param(get_param(params, distance_compare_t()),
  143. std::less<D>()),
  144. choose_param(get_param(params, graph_visitor),
  145. null_vis)
  146. );
  147. }
  148. template<typename VertexAndEdgeListGraph, typename Size,
  149. typename WeightMap, typename PredecessorMap, typename DistanceMap,
  150. typename P, typename T, typename R>
  151. bool
  152. bellman_dispatch2
  153. (VertexAndEdgeListGraph& g,
  154. param_not_found,
  155. Size N, WeightMap weight, PredecessorMap pred, DistanceMap distance,
  156. const bgl_named_params<P, T, R>& params)
  157. {
  158. typedef typename property_traits<DistanceMap>::value_type D;
  159. bellman_visitor<> null_vis;
  160. return bellman_ford_shortest_paths
  161. (g, N, weight, pred, distance,
  162. choose_param(get_param(params, distance_combine_t()),
  163. closed_plus<D>()),
  164. choose_param(get_param(params, distance_compare_t()),
  165. std::less<D>()),
  166. choose_param(get_param(params, graph_visitor),
  167. null_vis)
  168. );
  169. }
  170. template <class EdgeListGraph, class Size, class WeightMap,
  171. class DistanceMap, class P, class T, class R>
  172. bool bellman_dispatch(EdgeListGraph& g, Size N,
  173. WeightMap weight, DistanceMap distance,
  174. const bgl_named_params<P, T, R>& params)
  175. {
  176. dummy_property_map dummy_pred;
  177. return
  178. detail::bellman_dispatch2
  179. (g,
  180. get_param(params, root_vertex_t()),
  181. N, weight,
  182. choose_param(get_param(params, vertex_predecessor), dummy_pred),
  183. distance,
  184. params);
  185. }
  186. } // namespace detail
  187. template <class EdgeListGraph, class Size, class P, class T, class R>
  188. bool bellman_ford_shortest_paths
  189. (EdgeListGraph& g, Size N,
  190. const bgl_named_params<P, T, R>& params)
  191. {
  192. return detail::bellman_dispatch
  193. (g, N,
  194. choose_const_pmap(get_param(params, edge_weight), g, edge_weight),
  195. choose_pmap(get_param(params, vertex_distance), g, vertex_distance),
  196. params);
  197. }
  198. template <class EdgeListGraph, class Size>
  199. bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N)
  200. {
  201. bgl_named_params<int,int> params(0);
  202. return bellman_ford_shortest_paths(g, N, params);
  203. }
  204. template <class VertexAndEdgeListGraph, class P, class T, class R>
  205. bool bellman_ford_shortest_paths
  206. (VertexAndEdgeListGraph& g,
  207. const bgl_named_params<P, T, R>& params)
  208. {
  209. BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<VertexAndEdgeListGraph> ));
  210. return detail::bellman_dispatch
  211. (g, num_vertices(g),
  212. choose_const_pmap(get_param(params, edge_weight), g, edge_weight),
  213. choose_pmap(get_param(params, vertex_distance), g, vertex_distance),
  214. params);
  215. }
  216. } // namespace boost
  217. #endif // BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP