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