successive_shortest_path_nonnegative_weights.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. //=======================================================================
  2. // Copyright 2013 University of Warsaw.
  3. // Authors: Piotr Wygocki
  4. //
  5. // Distributed under the Boost Software License, Version 1.0. (See
  6. // accompanying file LICENSE_1_0.txt or copy at
  7. // http://www.boost.org/LICENSE_1_0.txt)
  8. //=======================================================================
  9. //
  10. // This algorithm is described in "Network Flows: Theory, Algorithms, and
  11. // Applications"
  12. // by Ahuja, Magnanti, Orlin.
  13. #ifndef BOOST_GRAPH_SUCCESSIVE_SHORTEST_PATH_HPP
  14. #define BOOST_GRAPH_SUCCESSIVE_SHORTEST_PATH_HPP
  15. #include <numeric>
  16. #include <boost/property_map/property_map.hpp>
  17. #include <boost/graph/graph_traits.hpp>
  18. #include <boost/graph/graph_concepts.hpp>
  19. #include <boost/pending/indirect_cmp.hpp>
  20. #include <boost/graph/dijkstra_shortest_paths.hpp>
  21. #include <boost/graph/properties.hpp>
  22. #include <boost/graph/iteration_macros.hpp>
  23. #include <boost/graph/detail/augment.hpp>
  24. namespace boost
  25. {
  26. namespace detail
  27. {
  28. template < class Graph, class Weight, class Distance, class Reversed >
  29. class MapReducedWeight
  30. : public put_get_helper< typename property_traits< Weight >::value_type,
  31. MapReducedWeight< Graph, Weight, Distance, Reversed > >
  32. {
  33. typedef graph_traits< Graph > gtraits;
  34. public:
  35. typedef boost::readable_property_map_tag category;
  36. typedef typename property_traits< Weight >::value_type value_type;
  37. typedef value_type reference;
  38. typedef typename gtraits::edge_descriptor key_type;
  39. MapReducedWeight(const Graph& g, Weight w, Distance d, Reversed r)
  40. : g_(g), weight_(w), distance_(d), rev_(r)
  41. {
  42. }
  43. reference operator[](key_type v) const
  44. {
  45. return get(distance_, source(v, g_)) - get(distance_, target(v, g_))
  46. + get(weight_, v);
  47. }
  48. private:
  49. const Graph& g_;
  50. Weight weight_;
  51. Distance distance_;
  52. Reversed rev_;
  53. };
  54. template < class Graph, class Weight, class Distance, class Reversed >
  55. MapReducedWeight< Graph, Weight, Distance, Reversed > make_mapReducedWeight(
  56. const Graph& g, Weight w, Distance d, Reversed r)
  57. {
  58. return MapReducedWeight< Graph, Weight, Distance, Reversed >(
  59. g, w, d, r);
  60. }
  61. } // detail
  62. template < class Graph, class Capacity, class ResidualCapacity, class Reversed,
  63. class Pred, class Weight, class Distance, class Distance2,
  64. class VertexIndex >
  65. void successive_shortest_path_nonnegative_weights(const Graph& g,
  66. typename graph_traits< Graph >::vertex_descriptor s,
  67. typename graph_traits< Graph >::vertex_descriptor t, Capacity capacity,
  68. ResidualCapacity residual_capacity, Weight weight, Reversed rev,
  69. VertexIndex index, Pred pred, Distance distance, Distance2 distance_prev)
  70. {
  71. filtered_graph< const Graph, is_residual_edge< ResidualCapacity > > gres
  72. = detail::residual_graph(g, residual_capacity);
  73. typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor;
  74. BGL_FORALL_EDGES_T(e, g, Graph)
  75. {
  76. put(residual_capacity, e, get(capacity, e));
  77. }
  78. BGL_FORALL_VERTICES_T(v, g, Graph) { put(distance_prev, v, 0); }
  79. while (true)
  80. {
  81. BGL_FORALL_VERTICES_T(v, g, Graph) { put(pred, v, edge_descriptor()); }
  82. dijkstra_shortest_paths(gres, s,
  83. weight_map(
  84. detail::make_mapReducedWeight(gres, weight, distance_prev, rev))
  85. .distance_map(distance)
  86. .vertex_index_map(index)
  87. .visitor(make_dijkstra_visitor(
  88. record_edge_predecessors(pred, on_edge_relaxed()))));
  89. if (get(pred, t) == edge_descriptor())
  90. {
  91. break;
  92. }
  93. BGL_FORALL_VERTICES_T(v, g, Graph)
  94. {
  95. put(distance_prev, v, get(distance_prev, v) + get(distance, v));
  96. }
  97. detail::augment(g, s, t, pred, residual_capacity, rev);
  98. }
  99. }
  100. // in this namespace argument dispatching tak place
  101. namespace detail
  102. {
  103. template < class Graph, class Capacity, class ResidualCapacity,
  104. class Weight, class Reversed, class Pred, class Distance,
  105. class Distance2, class VertexIndex >
  106. void successive_shortest_path_nonnegative_weights_dispatch3(const Graph& g,
  107. typename graph_traits< Graph >::vertex_descriptor s,
  108. typename graph_traits< Graph >::vertex_descriptor t, Capacity capacity,
  109. ResidualCapacity residual_capacity, Weight weight, Reversed rev,
  110. VertexIndex index, Pred pred, Distance dist, Distance2 dist_pred)
  111. {
  112. successive_shortest_path_nonnegative_weights(g, s, t, capacity,
  113. residual_capacity, weight, rev, index, pred, dist, dist_pred);
  114. }
  115. // setting default distance map
  116. template < class Graph, class Capacity, class ResidualCapacity,
  117. class Weight, class Reversed, class Pred, class Distance,
  118. class VertexIndex >
  119. void successive_shortest_path_nonnegative_weights_dispatch3(Graph& g,
  120. typename graph_traits< Graph >::vertex_descriptor s,
  121. typename graph_traits< Graph >::vertex_descriptor t, Capacity capacity,
  122. ResidualCapacity residual_capacity, Weight weight, Reversed rev,
  123. VertexIndex index, Pred pred, Distance dist, param_not_found)
  124. {
  125. typedef typename property_traits< Weight >::value_type D;
  126. std::vector< D > d_map(num_vertices(g));
  127. successive_shortest_path_nonnegative_weights(g, s, t, capacity,
  128. residual_capacity, weight, rev, index, pred, dist,
  129. make_iterator_property_map(d_map.begin(), index));
  130. }
  131. template < class Graph, class P, class T, class R, class Capacity,
  132. class ResidualCapacity, class Weight, class Reversed, class Pred,
  133. class Distance, class VertexIndex >
  134. void successive_shortest_path_nonnegative_weights_dispatch2(Graph& g,
  135. typename graph_traits< Graph >::vertex_descriptor s,
  136. typename graph_traits< Graph >::vertex_descriptor t, Capacity capacity,
  137. ResidualCapacity residual_capacity, Weight weight, Reversed rev,
  138. VertexIndex index, Pred pred, Distance dist,
  139. const bgl_named_params< P, T, R >& params)
  140. {
  141. successive_shortest_path_nonnegative_weights_dispatch3(g, s, t,
  142. capacity, residual_capacity, weight, rev, index, pred, dist,
  143. get_param(params, vertex_distance2));
  144. }
  145. // setting default distance map
  146. template < class Graph, class P, class T, class R, class Capacity,
  147. class ResidualCapacity, class Weight, class Reversed, class Pred,
  148. class VertexIndex >
  149. void successive_shortest_path_nonnegative_weights_dispatch2(Graph& g,
  150. typename graph_traits< Graph >::vertex_descriptor s,
  151. typename graph_traits< Graph >::vertex_descriptor t, Capacity capacity,
  152. ResidualCapacity residual_capacity, Weight weight, Reversed rev,
  153. VertexIndex index, Pred pred, param_not_found,
  154. const bgl_named_params< P, T, R >& params)
  155. {
  156. typedef typename property_traits< Weight >::value_type D;
  157. std::vector< D > d_map(num_vertices(g));
  158. successive_shortest_path_nonnegative_weights_dispatch3(g, s, t,
  159. capacity, residual_capacity, weight, rev, index, pred,
  160. make_iterator_property_map(d_map.begin(), index),
  161. get_param(params, vertex_distance2));
  162. }
  163. template < class Graph, class P, class T, class R, class Capacity,
  164. class ResidualCapacity, class Weight, class Reversed, class Pred,
  165. class VertexIndex >
  166. void successive_shortest_path_nonnegative_weights_dispatch1(Graph& g,
  167. typename graph_traits< Graph >::vertex_descriptor s,
  168. typename graph_traits< Graph >::vertex_descriptor t, Capacity capacity,
  169. ResidualCapacity residual_capacity, Weight weight, Reversed rev,
  170. VertexIndex index, Pred pred, const bgl_named_params< P, T, R >& params)
  171. {
  172. successive_shortest_path_nonnegative_weights_dispatch2(g, s, t,
  173. capacity, residual_capacity, weight, rev, index, pred,
  174. get_param(params, vertex_distance), params);
  175. }
  176. // setting default predecessors map
  177. template < class Graph, class P, class T, class R, class Capacity,
  178. class ResidualCapacity, class Weight, class Reversed,
  179. class VertexIndex >
  180. void successive_shortest_path_nonnegative_weights_dispatch1(Graph& g,
  181. typename graph_traits< Graph >::vertex_descriptor s,
  182. typename graph_traits< Graph >::vertex_descriptor t, Capacity capacity,
  183. ResidualCapacity residual_capacity, Weight weight, Reversed rev,
  184. VertexIndex index, param_not_found,
  185. const bgl_named_params< P, T, R >& params)
  186. {
  187. typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor;
  188. std::vector< edge_descriptor > pred_vec(num_vertices(g));
  189. successive_shortest_path_nonnegative_weights_dispatch2(g, s, t,
  190. capacity, residual_capacity, weight, rev, index,
  191. make_iterator_property_map(pred_vec.begin(), index),
  192. get_param(params, vertex_distance), params);
  193. }
  194. } // detail
  195. template < class Graph, class P, class T, class R >
  196. void successive_shortest_path_nonnegative_weights(Graph& g,
  197. typename graph_traits< Graph >::vertex_descriptor s,
  198. typename graph_traits< Graph >::vertex_descriptor t,
  199. const bgl_named_params< P, T, R >& params)
  200. {
  201. return detail::successive_shortest_path_nonnegative_weights_dispatch1(g, s,
  202. t,
  203. choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity),
  204. choose_pmap(get_param(params, edge_residual_capacity), g,
  205. edge_residual_capacity),
  206. choose_const_pmap(get_param(params, edge_weight), g, edge_weight),
  207. choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse),
  208. choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
  209. get_param(params, vertex_predecessor), params);
  210. }
  211. template < class Graph >
  212. void successive_shortest_path_nonnegative_weights(Graph& g,
  213. typename graph_traits< Graph >::vertex_descriptor s,
  214. typename graph_traits< Graph >::vertex_descriptor t)
  215. {
  216. bgl_named_params< int, buffer_param_t > params(0);
  217. successive_shortest_path_nonnegative_weights(g, s, t, params);
  218. }
  219. } // boost
  220. #endif /* BOOST_GRAPH_SUCCESSIVE_SHORTEST_PATH_HPP */