successive_shortest_path_nonnegative_weights.hpp 10 KB

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