push_relabel_max_flow.hpp 34 KB

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