| 1 | //======================================================================= |
|---|
| 2 | // Copyright 2000 University of Notre Dame. |
|---|
| 3 | // Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee |
|---|
| 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 | #ifndef BOOST_PUSH_RELABEL_MAX_FLOW_HPP |
|---|
| 11 | #define BOOST_PUSH_RELABEL_MAX_FLOW_HPP |
|---|
| 12 | |
|---|
| 13 | #include <boost/config.hpp> |
|---|
| 14 | #include <cassert> |
|---|
| 15 | #include <vector> |
|---|
| 16 | #include <list> |
|---|
| 17 | #include <iosfwd> |
|---|
| 18 | #include <algorithm> // for std::min and std::max |
|---|
| 19 | |
|---|
| 20 | #include <boost/pending/queue.hpp> |
|---|
| 21 | #include <boost/limits.hpp> |
|---|
| 22 | #include <boost/graph/graph_concepts.hpp> |
|---|
| 23 | #include <boost/graph/named_function_params.hpp> |
|---|
| 24 | |
|---|
| 25 | namespace boost { |
|---|
| 26 | |
|---|
| 27 | namespace detail { |
|---|
| 28 | |
|---|
| 29 | // This implementation is based on Goldberg's |
|---|
| 30 | // "On Implementing Push-Relabel Method for the Maximum Flow Problem" |
|---|
| 31 | // by B.V. Cherkassky and A.V. Goldberg, IPCO '95, pp. 157--171 |
|---|
| 32 | // and on the h_prf.c and hi_pr.c code written by the above authors. |
|---|
| 33 | |
|---|
| 34 | // This implements the highest-label version of the push-relabel method |
|---|
| 35 | // with the global relabeling and gap relabeling heuristics. |
|---|
| 36 | |
|---|
| 37 | // The terms "rank", "distance", "height" are synonyms in |
|---|
| 38 | // Goldberg's implementation, paper and in the CLR. A "layer" is a |
|---|
| 39 | // group of vertices with the same distance. The vertices in each |
|---|
| 40 | // layer are categorized as active or inactive. An active vertex |
|---|
| 41 | // has positive excess flow and its distance is less than n (it is |
|---|
| 42 | // not blocked). |
|---|
| 43 | |
|---|
| 44 | template <class Vertex> |
|---|
| 45 | struct preflow_layer { |
|---|
| 46 | std::list<Vertex> active_vertices; |
|---|
| 47 | std::list<Vertex> inactive_vertices; |
|---|
| 48 | }; |
|---|
| 49 | |
|---|
| 50 | template <class Graph, |
|---|
| 51 | class EdgeCapacityMap, // integer value type |
|---|
| 52 | class ResidualCapacityEdgeMap, |
|---|
| 53 | class ReverseEdgeMap, |
|---|
| 54 | class VertexIndexMap, // vertex_descriptor -> integer |
|---|
| 55 | class FlowValue> |
|---|
| 56 | class push_relabel |
|---|
| 57 | { |
|---|
| 58 | public: |
|---|
| 59 | typedef graph_traits<Graph> Traits; |
|---|
| 60 | typedef typename Traits::vertex_descriptor vertex_descriptor; |
|---|
| 61 | typedef typename Traits::edge_descriptor edge_descriptor; |
|---|
| 62 | typedef typename Traits::vertex_iterator vertex_iterator; |
|---|
| 63 | typedef typename Traits::out_edge_iterator out_edge_iterator; |
|---|
| 64 | typedef typename Traits::vertices_size_type vertices_size_type; |
|---|
| 65 | typedef typename Traits::edges_size_type edges_size_type; |
|---|
| 66 | |
|---|
| 67 | typedef preflow_layer<vertex_descriptor> Layer; |
|---|
| 68 | typedef std::vector< Layer > LayerArray; |
|---|
| 69 | typedef typename LayerArray::iterator layer_iterator; |
|---|
| 70 | typedef typename LayerArray::size_type distance_size_type; |
|---|
| 71 | |
|---|
| 72 | typedef color_traits<default_color_type> ColorTraits; |
|---|
| 73 | |
|---|
| 74 | //======================================================================= |
|---|
| 75 | // Some helper predicates |
|---|
| 76 | |
|---|
| 77 | inline bool is_admissible(vertex_descriptor u, vertex_descriptor v) { |
|---|
| 78 | return distance[u] == distance[v] + 1; |
|---|
| 79 | } |
|---|
| 80 | inline bool is_residual_edge(edge_descriptor a) { |
|---|
| 81 | return 0 < residual_capacity[a]; |
|---|
| 82 | } |
|---|
| 83 | inline bool is_saturated(edge_descriptor a) { |
|---|
| 84 | return residual_capacity[a] == 0; |
|---|
| 85 | } |
|---|
| 86 | |
|---|
| 87 | //======================================================================= |
|---|
| 88 | // Layer List Management Functions |
|---|
| 89 | |
|---|
| 90 | typedef typename std::list<vertex_descriptor>::iterator list_iterator; |
|---|
| 91 | |
|---|
| 92 | void add_to_active_list(vertex_descriptor u, Layer& layer) { |
|---|
| 93 | BOOST_USING_STD_MIN(); |
|---|
| 94 | BOOST_USING_STD_MAX(); |
|---|
| 95 | layer.active_vertices.push_front(u); |
|---|
| 96 | max_active = max BOOST_PREVENT_MACRO_SUBSTITUTION(distance[u], max_active); |
|---|
| 97 | min_active = min BOOST_PREVENT_MACRO_SUBSTITUTION(distance[u], min_active); |
|---|
| 98 | layer_list_ptr[u] = layer.active_vertices.begin(); |
|---|
| 99 | } |
|---|
| 100 | void remove_from_active_list(vertex_descriptor u) { |
|---|
| 101 | layers[distance[u]].active_vertices.erase(layer_list_ptr[u]); |
|---|
| 102 | } |
|---|
| 103 | |
|---|
| 104 | void add_to_inactive_list(vertex_descriptor u, Layer& layer) { |
|---|
| 105 | layer.inactive_vertices.push_front(u); |
|---|
| 106 | layer_list_ptr[u] = layer.inactive_vertices.begin(); |
|---|
| 107 | } |
|---|
| 108 | void remove_from_inactive_list(vertex_descriptor u) { |
|---|
| 109 | layers[distance[u]].inactive_vertices.erase(layer_list_ptr[u]); |
|---|
| 110 | } |
|---|
| 111 | |
|---|
| 112 | //======================================================================= |
|---|
| 113 | // initialization |
|---|
| 114 | push_relabel(Graph& g_, |
|---|
| 115 | EdgeCapacityMap cap, |
|---|
| 116 | ResidualCapacityEdgeMap res, |
|---|
| 117 | ReverseEdgeMap rev, |
|---|
| 118 | vertex_descriptor src_, |
|---|
| 119 | vertex_descriptor sink_, |
|---|
| 120 | VertexIndexMap idx) |
|---|
| 121 | : g(g_), n(num_vertices(g_)), capacity(cap), src(src_), sink(sink_), |
|---|
| 122 | index(idx), |
|---|
| 123 | excess_flow(num_vertices(g_)), |
|---|
| 124 | current(num_vertices(g_), out_edges(*vertices(g_).first, g_).second), |
|---|
| 125 | distance(num_vertices(g_)), |
|---|
| 126 | color(num_vertices(g_)), |
|---|
| 127 | reverse_edge(rev), |
|---|
| 128 | residual_capacity(res), |
|---|
| 129 | layers(num_vertices(g_)), |
|---|
| 130 | layer_list_ptr(num_vertices(g_), |
|---|
| 131 | layers.front().inactive_vertices.end()), |
|---|
| 132 | push_count(0), update_count(0), relabel_count(0), |
|---|
| 133 | gap_count(0), gap_node_count(0), |
|---|
| 134 | work_since_last_update(0) |
|---|
| 135 | { |
|---|
| 136 | vertex_iterator u_iter, u_end; |
|---|
| 137 | // Don't count the reverse edges |
|---|
| 138 | edges_size_type m = num_edges(g) / 2; |
|---|
| 139 | nm = alpha() * n + m; |
|---|
| 140 | |
|---|
| 141 | // Initialize flow to zero which means initializing |
|---|
| 142 | // the residual capacity to equal the capacity. |
|---|
| 143 | out_edge_iterator ei, e_end; |
|---|
| 144 | for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) |
|---|
| 145 | for (tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei) { |
|---|
| 146 | residual_capacity[*ei] = capacity[*ei]; |
|---|
| 147 | } |
|---|
| 148 | |
|---|
| 149 | for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) { |
|---|
| 150 | vertex_descriptor u = *u_iter; |
|---|
| 151 | excess_flow[u] = 0; |
|---|
| 152 | current[u] = out_edges(u, g).first; |
|---|
| 153 | } |
|---|
| 154 | |
|---|
| 155 | bool overflow_detected = false; |
|---|
| 156 | FlowValue test_excess = 0; |
|---|
| 157 | |
|---|
| 158 | out_edge_iterator a_iter, a_end; |
|---|
| 159 | for (tie(a_iter, a_end) = out_edges(src, g); a_iter != a_end; ++a_iter) |
|---|
| 160 | if (target(*a_iter, g) != src) |
|---|
| 161 | test_excess += residual_capacity[*a_iter]; |
|---|
| 162 | if (test_excess > (std::numeric_limits<FlowValue>::max)()) |
|---|
| 163 | overflow_detected = true; |
|---|
| 164 | |
|---|
| 165 | if (overflow_detected) |
|---|
| 166 | excess_flow[src] = (std::numeric_limits<FlowValue>::max)(); |
|---|
| 167 | else { |
|---|
| 168 | excess_flow[src] = 0; |
|---|
| 169 | for (tie(a_iter, a_end) = out_edges(src, g); |
|---|
| 170 | a_iter != a_end; ++a_iter) { |
|---|
| 171 | edge_descriptor a = *a_iter; |
|---|
| 172 | if (target(a, g) != src) { |
|---|
| 173 | ++push_count; |
|---|
| 174 | FlowValue delta = residual_capacity[a]; |
|---|
| 175 | residual_capacity[a] -= delta; |
|---|
| 176 | residual_capacity[reverse_edge[a]] += delta; |
|---|
| 177 | excess_flow[target(a, g)] += delta; |
|---|
| 178 | } |
|---|
| 179 | } |
|---|
| 180 | } |
|---|
| 181 | max_distance = num_vertices(g) - 1; |
|---|
| 182 | max_active = 0; |
|---|
| 183 | min_active = n; |
|---|
| 184 | |
|---|
| 185 | for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) { |
|---|
| 186 | vertex_descriptor u = *u_iter; |
|---|
| 187 | if (u == sink) { |
|---|
| 188 | distance[u] = 0; |
|---|
| 189 | continue; |
|---|
| 190 | } else if (u == src && !overflow_detected) |
|---|
| 191 | distance[u] = n; |
|---|
| 192 | else |
|---|
| 193 | distance[u] = 1; |
|---|
| 194 | |
|---|
| 195 | if (excess_flow[u] > 0) |
|---|
| 196 | add_to_active_list(u, layers[1]); |
|---|
| 197 | else if (distance[u] < n) |
|---|
| 198 | add_to_inactive_list(u, layers[1]); |
|---|
| 199 | } |
|---|
| 200 | |
|---|
| 201 | } // push_relabel constructor |
|---|
| 202 | |
|---|
| 203 | //======================================================================= |
|---|
| 204 | // This is a breadth-first search over the residual graph |
|---|
| 205 | // (well, actually the reverse of the residual graph). |
|---|
| 206 | // Would be cool to have a graph view adaptor for hiding certain |
|---|
| 207 | // edges, like the saturated (non-residual) edges in this case. |
|---|
| 208 | // Goldberg's implementation abused "distance" for the coloring. |
|---|
| 209 | void global_distance_update() |
|---|
| 210 | { |
|---|
| 211 | BOOST_USING_STD_MAX(); |
|---|
| 212 | ++update_count; |
|---|
| 213 | vertex_iterator u_iter, u_end; |
|---|
| 214 | for (tie(u_iter,u_end) = vertices(g); u_iter != u_end; ++u_iter) { |
|---|
| 215 | color[*u_iter] = ColorTraits::white(); |
|---|
| 216 | distance[*u_iter] = n; |
|---|
| 217 | } |
|---|
| 218 | color[sink] = ColorTraits::gray(); |
|---|
| 219 | distance[sink] = 0; |
|---|
| 220 | |
|---|
| 221 | for (distance_size_type l = 0; l <= max_distance; ++l) { |
|---|
| 222 | layers[l].active_vertices.clear(); |
|---|
| 223 | layers[l].inactive_vertices.clear(); |
|---|
| 224 | } |
|---|
| 225 | |
|---|
| 226 | max_distance = max_active = 0; |
|---|
| 227 | min_active = n; |
|---|
| 228 | |
|---|
| 229 | Q.push(sink); |
|---|
| 230 | while (! Q.empty()) { |
|---|
| 231 | vertex_descriptor u = Q.top(); |
|---|
| 232 | Q.pop(); |
|---|
| 233 | distance_size_type d_v = distance[u] + 1; |
|---|
| 234 | |
|---|
| 235 | out_edge_iterator ai, a_end; |
|---|
| 236 | for (tie(ai, a_end) = out_edges(u, g); ai != a_end; ++ai) { |
|---|
| 237 | edge_descriptor a = *ai; |
|---|
| 238 | vertex_descriptor v = target(a, g); |
|---|
| 239 | if (color[v] == ColorTraits::white() |
|---|
| 240 | && is_residual_edge(reverse_edge[a])) { |
|---|
| 241 | distance[v] = d_v; |
|---|
| 242 | color[v] = ColorTraits::gray(); |
|---|
| 243 | current[v] = out_edges(v, g).first; |
|---|
| 244 | max_distance = max BOOST_PREVENT_MACRO_SUBSTITUTION(d_v, max_distance); |
|---|
| 245 | |
|---|
| 246 | if (excess_flow[v] > 0) |
|---|
| 247 | add_to_active_list(v, layers[d_v]); |
|---|
| 248 | else |
|---|
| 249 | add_to_inactive_list(v, layers[d_v]); |
|---|
| 250 | |
|---|
| 251 | Q.push(v); |
|---|
| 252 | } |
|---|
| 253 | } |
|---|
| 254 | } |
|---|
| 255 | } // global_distance_update() |
|---|
| 256 | |
|---|
| 257 | //======================================================================= |
|---|
| 258 | // This function is called "push" in Goldberg's h_prf implementation, |
|---|
| 259 | // but it is called "discharge" in the paper and in hi_pr.c. |
|---|
| 260 | void discharge(vertex_descriptor u) |
|---|
| 261 | { |
|---|
| 262 | assert(excess_flow[u] > 0); |
|---|
| 263 | while (1) { |
|---|
| 264 | out_edge_iterator ai, ai_end; |
|---|
| 265 | for (ai = current[u], ai_end = out_edges(u, g).second; |
|---|
| 266 | ai != ai_end; ++ai) { |
|---|
| 267 | edge_descriptor a = *ai; |
|---|
| 268 | if (is_residual_edge(a)) { |
|---|
| 269 | vertex_descriptor v = target(a, g); |
|---|
| 270 | if (is_admissible(u, v)) { |
|---|
| 271 | ++push_count; |
|---|
| 272 | if (v != sink && excess_flow[v] == 0) { |
|---|
| 273 | remove_from_inactive_list(v); |
|---|
| 274 | add_to_active_list(v, layers[distance[v]]); |
|---|
| 275 | } |
|---|
| 276 | push_flow(a); |
|---|
| 277 | if (excess_flow[u] == 0) |
|---|
| 278 | break; |
|---|
| 279 | } |
|---|
| 280 | } |
|---|
| 281 | } // for out_edges of i starting from current |
|---|
| 282 | |
|---|
| 283 | Layer& layer = layers[distance[u]]; |
|---|
| 284 | distance_size_type du = distance[u]; |
|---|
| 285 | |
|---|
| 286 | if (ai == ai_end) { // i must be relabeled |
|---|
| 287 | relabel_distance(u); |
|---|
| 288 | if (layer.active_vertices.empty() |
|---|
| 289 | && layer.inactive_vertices.empty()) |
|---|
| 290 | gap(du); |
|---|
| 291 | if (distance[u] == n) |
|---|
| 292 | break; |
|---|
| 293 | } else { // i is no longer active |
|---|
| 294 | current[u] = ai; |
|---|
| 295 | add_to_inactive_list(u, layer); |
|---|
| 296 | break; |
|---|
| 297 | } |
|---|
| 298 | } // while (1) |
|---|
| 299 | } // discharge() |
|---|
| 300 | |
|---|
| 301 | //======================================================================= |
|---|
| 302 | // This corresponds to the "push" update operation of the paper, |
|---|
| 303 | // not the "push" function in Goldberg's h_prf.c implementation. |
|---|
| 304 | // The idea is to push the excess flow from from vertex u to v. |
|---|
| 305 | void push_flow(edge_descriptor u_v) |
|---|
| 306 | { |
|---|
| 307 | vertex_descriptor |
|---|
| 308 | u = source(u_v, g), |
|---|
| 309 | v = target(u_v, g); |
|---|
| 310 | |
|---|
| 311 | BOOST_USING_STD_MIN(); |
|---|
| 312 | FlowValue flow_delta |
|---|
| 313 | = min BOOST_PREVENT_MACRO_SUBSTITUTION(excess_flow[u], residual_capacity[u_v]); |
|---|
| 314 | |
|---|
| 315 | residual_capacity[u_v] -= flow_delta; |
|---|
| 316 | residual_capacity[reverse_edge[u_v]] += flow_delta; |
|---|
| 317 | |
|---|
| 318 | excess_flow[u] -= flow_delta; |
|---|
| 319 | excess_flow[v] += flow_delta; |
|---|
| 320 | } // push_flow() |
|---|
| 321 | |
|---|
| 322 | //======================================================================= |
|---|
| 323 | // The main purpose of this routine is to set distance[v] |
|---|
| 324 | // to the smallest value allowed by the valid labeling constraints, |
|---|
| 325 | // which are: |
|---|
| 326 | // distance[t] = 0 |
|---|
| 327 | // distance[u] <= distance[v] + 1 for every residual edge (u,v) |
|---|
| 328 | // |
|---|
| 329 | distance_size_type relabel_distance(vertex_descriptor u) |
|---|
| 330 | { |
|---|
| 331 | BOOST_USING_STD_MAX(); |
|---|
| 332 | ++relabel_count; |
|---|
| 333 | work_since_last_update += beta(); |
|---|
| 334 | |
|---|
| 335 | distance_size_type min_distance = num_vertices(g); |
|---|
| 336 | distance[u] = min_distance; |
|---|
| 337 | |
|---|
| 338 | // Examine the residual out-edges of vertex i, choosing the |
|---|
| 339 | // edge whose target vertex has the minimal distance. |
|---|
| 340 | out_edge_iterator ai, a_end, min_edge_iter; |
|---|
| 341 | for (tie(ai, a_end) = out_edges(u, g); ai != a_end; ++ai) { |
|---|
| 342 | ++work_since_last_update; |
|---|
| 343 | edge_descriptor a = *ai; |
|---|
| 344 | vertex_descriptor v = target(a, g); |
|---|
| 345 | if (is_residual_edge(a) && distance[v] < min_distance) { |
|---|
| 346 | min_distance = distance[v]; |
|---|
| 347 | min_edge_iter = ai; |
|---|
| 348 | } |
|---|
| 349 | } |
|---|
| 350 | ++min_distance; |
|---|
| 351 | if (min_distance < n) { |
|---|
| 352 | distance[u] = min_distance; // this is the main action |
|---|
| 353 | current[u] = min_edge_iter; |
|---|
| 354 | max_distance = max BOOST_PREVENT_MACRO_SUBSTITUTION(min_distance, max_distance); |
|---|
| 355 | } |
|---|
| 356 | return min_distance; |
|---|
| 357 | } // relabel_distance() |
|---|
| 358 | |
|---|
| 359 | //======================================================================= |
|---|
| 360 | // cleanup beyond the gap |
|---|
| 361 | void gap(distance_size_type empty_distance) |
|---|
| 362 | { |
|---|
| 363 | ++gap_count; |
|---|
| 364 | |
|---|
| 365 | distance_size_type r; // distance of layer before the current layer |
|---|
| 366 | r = empty_distance - 1; |
|---|
| 367 | |
|---|
| 368 | // Set the distance for the vertices beyond the gap to "infinity". |
|---|
| 369 | for (layer_iterator l = layers.begin() + empty_distance + 1; |
|---|
| 370 | l < layers.begin() + max_distance; ++l) { |
|---|
| 371 | list_iterator i; |
|---|
| 372 | for (i = l->inactive_vertices.begin(); |
|---|
| 373 | i != l->inactive_vertices.end(); ++i) { |
|---|
| 374 | distance[*i] = n; |
|---|
| 375 | ++gap_node_count; |
|---|
| 376 | } |
|---|
| 377 | l->inactive_vertices.clear(); |
|---|
| 378 | } |
|---|
| 379 | max_distance = r; |
|---|
| 380 | max_active = r; |
|---|
| 381 | } |
|---|
| 382 | |
|---|
| 383 | //======================================================================= |
|---|
| 384 | // This is the core part of the algorithm, "phase one". |
|---|
| 385 | FlowValue maximum_preflow() |
|---|
| 386 | { |
|---|
| 387 | work_since_last_update = 0; |
|---|
| 388 | |
|---|
| 389 | while (max_active >= min_active) { // "main" loop |
|---|
| 390 | |
|---|
| 391 | Layer& layer = layers[max_active]; |
|---|
| 392 | list_iterator u_iter = layer.active_vertices.begin(); |
|---|
| 393 | |
|---|
| 394 | if (u_iter == layer.active_vertices.end()) |
|---|
| 395 | --max_active; |
|---|
| 396 | else { |
|---|
| 397 | vertex_descriptor u = *u_iter; |
|---|
| 398 | remove_from_active_list(u); |
|---|
| 399 | |
|---|
| 400 | discharge(u); |
|---|
| 401 | |
|---|
| 402 | if (work_since_last_update * global_update_frequency() > nm) { |
|---|
| 403 | global_distance_update(); |
|---|
| 404 | work_since_last_update = 0; |
|---|
| 405 | } |
|---|
| 406 | } |
|---|
| 407 | } // while (max_active >= min_active) |
|---|
| 408 | |
|---|
| 409 | return excess_flow[sink]; |
|---|
| 410 | } // maximum_preflow() |
|---|
| 411 | |
|---|
| 412 | //======================================================================= |
|---|
| 413 | // remove excess flow, the "second phase" |
|---|
| 414 | // This does a DFS on the reverse flow graph of nodes with excess flow. |
|---|
| 415 | // If a cycle is found, cancel it. |
|---|
| 416 | // Return the nodes with excess flow in topological order. |
|---|
| 417 | // |
|---|
| 418 | // Unlike the prefl_to_flow() implementation, we use |
|---|
| 419 | // "color" instead of "distance" for the DFS labels |
|---|
| 420 | // "parent" instead of nl_prev for the DFS tree |
|---|
| 421 | // "topo_next" instead of nl_next for the topological ordering |
|---|
| 422 | void convert_preflow_to_flow() |
|---|
| 423 | { |
|---|
| 424 | vertex_iterator u_iter, u_end; |
|---|
| 425 | out_edge_iterator ai, a_end; |
|---|
| 426 | |
|---|
| 427 | vertex_descriptor r, restart, u; |
|---|
| 428 | |
|---|
| 429 | std::vector<vertex_descriptor> parent(n); |
|---|
| 430 | std::vector<vertex_descriptor> topo_next(n); |
|---|
| 431 | |
|---|
| 432 | vertex_descriptor tos(parent[0]), |
|---|
| 433 | bos(parent[0]); // bogus initialization, just to avoid warning |
|---|
| 434 | bool bos_null = true; |
|---|
| 435 | |
|---|
| 436 | // handle self-loops |
|---|
| 437 | for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) |
|---|
| 438 | for (tie(ai, a_end) = out_edges(*u_iter, g); ai != a_end; ++ai) |
|---|
| 439 | if (target(*ai, g) == *u_iter) |
|---|
| 440 | residual_capacity[*ai] = capacity[*ai]; |
|---|
| 441 | |
|---|
| 442 | // initialize |
|---|
| 443 | for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) { |
|---|
| 444 | u = *u_iter; |
|---|
| 445 | color[u] = ColorTraits::white(); |
|---|
| 446 | parent[u] = u; |
|---|
| 447 | current[u] = out_edges(u, g).first; |
|---|
| 448 | } |
|---|
| 449 | // eliminate flow cycles and topologically order the vertices |
|---|
| 450 | for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) { |
|---|
| 451 | u = *u_iter; |
|---|
| 452 | if (color[u] == ColorTraits::white() |
|---|
| 453 | && excess_flow[u] > 0 |
|---|
| 454 | && u != src && u != sink ) { |
|---|
| 455 | r = u; |
|---|
| 456 | color[r] = ColorTraits::gray(); |
|---|
| 457 | while (1) { |
|---|
| 458 | for (; current[u] != out_edges(u, g).second; ++current[u]) { |
|---|
| 459 | edge_descriptor a = *current[u]; |
|---|
| 460 | if (capacity[a] == 0 && is_residual_edge(a)) { |
|---|
| 461 | vertex_descriptor v = target(a, g); |
|---|
| 462 | if (color[v] == ColorTraits::white()) { |
|---|
| 463 | color[v] = ColorTraits::gray(); |
|---|
| 464 | parent[v] = u; |
|---|
| 465 | u = v; |
|---|
| 466 | break; |
|---|
| 467 | } else if (color[v] == ColorTraits::gray()) { |
|---|
| 468 | // find minimum flow on the cycle |
|---|
| 469 | FlowValue delta = residual_capacity[a]; |
|---|
| 470 | while (1) { |
|---|
| 471 | BOOST_USING_STD_MIN(); |
|---|
| 472 | delta = min BOOST_PREVENT_MACRO_SUBSTITUTION(delta, residual_capacity[*current[v]]); |
|---|
| 473 | if (v == u) |
|---|
| 474 | break; |
|---|
| 475 | else |
|---|
| 476 | v = target(*current[v], g); |
|---|
| 477 | } |
|---|
| 478 | // remove delta flow units |
|---|
| 479 | v = u; |
|---|
| 480 | while (1) { |
|---|
| 481 | a = *current[v]; |
|---|
| 482 | residual_capacity[a] -= delta; |
|---|
| 483 | residual_capacity[reverse_edge[a]] += delta; |
|---|
| 484 | v = target(a, g); |
|---|
| 485 | if (v == u) |
|---|
| 486 | break; |
|---|
| 487 | } |
|---|
| 488 | |
|---|
| 489 | // back-out of DFS to the first saturated edge |
|---|
| 490 | restart = u; |
|---|
| 491 | for (v = target(*current[u], g); v != u; v = target(a, g)){ |
|---|
| 492 | a = *current[v]; |
|---|
| 493 | if (color[v] == ColorTraits::white() |
|---|
| 494 | || is_saturated(a)) { |
|---|
| 495 | color[target(*current[v], g)] = ColorTraits::white(); |
|---|
| 496 | if (color[v] != ColorTraits::white()) |
|---|
| 497 | restart = v; |
|---|
| 498 | } |
|---|
| 499 | } |
|---|
| 500 | if (restart != u) { |
|---|
| 501 | u = restart; |
|---|
| 502 | ++current[u]; |
|---|
| 503 | break; |
|---|
| 504 | } |
|---|
| 505 | } // else if (color[v] == ColorTraits::gray()) |
|---|
| 506 | } // if (capacity[a] == 0 ... |
|---|
| 507 | } // for out_edges(u, g) (though "u" changes during loop) |
|---|
| 508 | |
|---|
| 509 | if (current[u] == out_edges(u, g).second) { |
|---|
| 510 | // scan of i is complete |
|---|
| 511 | color[u] = ColorTraits::black(); |
|---|
| 512 | if (u != src) { |
|---|
| 513 | if (bos_null) { |
|---|
| 514 | bos = u; |
|---|
| 515 | bos_null = false; |
|---|
| 516 | tos = u; |
|---|
| 517 | } else { |
|---|
| 518 | topo_next[u] = tos; |
|---|
| 519 | tos = u; |
|---|
| 520 | } |
|---|
| 521 | } |
|---|
| 522 | if (u != r) { |
|---|
| 523 | u = parent[u]; |
|---|
| 524 | ++current[u]; |
|---|
| 525 | } else |
|---|
| 526 | break; |
|---|
| 527 | } |
|---|
| 528 | } // while (1) |
|---|
| 529 | } // if (color[u] == white && excess_flow[u] > 0 & ...) |
|---|
| 530 | } // for all vertices in g |
|---|
| 531 | |
|---|
| 532 | // return excess flows |
|---|
| 533 | // note that the sink is not on the stack |
|---|
| 534 | if (! bos_null) { |
|---|
| 535 | for (u = tos; u != bos; u = topo_next[u]) { |
|---|
| 536 | ai = out_edges(u, g).first; |
|---|
| 537 | while (excess_flow[u] > 0 && ai != out_edges(u, g).second) { |
|---|
| 538 | if (capacity[*ai] == 0 && is_residual_edge(*ai)) |
|---|
| 539 | push_flow(*ai); |
|---|
| 540 | ++ai; |
|---|
| 541 | } |
|---|
| 542 | } |
|---|
| 543 | // do the bottom |
|---|
| 544 | u = bos; |
|---|
| 545 | ai = out_edges(u, g).first; |
|---|
| 546 | while (excess_flow[u] > 0) { |
|---|
| 547 | if (capacity[*ai] == 0 && is_residual_edge(*ai)) |
|---|
| 548 | push_flow(*ai); |
|---|
| 549 | ++ai; |
|---|
| 550 | } |
|---|
| 551 | } |
|---|
| 552 | |
|---|
| 553 | } // convert_preflow_to_flow() |
|---|
| 554 | |
|---|
| 555 | //======================================================================= |
|---|
| 556 | inline bool is_flow() |
|---|
| 557 | { |
|---|
| 558 | vertex_iterator u_iter, u_end; |
|---|
| 559 | out_edge_iterator ai, a_end; |
|---|
| 560 | |
|---|
| 561 | // check edge flow values |
|---|
| 562 | for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) { |
|---|
| 563 | for (tie(ai, a_end) = out_edges(*u_iter, g); ai != a_end; ++ai) { |
|---|
| 564 | edge_descriptor a = *ai; |
|---|
| 565 | if (capacity[a] > 0) |
|---|
| 566 | if ((residual_capacity[a] + residual_capacity[reverse_edge[a]] |
|---|
| 567 | != capacity[a] + capacity[reverse_edge[a]]) |
|---|
| 568 | || (residual_capacity[a] < 0) |
|---|
| 569 | || (residual_capacity[reverse_edge[a]] < 0)) |
|---|
| 570 | return false; |
|---|
| 571 | } |
|---|
| 572 | } |
|---|
| 573 | |
|---|
| 574 | // check conservation |
|---|
| 575 | FlowValue sum; |
|---|
| 576 | for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) { |
|---|
| 577 | vertex_descriptor u = *u_iter; |
|---|
| 578 | if (u != src && u != sink) { |
|---|
| 579 | if (excess_flow[u] != 0) |
|---|
| 580 | return false; |
|---|
| 581 | sum = 0; |
|---|
| 582 | for (tie(ai, a_end) = out_edges(u, g); ai != a_end; ++ai) |
|---|
| 583 | if (capacity[*ai] > 0) |
|---|
| 584 | sum -= capacity[*ai] - residual_capacity[*ai]; |
|---|
| 585 | else |
|---|
| 586 | sum += residual_capacity[*ai]; |
|---|
| 587 | |
|---|
| 588 | if (excess_flow[u] != sum) |
|---|
| 589 | return false; |
|---|
| 590 | } |
|---|
| 591 | } |
|---|
| 592 | |
|---|
| 593 | return true; |
|---|
| 594 | } // is_flow() |
|---|
| 595 | |
|---|
| 596 | bool is_optimal() { |
|---|
| 597 | // check if mincut is saturated... |
|---|
| 598 | global_distance_update(); |
|---|
| 599 | return distance[src] >= n; |
|---|
| 600 | } |
|---|
| 601 | |
|---|
| 602 | void print_statistics(std::ostream& os) const { |
|---|
| 603 | os << "pushes: " << push_count << std::endl |
|---|
| 604 | << "relabels: " << relabel_count << std::endl |
|---|
| 605 | << "updates: " << update_count << std::endl |
|---|
| 606 | << "gaps: " << gap_count << std::endl |
|---|
| 607 | << "gap nodes: " << gap_node_count << std::endl |
|---|
| 608 | << std::endl; |
|---|
| 609 | } |
|---|
| 610 | |
|---|
| 611 | void print_flow_values(std::ostream& os) const { |
|---|
| 612 | os << "flow values" << std::endl; |
|---|
| 613 | vertex_iterator u_iter, u_end; |
|---|
| 614 | out_edge_iterator ei, e_end; |
|---|
| 615 | for (tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) |
|---|
| 616 | for (tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei) |
|---|
| 617 | if (capacity[*ei] > 0) |
|---|
| 618 | os << *u_iter << " " << target(*ei, g) << " " |
|---|
| 619 | << (capacity[*ei] - residual_capacity[*ei]) << std::endl; |
|---|
| 620 | os << std::endl; |
|---|
| 621 | } |
|---|
| 622 | |
|---|
| 623 | //======================================================================= |
|---|
| 624 | |
|---|
| 625 | Graph& g; |
|---|
| 626 | vertices_size_type n; |
|---|
| 627 | vertices_size_type nm; |
|---|
| 628 | EdgeCapacityMap capacity; |
|---|
| 629 | vertex_descriptor src; |
|---|
| 630 | vertex_descriptor sink; |
|---|
| 631 | VertexIndexMap index; |
|---|
| 632 | |
|---|
| 633 | // will need to use random_access_property_map with these |
|---|
| 634 | std::vector< FlowValue > excess_flow; |
|---|
| 635 | std::vector< out_edge_iterator > current; |
|---|
| 636 | std::vector< distance_size_type > distance; |
|---|
| 637 | std::vector< default_color_type > color; |
|---|
| 638 | |
|---|
| 639 | // Edge Property Maps that must be interior to the graph |
|---|
| 640 | ReverseEdgeMap reverse_edge; |
|---|
| 641 | ResidualCapacityEdgeMap residual_capacity; |
|---|
| 642 | |
|---|
| 643 | LayerArray layers; |
|---|
| 644 | std::vector< list_iterator > layer_list_ptr; |
|---|
| 645 | distance_size_type max_distance; // maximal distance |
|---|
| 646 | distance_size_type max_active; // maximal distance with active node |
|---|
| 647 | distance_size_type min_active; // minimal distance with active node |
|---|
| 648 | boost::queue<vertex_descriptor> Q; |
|---|
| 649 | |
|---|
| 650 | // Statistics counters |
|---|
| 651 | long push_count; |
|---|
| 652 | long update_count; |
|---|
| 653 | long relabel_count; |
|---|
| 654 | long gap_count; |
|---|
| 655 | long gap_node_count; |
|---|
| 656 | |
|---|
| 657 | inline double global_update_frequency() { return 0.5; } |
|---|
| 658 | inline vertices_size_type alpha() { return 6; } |
|---|
| 659 | inline long beta() { return 12; } |
|---|
| 660 | |
|---|
| 661 | long work_since_last_update; |
|---|
| 662 | }; |
|---|
| 663 | |
|---|
| 664 | } // namespace detail |
|---|
| 665 | |
|---|
| 666 | template <class Graph, |
|---|
| 667 | class CapacityEdgeMap, class ResidualCapacityEdgeMap, |
|---|
| 668 | class ReverseEdgeMap, class VertexIndexMap> |
|---|
| 669 | typename property_traits<CapacityEdgeMap>::value_type |
|---|
| 670 | push_relabel_max_flow |
|---|
| 671 | (Graph& g, |
|---|
| 672 | typename graph_traits<Graph>::vertex_descriptor src, |
|---|
| 673 | typename graph_traits<Graph>::vertex_descriptor sink, |
|---|
| 674 | CapacityEdgeMap cap, ResidualCapacityEdgeMap res, |
|---|
| 675 | ReverseEdgeMap rev, VertexIndexMap index_map) |
|---|
| 676 | { |
|---|
| 677 | typedef typename property_traits<CapacityEdgeMap>::value_type FlowValue; |
|---|
| 678 | |
|---|
| 679 | detail::push_relabel<Graph, CapacityEdgeMap, ResidualCapacityEdgeMap, |
|---|
| 680 | ReverseEdgeMap, VertexIndexMap, FlowValue> |
|---|
| 681 | algo(g, cap, res, rev, src, sink, index_map); |
|---|
| 682 | |
|---|
| 683 | FlowValue flow = algo.maximum_preflow(); |
|---|
| 684 | |
|---|
| 685 | algo.convert_preflow_to_flow(); |
|---|
| 686 | |
|---|
| 687 | assert(algo.is_flow()); |
|---|
| 688 | assert(algo.is_optimal()); |
|---|
| 689 | |
|---|
| 690 | return flow; |
|---|
| 691 | } // push_relabel_max_flow() |
|---|
| 692 | |
|---|
| 693 | template <class Graph, class P, class T, class R> |
|---|
| 694 | typename detail::edge_capacity_value<Graph, P, T, R>::type |
|---|
| 695 | push_relabel_max_flow |
|---|
| 696 | (Graph& g, |
|---|
| 697 | typename graph_traits<Graph>::vertex_descriptor src, |
|---|
| 698 | typename graph_traits<Graph>::vertex_descriptor sink, |
|---|
| 699 | const bgl_named_params<P, T, R>& params) |
|---|
| 700 | { |
|---|
| 701 | return push_relabel_max_flow |
|---|
| 702 | (g, src, sink, |
|---|
| 703 | choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity), |
|---|
| 704 | choose_pmap(get_param(params, edge_residual_capacity), |
|---|
| 705 | g, edge_residual_capacity), |
|---|
| 706 | choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse), |
|---|
| 707 | choose_const_pmap(get_param(params, vertex_index), g, vertex_index) |
|---|
| 708 | ); |
|---|
| 709 | } |
|---|
| 710 | |
|---|
| 711 | template <class Graph> |
|---|
| 712 | typename property_traits< |
|---|
| 713 | typename property_map<Graph, edge_capacity_t>::const_type |
|---|
| 714 | >::value_type |
|---|
| 715 | push_relabel_max_flow |
|---|
| 716 | (Graph& g, |
|---|
| 717 | typename graph_traits<Graph>::vertex_descriptor src, |
|---|
| 718 | typename graph_traits<Graph>::vertex_descriptor sink) |
|---|
| 719 | { |
|---|
| 720 | bgl_named_params<int, buffer_param_t> params(0); // bogus empty param |
|---|
| 721 | return push_relabel_max_flow(g, src, sink, params); |
|---|
| 722 | } |
|---|
| 723 | |
|---|
| 724 | } // namespace boost |
|---|
| 725 | |
|---|
| 726 | #endif // BOOST_PUSH_RELABEL_MAX_FLOW_HPP |
|---|
| 727 | |
|---|