• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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