| 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 |  | 
|---|