File indexing completed on 2025-01-30 09:43:06
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_PUSH_RELABEL_MAX_FLOW_HPP
0011 #define BOOST_PUSH_RELABEL_MAX_FLOW_HPP
0012
0013 #include <boost/config.hpp>
0014 #include <boost/assert.hpp>
0015 #include <vector>
0016 #include <list>
0017 #include <iosfwd>
0018 #include <algorithm> // for std::min and std::max
0019
0020 #include <boost/pending/queue.hpp>
0021 #include <boost/limits.hpp>
0022 #include <boost/graph/graph_concepts.hpp>
0023 #include <boost/graph/named_function_params.hpp>
0024
0025 namespace boost
0026 {
0027
0028 namespace detail
0029 {
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046 template < class Vertex > struct preflow_layer
0047 {
0048 std::list< Vertex > active_vertices;
0049 std::list< Vertex > inactive_vertices;
0050 };
0051
0052 template < class Graph,
0053 class EdgeCapacityMap,
0054 class ResidualCapacityEdgeMap, class ReverseEdgeMap,
0055 class VertexIndexMap,
0056 class FlowValue >
0057 class push_relabel
0058 {
0059 public:
0060 typedef graph_traits< Graph > Traits;
0061 typedef typename Traits::vertex_descriptor vertex_descriptor;
0062 typedef typename Traits::edge_descriptor edge_descriptor;
0063 typedef typename Traits::vertex_iterator vertex_iterator;
0064 typedef typename Traits::out_edge_iterator out_edge_iterator;
0065 typedef typename Traits::vertices_size_type vertices_size_type;
0066 typedef typename Traits::edges_size_type edges_size_type;
0067
0068 typedef preflow_layer< vertex_descriptor > Layer;
0069 typedef std::vector< Layer > LayerArray;
0070 typedef typename LayerArray::iterator layer_iterator;
0071 typedef typename LayerArray::size_type distance_size_type;
0072
0073 typedef color_traits< default_color_type > ColorTraits;
0074
0075
0076
0077
0078 inline bool is_admissible(vertex_descriptor u, vertex_descriptor v)
0079 {
0080 return get(distance, u) == get(distance, v) + 1;
0081 }
0082 inline bool is_residual_edge(edge_descriptor a)
0083 {
0084 return 0 < get(residual_capacity, a);
0085 }
0086 inline bool is_saturated(edge_descriptor a)
0087 {
0088 return get(residual_capacity, a) == 0;
0089 }
0090
0091
0092
0093
0094 typedef typename std::list< vertex_descriptor >::iterator list_iterator;
0095
0096 void add_to_active_list(vertex_descriptor u, Layer& layer)
0097 {
0098 BOOST_USING_STD_MIN();
0099 BOOST_USING_STD_MAX();
0100 layer.active_vertices.push_front(u);
0101 max_active = max BOOST_PREVENT_MACRO_SUBSTITUTION(
0102 get(distance, u), max_active);
0103 min_active = min BOOST_PREVENT_MACRO_SUBSTITUTION(
0104 get(distance, u), min_active);
0105 layer_list_ptr[u] = layer.active_vertices.begin();
0106 }
0107 void remove_from_active_list(vertex_descriptor u)
0108 {
0109 layers[get(distance, u)].active_vertices.erase(layer_list_ptr[u]);
0110 }
0111
0112 void add_to_inactive_list(vertex_descriptor u, Layer& layer)
0113 {
0114 layer.inactive_vertices.push_front(u);
0115 layer_list_ptr[u] = layer.inactive_vertices.begin();
0116 }
0117 void remove_from_inactive_list(vertex_descriptor u)
0118 {
0119 layers[get(distance, u)].inactive_vertices.erase(layer_list_ptr[u]);
0120 }
0121
0122
0123
0124 push_relabel(Graph& g_, EdgeCapacityMap cap,
0125 ResidualCapacityEdgeMap res, ReverseEdgeMap rev,
0126 vertex_descriptor src_, vertex_descriptor sink_, VertexIndexMap idx)
0127 : g(g_)
0128 , n(num_vertices(g_))
0129 , capacity(cap)
0130 , src(src_)
0131 , sink(sink_)
0132 , index(idx)
0133 , excess_flow_data(num_vertices(g_))
0134 , excess_flow(excess_flow_data.begin(), idx)
0135 , current_data(num_vertices(g_), out_edges(*vertices(g_).first, g_))
0136 , current(current_data.begin(), idx)
0137 , distance_data(num_vertices(g_))
0138 , distance(distance_data.begin(), idx)
0139 , color_data(num_vertices(g_))
0140 , color(color_data.begin(), idx)
0141 , reverse_edge(rev)
0142 , residual_capacity(res)
0143 , layers(num_vertices(g_))
0144 , layer_list_ptr_data(
0145 num_vertices(g_), layers.front().inactive_vertices.end())
0146 , layer_list_ptr(layer_list_ptr_data.begin(), idx)
0147 , push_count(0)
0148 , update_count(0)
0149 , relabel_count(0)
0150 , gap_count(0)
0151 , gap_node_count(0)
0152 , work_since_last_update(0)
0153 {
0154 vertex_iterator u_iter, u_end;
0155
0156 edges_size_type m = num_edges(g) / 2;
0157 nm = alpha() * n + m;
0158
0159
0160
0161 out_edge_iterator ei, e_end;
0162 for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end;
0163 ++u_iter)
0164 for (boost::tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end;
0165 ++ei)
0166 {
0167 put(residual_capacity, *ei, get(capacity, *ei));
0168 }
0169
0170 for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end;
0171 ++u_iter)
0172 {
0173 vertex_descriptor u = *u_iter;
0174 put(excess_flow, u, 0);
0175 current[u] = out_edges(u, g);
0176 }
0177
0178 bool overflow_detected = false;
0179 FlowValue test_excess = 0;
0180
0181 out_edge_iterator a_iter, a_end;
0182 for (boost::tie(a_iter, a_end) = out_edges(src, g); a_iter != a_end;
0183 ++a_iter)
0184 if (target(*a_iter, g) != src)
0185 test_excess += get(residual_capacity, *a_iter);
0186 if (test_excess > (std::numeric_limits< FlowValue >::max)())
0187 overflow_detected = true;
0188
0189 if (overflow_detected)
0190 put(excess_flow, src,
0191 (std::numeric_limits< FlowValue >::max)());
0192 else
0193 {
0194 put(excess_flow, src, 0);
0195 for (boost::tie(a_iter, a_end) = out_edges(src, g);
0196 a_iter != a_end; ++a_iter)
0197 {
0198 edge_descriptor a = *a_iter;
0199 vertex_descriptor tgt = target(a, g);
0200 if (tgt != src)
0201 {
0202 ++push_count;
0203 FlowValue delta = get(residual_capacity, a);
0204 put(residual_capacity, a,
0205 get(residual_capacity, a) - delta);
0206 edge_descriptor rev = get(reverse_edge, a);
0207 put(residual_capacity, rev,
0208 get(residual_capacity, rev) + delta);
0209 put(excess_flow, tgt, get(excess_flow, tgt) + delta);
0210 }
0211 }
0212 }
0213 max_distance = num_vertices(g) - 1;
0214 max_active = 0;
0215 min_active = n;
0216
0217 for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end;
0218 ++u_iter)
0219 {
0220 vertex_descriptor u = *u_iter;
0221 if (u == sink)
0222 {
0223 put(distance, u, 0);
0224 continue;
0225 }
0226 else if (u == src && !overflow_detected)
0227 put(distance, u, n);
0228 else
0229 put(distance, u, 1);
0230
0231 if (get(excess_flow, u) > 0)
0232 add_to_active_list(u, layers[1]);
0233 else if (get(distance, u) < n)
0234 add_to_inactive_list(u, layers[1]);
0235 }
0236
0237 }
0238
0239
0240
0241
0242
0243
0244
0245 void global_distance_update()
0246 {
0247 BOOST_USING_STD_MAX();
0248 ++update_count;
0249 vertex_iterator u_iter, u_end;
0250 for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end;
0251 ++u_iter)
0252 {
0253 put(color, *u_iter, ColorTraits::white());
0254 put(distance, *u_iter, n);
0255 }
0256 put(color, sink, ColorTraits::gray());
0257 put(distance, sink, 0);
0258
0259 for (distance_size_type l = 0; l <= max_distance; ++l)
0260 {
0261 layers[l].active_vertices.clear();
0262 layers[l].inactive_vertices.clear();
0263 }
0264
0265 max_distance = max_active = 0;
0266 min_active = n;
0267
0268 Q.push(sink);
0269 while (!Q.empty())
0270 {
0271 vertex_descriptor u = Q.top();
0272 Q.pop();
0273 distance_size_type d_v = get(distance, u) + 1;
0274
0275 out_edge_iterator ai, a_end;
0276 for (boost::tie(ai, a_end) = out_edges(u, g); ai != a_end; ++ai)
0277 {
0278 edge_descriptor a = *ai;
0279 vertex_descriptor v = target(a, g);
0280 if (get(color, v) == ColorTraits::white()
0281 && is_residual_edge(get(reverse_edge, a)))
0282 {
0283 put(distance, v, d_v);
0284 put(color, v, ColorTraits::gray());
0285 current[v] = out_edges(v, g);
0286 max_distance = max BOOST_PREVENT_MACRO_SUBSTITUTION(
0287 d_v, max_distance);
0288
0289 if (get(excess_flow, v) > 0)
0290 add_to_active_list(v, layers[d_v]);
0291 else
0292 add_to_inactive_list(v, layers[d_v]);
0293
0294 Q.push(v);
0295 }
0296 }
0297 }
0298 }
0299
0300
0301
0302
0303 void discharge(vertex_descriptor u)
0304 {
0305 BOOST_ASSERT(get(excess_flow, u) > 0);
0306 while (1)
0307 {
0308 out_edge_iterator ai, ai_end;
0309 for (boost::tie(ai, ai_end) = current[u]; ai != ai_end; ++ai)
0310 {
0311 edge_descriptor a = *ai;
0312 if (is_residual_edge(a))
0313 {
0314 vertex_descriptor v = target(a, g);
0315 if (is_admissible(u, v))
0316 {
0317 ++push_count;
0318 if (v != sink && get(excess_flow, v) == 0)
0319 {
0320 remove_from_inactive_list(v);
0321 add_to_active_list(v, layers[get(distance, v)]);
0322 }
0323 push_flow(a);
0324 if (get(excess_flow, u) == 0)
0325 break;
0326 }
0327 }
0328 }
0329
0330 Layer& layer = layers[get(distance, u)];
0331 distance_size_type du = get(distance, u);
0332
0333 if (ai == ai_end)
0334 {
0335 relabel_distance(u);
0336 if (layer.active_vertices.empty()
0337 && layer.inactive_vertices.empty())
0338 gap(du);
0339 if (get(distance, u) == n)
0340 break;
0341 }
0342 else
0343 {
0344 current[u].first = ai;
0345 add_to_inactive_list(u, layer);
0346 break;
0347 }
0348 }
0349 }
0350
0351
0352
0353
0354
0355 void push_flow(edge_descriptor u_v)
0356 {
0357 vertex_descriptor u = source(u_v, g), v = target(u_v, g);
0358
0359 BOOST_USING_STD_MIN();
0360 FlowValue flow_delta = min BOOST_PREVENT_MACRO_SUBSTITUTION(
0361 get(excess_flow, u), get(residual_capacity, u_v));
0362
0363 put(residual_capacity, u_v,
0364 get(residual_capacity, u_v) - flow_delta);
0365 edge_descriptor rev = get(reverse_edge, u_v);
0366 put(residual_capacity, rev,
0367 get(residual_capacity, rev) + flow_delta);
0368
0369 put(excess_flow, u, get(excess_flow, u) - flow_delta);
0370 put(excess_flow, v, get(excess_flow, v) + flow_delta);
0371 }
0372
0373
0374
0375
0376
0377
0378
0379
0380 distance_size_type relabel_distance(vertex_descriptor u)
0381 {
0382 BOOST_USING_STD_MAX();
0383 ++relabel_count;
0384 work_since_last_update += beta();
0385
0386 distance_size_type min_distance = num_vertices(g);
0387 put(distance, u, min_distance);
0388
0389
0390
0391 out_edge_iterator ai, a_end, min_edge_iter;
0392 for (boost::tie(ai, a_end) = out_edges(u, g); ai != a_end; ++ai)
0393 {
0394 ++work_since_last_update;
0395 edge_descriptor a = *ai;
0396 vertex_descriptor v = target(a, g);
0397 if (is_residual_edge(a) && get(distance, v) < min_distance)
0398 {
0399 min_distance = get(distance, v);
0400 min_edge_iter = ai;
0401 }
0402 }
0403 ++min_distance;
0404 if (min_distance < n)
0405 {
0406 put(distance, u, min_distance);
0407 current[u].first = min_edge_iter;
0408 max_distance = max BOOST_PREVENT_MACRO_SUBSTITUTION(
0409 min_distance, max_distance);
0410 }
0411 return min_distance;
0412 }
0413
0414
0415
0416 void gap(distance_size_type empty_distance)
0417 {
0418 ++gap_count;
0419
0420 distance_size_type r;
0421 r = empty_distance - 1;
0422
0423
0424 for (layer_iterator l = layers.begin() + empty_distance + 1;
0425 l < layers.begin() + max_distance; ++l)
0426 {
0427 list_iterator i;
0428 for (i = l->inactive_vertices.begin();
0429 i != l->inactive_vertices.end(); ++i)
0430 {
0431 put(distance, *i, n);
0432 ++gap_node_count;
0433 }
0434 l->inactive_vertices.clear();
0435 }
0436 max_distance = r;
0437 max_active = r;
0438 }
0439
0440
0441
0442 FlowValue maximum_preflow()
0443 {
0444 work_since_last_update = 0;
0445
0446 while (max_active >= min_active)
0447 {
0448
0449 Layer& layer = layers[max_active];
0450 list_iterator u_iter = layer.active_vertices.begin();
0451
0452 if (u_iter == layer.active_vertices.end())
0453 --max_active;
0454 else
0455 {
0456 vertex_descriptor u = *u_iter;
0457 remove_from_active_list(u);
0458
0459 discharge(u);
0460
0461 if (work_since_last_update * global_update_frequency() > nm)
0462 {
0463 global_distance_update();
0464 work_since_last_update = 0;
0465 }
0466 }
0467 }
0468
0469 return get(excess_flow, sink);
0470 }
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482 void convert_preflow_to_flow()
0483 {
0484 vertex_iterator u_iter, u_end;
0485 out_edge_iterator ai, a_end;
0486
0487 vertex_descriptor r, restart, u;
0488
0489 std::vector< vertex_descriptor > parent(n);
0490 std::vector< vertex_descriptor > topo_next(n);
0491
0492 vertex_descriptor tos(parent[0]),
0493 bos(parent[0]);
0494 bool bos_null = true;
0495
0496
0497 for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end;
0498 ++u_iter)
0499 for (boost::tie(ai, a_end) = out_edges(*u_iter, g); ai != a_end;
0500 ++ai)
0501 if (target(*ai, g) == *u_iter)
0502 put(residual_capacity, *ai, get(capacity, *ai));
0503
0504
0505 for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end;
0506 ++u_iter)
0507 {
0508 u = *u_iter;
0509 put(color, u, ColorTraits::white());
0510 parent[get(index, u)] = u;
0511 current[u] = out_edges(u, g);
0512 }
0513
0514 for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end;
0515 ++u_iter)
0516 {
0517 u = *u_iter;
0518 if (get(color, u) == ColorTraits::white()
0519 && get(excess_flow, u) > 0 && u != src && u != sink)
0520 {
0521 r = u;
0522 put(color, r, ColorTraits::gray());
0523 while (1)
0524 {
0525 for (; current[u].first != current[u].second;
0526 ++current[u].first)
0527 {
0528 edge_descriptor a = *current[u].first;
0529 if (get(capacity, a) == 0 && is_residual_edge(a))
0530 {
0531 vertex_descriptor v = target(a, g);
0532 if (get(color, v) == ColorTraits::white())
0533 {
0534 put(color, v, ColorTraits::gray());
0535 parent[get(index, v)] = u;
0536 u = v;
0537 break;
0538 }
0539 else if (get(color, v) == ColorTraits::gray())
0540 {
0541
0542 FlowValue delta = get(residual_capacity, a);
0543 while (1)
0544 {
0545 BOOST_USING_STD_MIN();
0546 delta = min
0547 BOOST_PREVENT_MACRO_SUBSTITUTION(
0548 delta,
0549 get(residual_capacity,
0550 *current[v].first));
0551 if (v == u)
0552 break;
0553 else
0554 v = target(*current[v].first, g);
0555 }
0556
0557 v = u;
0558 while (1)
0559 {
0560 a = *current[v].first;
0561 put(residual_capacity, a,
0562 get(residual_capacity, a) - delta);
0563 edge_descriptor rev
0564 = get(reverse_edge, a);
0565 put(residual_capacity, rev,
0566 get(residual_capacity, rev)
0567 + delta);
0568 v = target(a, g);
0569 if (v == u)
0570 break;
0571 }
0572
0573
0574
0575 restart = u;
0576 for (v = target(*current[u].first, g);
0577 v != u; v = target(a, g))
0578 {
0579 a = *current[v].first;
0580 if (get(color, v)
0581 == ColorTraits::white()
0582 || is_saturated(a))
0583 {
0584 put(color,
0585 target(*current[v].first, g),
0586 ColorTraits::white());
0587 if (get(color, v)
0588 != ColorTraits::white())
0589 restart = v;
0590 }
0591 }
0592 if (restart != u)
0593 {
0594 u = restart;
0595 ++current[u].first;
0596 break;
0597 }
0598 }
0599 }
0600 }
0601
0602
0603 if (current[u].first == current[u].second)
0604 {
0605
0606 put(color, u, ColorTraits::black());
0607 if (u != src)
0608 {
0609 if (bos_null)
0610 {
0611 bos = u;
0612 bos_null = false;
0613 tos = u;
0614 }
0615 else
0616 {
0617 topo_next[get(index, u)] = tos;
0618 tos = u;
0619 }
0620 }
0621 if (u != r)
0622 {
0623 u = parent[get(index, u)];
0624 ++current[u].first;
0625 }
0626 else
0627 break;
0628 }
0629 }
0630 }
0631 }
0632
0633
0634
0635 if (!bos_null)
0636 {
0637 for (u = tos; u != bos; u = topo_next[get(index, u)])
0638 {
0639 boost::tie(ai, a_end) = out_edges(u, g);
0640 while (get(excess_flow, u) > 0 && ai != a_end)
0641 {
0642 if (get(capacity, *ai) == 0 && is_residual_edge(*ai))
0643 push_flow(*ai);
0644 ++ai;
0645 }
0646 }
0647
0648 u = bos;
0649 boost::tie(ai, a_end) = out_edges(u, g);
0650 while (get(excess_flow, u) > 0 && ai != a_end)
0651 {
0652 if (get(capacity, *ai) == 0 && is_residual_edge(*ai))
0653 push_flow(*ai);
0654 ++ai;
0655 }
0656 }
0657
0658 }
0659
0660
0661 inline bool is_flow()
0662 {
0663 vertex_iterator u_iter, u_end;
0664 out_edge_iterator ai, a_end;
0665
0666
0667 for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end;
0668 ++u_iter)
0669 {
0670 for (boost::tie(ai, a_end) = out_edges(*u_iter, g); ai != a_end;
0671 ++ai)
0672 {
0673 edge_descriptor a = *ai;
0674 if (get(capacity, a) > 0)
0675 if ((get(residual_capacity, a)
0676 + get(
0677 residual_capacity, get(reverse_edge, a))
0678 != get(capacity, a)
0679 + get(capacity, get(reverse_edge, a)))
0680 || (get(residual_capacity, a) < 0)
0681 || (get(residual_capacity, get(reverse_edge, a))
0682 < 0))
0683 return false;
0684 }
0685 }
0686
0687
0688 FlowValue sum;
0689 for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end;
0690 ++u_iter)
0691 {
0692 vertex_descriptor u = *u_iter;
0693 if (u != src && u != sink)
0694 {
0695 if (get(excess_flow, u) != 0)
0696 return false;
0697 sum = 0;
0698 for (boost::tie(ai, a_end) = out_edges(u, g); ai != a_end;
0699 ++ai)
0700 if (get(capacity, *ai) > 0)
0701 sum -= get(capacity, *ai)
0702 - get(residual_capacity, *ai);
0703 else
0704 sum += get(residual_capacity, *ai);
0705
0706 if (get(excess_flow, u) != sum)
0707 return false;
0708 }
0709 }
0710
0711 return true;
0712 }
0713
0714 bool is_optimal()
0715 {
0716
0717 global_distance_update();
0718 return get(distance, src) >= n;
0719 }
0720
0721 void print_statistics(std::ostream& os) const
0722 {
0723 os << "pushes: " << push_count << std::endl
0724 << "relabels: " << relabel_count << std::endl
0725 << "updates: " << update_count << std::endl
0726 << "gaps: " << gap_count << std::endl
0727 << "gap nodes: " << gap_node_count << std::endl
0728 << std::endl;
0729 }
0730
0731 void print_flow_values(std::ostream& os) const
0732 {
0733 os << "flow values" << std::endl;
0734 vertex_iterator u_iter, u_end;
0735 out_edge_iterator ei, e_end;
0736 for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end;
0737 ++u_iter)
0738 for (boost::tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end;
0739 ++ei)
0740 if (get(capacity, *ei) > 0)
0741 os << *u_iter << " " << target(*ei, g) << " "
0742 << (get(capacity, *ei) - get(residual_capacity, *ei))
0743 << std::endl;
0744 os << std::endl;
0745 }
0746
0747
0748
0749 Graph& g;
0750 vertices_size_type n;
0751 vertices_size_type nm;
0752 EdgeCapacityMap capacity;
0753 vertex_descriptor src;
0754 vertex_descriptor sink;
0755 VertexIndexMap index;
0756
0757
0758 std::vector< FlowValue > excess_flow_data;
0759 iterator_property_map< typename std::vector< FlowValue >::iterator,
0760 VertexIndexMap >
0761 excess_flow;
0762 std::vector< std::pair< out_edge_iterator, out_edge_iterator > >
0763 current_data;
0764 iterator_property_map<
0765 typename std::vector<
0766 std::pair< out_edge_iterator, out_edge_iterator > >::iterator,
0767 VertexIndexMap >
0768 current;
0769 std::vector< distance_size_type > distance_data;
0770 iterator_property_map<
0771 typename std::vector< distance_size_type >::iterator,
0772 VertexIndexMap >
0773 distance;
0774 std::vector< default_color_type > color_data;
0775 iterator_property_map< std::vector< default_color_type >::iterator,
0776 VertexIndexMap >
0777 color;
0778
0779
0780 ReverseEdgeMap reverse_edge;
0781 ResidualCapacityEdgeMap residual_capacity;
0782
0783 LayerArray layers;
0784 std::vector< list_iterator > layer_list_ptr_data;
0785 iterator_property_map< typename std::vector< list_iterator >::iterator,
0786 VertexIndexMap >
0787 layer_list_ptr;
0788 distance_size_type max_distance;
0789 distance_size_type max_active;
0790 distance_size_type min_active;
0791 boost::queue< vertex_descriptor > Q;
0792
0793
0794 long push_count;
0795 long update_count;
0796 long relabel_count;
0797 long gap_count;
0798 long gap_node_count;
0799
0800 inline double global_update_frequency() { return 0.5; }
0801 inline vertices_size_type alpha() { return 6; }
0802 inline long beta() { return 12; }
0803
0804 long work_since_last_update;
0805 };
0806
0807 }
0808
0809 template < class Graph, class CapacityEdgeMap, class ResidualCapacityEdgeMap,
0810 class ReverseEdgeMap, class VertexIndexMap >
0811 typename property_traits< CapacityEdgeMap >::value_type push_relabel_max_flow(
0812 Graph& g, typename graph_traits< Graph >::vertex_descriptor src,
0813 typename graph_traits< Graph >::vertex_descriptor sink, CapacityEdgeMap cap,
0814 ResidualCapacityEdgeMap res, ReverseEdgeMap rev, VertexIndexMap index_map)
0815 {
0816 typedef typename property_traits< CapacityEdgeMap >::value_type FlowValue;
0817
0818 detail::push_relabel< Graph, CapacityEdgeMap, ResidualCapacityEdgeMap,
0819 ReverseEdgeMap, VertexIndexMap, FlowValue >
0820 algo(g, cap, res, rev, src, sink, index_map);
0821
0822 FlowValue flow = algo.maximum_preflow();
0823
0824 algo.convert_preflow_to_flow();
0825
0826 BOOST_ASSERT(algo.is_flow());
0827 BOOST_ASSERT(algo.is_optimal());
0828
0829 return flow;
0830 }
0831
0832 template < class Graph, class P, class T, class R >
0833 typename detail::edge_capacity_value< Graph, P, T, R >::type
0834 push_relabel_max_flow(Graph& g,
0835 typename graph_traits< Graph >::vertex_descriptor src,
0836 typename graph_traits< Graph >::vertex_descriptor sink,
0837 const bgl_named_params< P, T, R >& params)
0838 {
0839 return push_relabel_max_flow(g, src, sink,
0840 choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity),
0841 choose_pmap(get_param(params, edge_residual_capacity), g,
0842 edge_residual_capacity),
0843 choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse),
0844 choose_const_pmap(get_param(params, vertex_index), g, vertex_index));
0845 }
0846
0847 template < class Graph >
0848 typename property_traits<
0849 typename property_map< Graph, edge_capacity_t >::const_type >::value_type
0850 push_relabel_max_flow(Graph& g,
0851 typename graph_traits< Graph >::vertex_descriptor src,
0852 typename graph_traits< Graph >::vertex_descriptor sink)
0853 {
0854 bgl_named_params< int, buffer_param_t > params(0);
0855 return push_relabel_max_flow(g, src, sink, params);
0856 }
0857
0858 }
0859
0860 #endif