williamr@2
|
1 |
//=======================================================================
|
williamr@2
|
2 |
// Copyright 2000 University of Notre Dame.
|
williamr@2
|
3 |
// Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee
|
williamr@2
|
4 |
//
|
williamr@2
|
5 |
// Distributed under the Boost Software License, Version 1.0. (See
|
williamr@2
|
6 |
// accompanying file LICENSE_1_0.txt or copy at
|
williamr@2
|
7 |
// http://www.boost.org/LICENSE_1_0.txt)
|
williamr@2
|
8 |
//=======================================================================
|
williamr@2
|
9 |
|
williamr@2
|
10 |
#ifndef EDMUNDS_KARP_MAX_FLOW_HPP
|
williamr@2
|
11 |
#define EDMUNDS_KARP_MAX_FLOW_HPP
|
williamr@2
|
12 |
|
williamr@2
|
13 |
#include <boost/config.hpp>
|
williamr@2
|
14 |
#include <vector>
|
williamr@2
|
15 |
#include <algorithm> // for std::min and std::max
|
williamr@2
|
16 |
#include <boost/config.hpp>
|
williamr@2
|
17 |
#include <boost/pending/queue.hpp>
|
williamr@2
|
18 |
#include <boost/property_map.hpp>
|
williamr@2
|
19 |
#include <boost/graph/graph_traits.hpp>
|
williamr@2
|
20 |
#include <boost/graph/properties.hpp>
|
williamr@2
|
21 |
#include <boost/graph/filtered_graph.hpp>
|
williamr@2
|
22 |
#include <boost/graph/breadth_first_search.hpp>
|
williamr@2
|
23 |
|
williamr@2
|
24 |
namespace boost {
|
williamr@2
|
25 |
|
williamr@2
|
26 |
// The "labeling" algorithm from "Network Flows" by Ahuja, Magnanti,
|
williamr@2
|
27 |
// Orlin. I think this is the same as or very similar to the original
|
williamr@2
|
28 |
// Edmunds-Karp algorithm. This solves the maximum flow problem.
|
williamr@2
|
29 |
|
williamr@2
|
30 |
namespace detail {
|
williamr@2
|
31 |
|
williamr@2
|
32 |
template <class Graph, class ResCapMap>
|
williamr@2
|
33 |
filtered_graph<Graph, is_residual_edge<ResCapMap> >
|
williamr@2
|
34 |
residual_graph(Graph& g, ResCapMap residual_capacity) {
|
williamr@2
|
35 |
return filtered_graph<Graph, is_residual_edge<ResCapMap> >
|
williamr@2
|
36 |
(g, is_residual_edge<ResCapMap>(residual_capacity));
|
williamr@2
|
37 |
}
|
williamr@2
|
38 |
|
williamr@2
|
39 |
template <class Graph, class PredEdgeMap, class ResCapMap,
|
williamr@2
|
40 |
class RevEdgeMap>
|
williamr@2
|
41 |
inline void
|
williamr@2
|
42 |
augment(Graph& g,
|
williamr@2
|
43 |
typename graph_traits<Graph>::vertex_descriptor src,
|
williamr@2
|
44 |
typename graph_traits<Graph>::vertex_descriptor sink,
|
williamr@2
|
45 |
PredEdgeMap p,
|
williamr@2
|
46 |
ResCapMap residual_capacity,
|
williamr@2
|
47 |
RevEdgeMap reverse_edge)
|
williamr@2
|
48 |
{
|
williamr@2
|
49 |
typename graph_traits<Graph>::edge_descriptor e;
|
williamr@2
|
50 |
typename graph_traits<Graph>::vertex_descriptor u;
|
williamr@2
|
51 |
typedef typename property_traits<ResCapMap>::value_type FlowValue;
|
williamr@2
|
52 |
|
williamr@2
|
53 |
// find minimum residual capacity along the augmenting path
|
williamr@2
|
54 |
FlowValue delta = (std::numeric_limits<FlowValue>::max)();
|
williamr@2
|
55 |
e = p[sink];
|
williamr@2
|
56 |
do {
|
williamr@2
|
57 |
BOOST_USING_STD_MIN();
|
williamr@2
|
58 |
delta = min BOOST_PREVENT_MACRO_SUBSTITUTION(delta, residual_capacity[e]);
|
williamr@2
|
59 |
u = source(e, g);
|
williamr@2
|
60 |
e = p[u];
|
williamr@2
|
61 |
} while (u != src);
|
williamr@2
|
62 |
|
williamr@2
|
63 |
// push delta units of flow along the augmenting path
|
williamr@2
|
64 |
e = p[sink];
|
williamr@2
|
65 |
do {
|
williamr@2
|
66 |
residual_capacity[e] -= delta;
|
williamr@2
|
67 |
residual_capacity[reverse_edge[e]] += delta;
|
williamr@2
|
68 |
u = source(e, g);
|
williamr@2
|
69 |
e = p[u];
|
williamr@2
|
70 |
} while (u != src);
|
williamr@2
|
71 |
}
|
williamr@2
|
72 |
|
williamr@2
|
73 |
} // namespace detail
|
williamr@2
|
74 |
|
williamr@2
|
75 |
template <class Graph,
|
williamr@2
|
76 |
class CapacityEdgeMap, class ResidualCapacityEdgeMap,
|
williamr@2
|
77 |
class ReverseEdgeMap, class ColorMap, class PredEdgeMap>
|
williamr@2
|
78 |
typename property_traits<CapacityEdgeMap>::value_type
|
williamr@2
|
79 |
edmunds_karp_max_flow
|
williamr@2
|
80 |
(Graph& g,
|
williamr@2
|
81 |
typename graph_traits<Graph>::vertex_descriptor src,
|
williamr@2
|
82 |
typename graph_traits<Graph>::vertex_descriptor sink,
|
williamr@2
|
83 |
CapacityEdgeMap cap,
|
williamr@2
|
84 |
ResidualCapacityEdgeMap res,
|
williamr@2
|
85 |
ReverseEdgeMap rev,
|
williamr@2
|
86 |
ColorMap color,
|
williamr@2
|
87 |
PredEdgeMap pred)
|
williamr@2
|
88 |
{
|
williamr@2
|
89 |
typedef typename graph_traits<Graph>::vertex_descriptor vertex_t;
|
williamr@2
|
90 |
typedef typename property_traits<ColorMap>::value_type ColorValue;
|
williamr@2
|
91 |
typedef color_traits<ColorValue> Color;
|
williamr@2
|
92 |
|
williamr@2
|
93 |
typename graph_traits<Graph>::vertex_iterator u_iter, u_end;
|
williamr@2
|
94 |
typename graph_traits<Graph>::out_edge_iterator ei, e_end;
|
williamr@2
|
95 |
for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter)
|
williamr@2
|
96 |
for (tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei)
|
williamr@2
|
97 |
res[*ei] = cap[*ei];
|
williamr@2
|
98 |
|
williamr@2
|
99 |
color[sink] = Color::gray();
|
williamr@2
|
100 |
while (color[sink] != Color::white()) {
|
williamr@2
|
101 |
boost::queue<vertex_t> Q;
|
williamr@2
|
102 |
breadth_first_search
|
williamr@2
|
103 |
(detail::residual_graph(g, res), src, Q,
|
williamr@2
|
104 |
make_bfs_visitor(record_edge_predecessors(pred, on_tree_edge())),
|
williamr@2
|
105 |
color);
|
williamr@2
|
106 |
if (color[sink] != Color::white())
|
williamr@2
|
107 |
detail::augment(g, src, sink, pred, res, rev);
|
williamr@2
|
108 |
} // while
|
williamr@2
|
109 |
|
williamr@2
|
110 |
typename property_traits<CapacityEdgeMap>::value_type flow = 0;
|
williamr@2
|
111 |
for (tie(ei, e_end) = out_edges(src, g); ei != e_end; ++ei)
|
williamr@2
|
112 |
flow += (cap[*ei] - res[*ei]);
|
williamr@2
|
113 |
return flow;
|
williamr@2
|
114 |
} // edmunds_karp_max_flow()
|
williamr@2
|
115 |
|
williamr@2
|
116 |
namespace detail {
|
williamr@2
|
117 |
//-------------------------------------------------------------------------
|
williamr@2
|
118 |
// Handle default for color property map
|
williamr@2
|
119 |
|
williamr@2
|
120 |
// use of class here is a VC++ workaround
|
williamr@2
|
121 |
template <class ColorMap>
|
williamr@2
|
122 |
struct edmunds_karp_dispatch2 {
|
williamr@2
|
123 |
template <class Graph, class PredMap, class P, class T, class R>
|
williamr@2
|
124 |
static typename edge_capacity_value<Graph, P, T, R>::type
|
williamr@2
|
125 |
apply
|
williamr@2
|
126 |
(Graph& g,
|
williamr@2
|
127 |
typename graph_traits<Graph>::vertex_descriptor src,
|
williamr@2
|
128 |
typename graph_traits<Graph>::vertex_descriptor sink,
|
williamr@2
|
129 |
PredMap pred,
|
williamr@2
|
130 |
const bgl_named_params<P, T, R>& params,
|
williamr@2
|
131 |
ColorMap color)
|
williamr@2
|
132 |
{
|
williamr@2
|
133 |
return edmunds_karp_max_flow
|
williamr@2
|
134 |
(g, src, sink,
|
williamr@2
|
135 |
choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity),
|
williamr@2
|
136 |
choose_pmap(get_param(params, edge_residual_capacity),
|
williamr@2
|
137 |
g, edge_residual_capacity),
|
williamr@2
|
138 |
choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse),
|
williamr@2
|
139 |
color, pred);
|
williamr@2
|
140 |
}
|
williamr@2
|
141 |
};
|
williamr@2
|
142 |
template<>
|
williamr@2
|
143 |
struct edmunds_karp_dispatch2<detail::error_property_not_found> {
|
williamr@2
|
144 |
template <class Graph, class PredMap, class P, class T, class R>
|
williamr@2
|
145 |
static typename edge_capacity_value<Graph, P, T, R>::type
|
williamr@2
|
146 |
apply
|
williamr@2
|
147 |
(Graph& g,
|
williamr@2
|
148 |
typename graph_traits<Graph>::vertex_descriptor src,
|
williamr@2
|
149 |
typename graph_traits<Graph>::vertex_descriptor sink,
|
williamr@2
|
150 |
PredMap pred,
|
williamr@2
|
151 |
const bgl_named_params<P, T, R>& params,
|
williamr@2
|
152 |
detail::error_property_not_found)
|
williamr@2
|
153 |
{
|
williamr@2
|
154 |
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
williamr@2
|
155 |
typedef typename graph_traits<Graph>::vertices_size_type size_type;
|
williamr@2
|
156 |
size_type n = is_default_param(get_param(params, vertex_color)) ?
|
williamr@2
|
157 |
num_vertices(g) : 1;
|
williamr@2
|
158 |
std::vector<default_color_type> color_vec(n);
|
williamr@2
|
159 |
return edmunds_karp_max_flow
|
williamr@2
|
160 |
(g, src, sink,
|
williamr@2
|
161 |
choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity),
|
williamr@2
|
162 |
choose_pmap(get_param(params, edge_residual_capacity),
|
williamr@2
|
163 |
g, edge_residual_capacity),
|
williamr@2
|
164 |
choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse),
|
williamr@2
|
165 |
make_iterator_property_map(color_vec.begin(), choose_const_pmap
|
williamr@2
|
166 |
(get_param(params, vertex_index),
|
williamr@2
|
167 |
g, vertex_index), color_vec[0]),
|
williamr@2
|
168 |
pred);
|
williamr@2
|
169 |
}
|
williamr@2
|
170 |
};
|
williamr@2
|
171 |
|
williamr@2
|
172 |
//-------------------------------------------------------------------------
|
williamr@2
|
173 |
// Handle default for predecessor property map
|
williamr@2
|
174 |
|
williamr@2
|
175 |
// use of class here is a VC++ workaround
|
williamr@2
|
176 |
template <class PredMap>
|
williamr@2
|
177 |
struct edmunds_karp_dispatch1 {
|
williamr@2
|
178 |
template <class Graph, class P, class T, class R>
|
williamr@2
|
179 |
static typename edge_capacity_value<Graph, P, T, R>::type
|
williamr@2
|
180 |
apply(Graph& g,
|
williamr@2
|
181 |
typename graph_traits<Graph>::vertex_descriptor src,
|
williamr@2
|
182 |
typename graph_traits<Graph>::vertex_descriptor sink,
|
williamr@2
|
183 |
const bgl_named_params<P, T, R>& params,
|
williamr@2
|
184 |
PredMap pred)
|
williamr@2
|
185 |
{
|
williamr@2
|
186 |
typedef typename property_value< bgl_named_params<P,T,R>, vertex_color_t>::type C;
|
williamr@2
|
187 |
return edmunds_karp_dispatch2<C>::apply
|
williamr@2
|
188 |
(g, src, sink, pred, params, get_param(params, vertex_color));
|
williamr@2
|
189 |
}
|
williamr@2
|
190 |
};
|
williamr@2
|
191 |
template<>
|
williamr@2
|
192 |
struct edmunds_karp_dispatch1<detail::error_property_not_found> {
|
williamr@2
|
193 |
|
williamr@2
|
194 |
template <class Graph, class P, class T, class R>
|
williamr@2
|
195 |
static typename edge_capacity_value<Graph, P, T, R>::type
|
williamr@2
|
196 |
apply
|
williamr@2
|
197 |
(Graph& g,
|
williamr@2
|
198 |
typename graph_traits<Graph>::vertex_descriptor src,
|
williamr@2
|
199 |
typename graph_traits<Graph>::vertex_descriptor sink,
|
williamr@2
|
200 |
const bgl_named_params<P, T, R>& params,
|
williamr@2
|
201 |
detail::error_property_not_found)
|
williamr@2
|
202 |
{
|
williamr@2
|
203 |
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
williamr@2
|
204 |
typedef typename graph_traits<Graph>::vertices_size_type size_type;
|
williamr@2
|
205 |
size_type n = is_default_param(get_param(params, vertex_predecessor)) ?
|
williamr@2
|
206 |
num_vertices(g) : 1;
|
williamr@2
|
207 |
std::vector<edge_descriptor> pred_vec(n);
|
williamr@2
|
208 |
|
williamr@2
|
209 |
typedef typename property_value< bgl_named_params<P,T,R>, vertex_color_t>::type C;
|
williamr@2
|
210 |
return edmunds_karp_dispatch2<C>::apply
|
williamr@2
|
211 |
(g, src, sink,
|
williamr@2
|
212 |
make_iterator_property_map(pred_vec.begin(), choose_const_pmap
|
williamr@2
|
213 |
(get_param(params, vertex_index),
|
williamr@2
|
214 |
g, vertex_index), pred_vec[0]),
|
williamr@2
|
215 |
params,
|
williamr@2
|
216 |
get_param(params, vertex_color));
|
williamr@2
|
217 |
}
|
williamr@2
|
218 |
};
|
williamr@2
|
219 |
|
williamr@2
|
220 |
} // namespace detail
|
williamr@2
|
221 |
|
williamr@2
|
222 |
template <class Graph, class P, class T, class R>
|
williamr@2
|
223 |
typename detail::edge_capacity_value<Graph, P, T, R>::type
|
williamr@2
|
224 |
edmunds_karp_max_flow
|
williamr@2
|
225 |
(Graph& g,
|
williamr@2
|
226 |
typename graph_traits<Graph>::vertex_descriptor src,
|
williamr@2
|
227 |
typename graph_traits<Graph>::vertex_descriptor sink,
|
williamr@2
|
228 |
const bgl_named_params<P, T, R>& params)
|
williamr@2
|
229 |
{
|
williamr@2
|
230 |
typedef typename property_value< bgl_named_params<P,T,R>, vertex_predecessor_t>::type Pred;
|
williamr@2
|
231 |
return detail::edmunds_karp_dispatch1<Pred>::apply
|
williamr@2
|
232 |
(g, src, sink, params, get_param(params, vertex_predecessor));
|
williamr@2
|
233 |
}
|
williamr@2
|
234 |
|
williamr@2
|
235 |
template <class Graph>
|
williamr@2
|
236 |
typename property_traits<
|
williamr@2
|
237 |
typename property_map<Graph, edge_capacity_t>::const_type
|
williamr@2
|
238 |
>::value_type
|
williamr@2
|
239 |
edmunds_karp_max_flow
|
williamr@2
|
240 |
(Graph& g,
|
williamr@2
|
241 |
typename graph_traits<Graph>::vertex_descriptor src,
|
williamr@2
|
242 |
typename graph_traits<Graph>::vertex_descriptor sink)
|
williamr@2
|
243 |
{
|
williamr@2
|
244 |
bgl_named_params<int, buffer_param_t> params(0);
|
williamr@2
|
245 |
return edmunds_karp_max_flow(g, src, sink, params);
|
williamr@2
|
246 |
}
|
williamr@2
|
247 |
|
williamr@2
|
248 |
} // namespace boost
|
williamr@2
|
249 |
|
williamr@2
|
250 |
#endif // EDMUNDS_KARP_MAX_FLOW_HPP
|