boykov_kolmogorov_max_flow.hpp 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  1. // Copyright (c) 2006, Stephan Diederich
  2. //
  3. // This code may be used under either of the following two licences:
  4. //
  5. // Permission is hereby granted, free of charge, to any person
  6. // obtaining a copy of this software and associated documentation
  7. // files (the "Software"), to deal in the Software without
  8. // restriction, including without limitation the rights to use,
  9. // copy, modify, merge, publish, distribute, sublicense, and/or
  10. // sell copies of the Software, and to permit persons to whom the
  11. // Software is furnished to do so, subject to the following
  12. // conditions:
  13. //
  14. // The above copyright notice and this permission notice shall be
  15. // included in all copies or substantial portions of the Software.
  16. //
  17. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  19. // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  20. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  21. // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  22. // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  23. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  24. // OTHER DEALINGS IN THE SOFTWARE. OF SUCH DAMAGE.
  25. //
  26. // Or:
  27. //
  28. // Distributed under the Boost Software License, Version 1.0.
  29. // (See accompanying file LICENSE_1_0.txt or copy at
  30. // http://www.boost.org/LICENSE_1_0.txt)
  31. #ifndef BOOST_BOYKOV_KOLMOGOROV_MAX_FLOW_HPP
  32. #define BOOST_BOYKOV_KOLMOGOROV_MAX_FLOW_HPP
  33. #include <boost/config.hpp>
  34. #include <boost/assert.hpp>
  35. #include <vector>
  36. #include <list>
  37. #include <utility>
  38. #include <iosfwd>
  39. #include <algorithm> // for std::min and std::max
  40. #include <boost/pending/queue.hpp>
  41. #include <boost/limits.hpp>
  42. #include <boost/property_map/property_map.hpp>
  43. #include <boost/none_t.hpp>
  44. #include <boost/graph/graph_concepts.hpp>
  45. #include <boost/graph/named_function_params.hpp>
  46. #include <boost/graph/lookup_edge.hpp>
  47. #include <boost/concept/assert.hpp>
  48. // The algorithm impelemented here is described in:
  49. //
  50. // Boykov, Y., Kolmogorov, V. "An Experimental Comparison of Min-Cut/Max-Flow
  51. // Algorithms for Energy Minimization in Vision", In IEEE Transactions on
  52. // Pattern Analysis and Machine Intelligence, vol. 26, no. 9, pp. 1124-1137,
  53. // Sep 2004.
  54. //
  55. // For further reading, also see:
  56. //
  57. // Kolmogorov, V. "Graph Based Algorithms for Scene Reconstruction from Two or
  58. // More Views". PhD thesis, Cornell University, Sep 2003.
  59. namespace boost
  60. {
  61. namespace detail
  62. {
  63. template < class Graph, class EdgeCapacityMap,
  64. class ResidualCapacityEdgeMap, class ReverseEdgeMap,
  65. class PredecessorMap, class ColorMap, class DistanceMap,
  66. class IndexMap >
  67. class bk_max_flow
  68. {
  69. typedef
  70. typename property_traits< EdgeCapacityMap >::value_type tEdgeVal;
  71. typedef graph_traits< Graph > tGraphTraits;
  72. typedef typename tGraphTraits::vertex_iterator vertex_iterator;
  73. typedef typename tGraphTraits::vertex_descriptor vertex_descriptor;
  74. typedef typename tGraphTraits::edge_descriptor edge_descriptor;
  75. typedef typename tGraphTraits::edge_iterator edge_iterator;
  76. typedef typename tGraphTraits::out_edge_iterator out_edge_iterator;
  77. typedef boost::queue< vertex_descriptor >
  78. tQueue; // queue of vertices, used in adoption-stage
  79. typedef typename property_traits< ColorMap >::value_type tColorValue;
  80. typedef color_traits< tColorValue > tColorTraits;
  81. typedef
  82. typename property_traits< DistanceMap >::value_type tDistanceVal;
  83. public:
  84. bk_max_flow(Graph& g, EdgeCapacityMap cap, ResidualCapacityEdgeMap res,
  85. ReverseEdgeMap rev, PredecessorMap pre, ColorMap color,
  86. DistanceMap dist, IndexMap idx, vertex_descriptor src,
  87. vertex_descriptor sink)
  88. : m_g(g)
  89. , m_index_map(idx)
  90. , m_cap_map(cap)
  91. , m_res_cap_map(res)
  92. , m_rev_edge_map(rev)
  93. , m_pre_map(pre)
  94. , m_tree_map(color)
  95. , m_dist_map(dist)
  96. , m_source(src)
  97. , m_sink(sink)
  98. , m_active_nodes()
  99. , m_in_active_list_vec(num_vertices(g), false)
  100. , m_in_active_list_map(make_iterator_property_map(
  101. m_in_active_list_vec.begin(), m_index_map))
  102. , m_has_parent_vec(num_vertices(g), false)
  103. , m_has_parent_map(
  104. make_iterator_property_map(m_has_parent_vec.begin(), m_index_map))
  105. , m_time_vec(num_vertices(g), 0)
  106. , m_time_map(
  107. make_iterator_property_map(m_time_vec.begin(), m_index_map))
  108. , m_flow(0)
  109. , m_time(1)
  110. , m_last_grow_vertex(graph_traits< Graph >::null_vertex())
  111. {
  112. // initialize the color-map with gray-values
  113. vertex_iterator vi, v_end;
  114. for (boost::tie(vi, v_end) = vertices(m_g); vi != v_end; ++vi)
  115. {
  116. set_tree(*vi, tColorTraits::gray());
  117. }
  118. // Initialize flow to zero which means initializing
  119. // the residual capacity equal to the capacity
  120. edge_iterator ei, e_end;
  121. for (boost::tie(ei, e_end) = edges(m_g); ei != e_end; ++ei)
  122. {
  123. put(m_res_cap_map, *ei, get(m_cap_map, *ei));
  124. BOOST_ASSERT(get(m_rev_edge_map, get(m_rev_edge_map, *ei))
  125. == *ei); // check if the reverse edge map is build up
  126. // properly
  127. }
  128. // init the search trees with the two terminals
  129. set_tree(m_source, tColorTraits::black());
  130. set_tree(m_sink, tColorTraits::white());
  131. put(m_time_map, m_source, 1);
  132. put(m_time_map, m_sink, 1);
  133. }
  134. tEdgeVal max_flow()
  135. {
  136. // augment direct paths from SOURCE->SINK and SOURCE->VERTEX->SINK
  137. augment_direct_paths();
  138. // start the main-loop
  139. while (true)
  140. {
  141. bool path_found;
  142. edge_descriptor connecting_edge;
  143. boost::tie(connecting_edge, path_found)
  144. = grow(); // find a path from source to sink
  145. if (!path_found)
  146. {
  147. // we're finished, no more paths were found
  148. break;
  149. }
  150. ++m_time;
  151. augment(connecting_edge); // augment that path
  152. adopt(); // rebuild search tree structure
  153. }
  154. return m_flow;
  155. }
  156. // the complete class is protected, as we want access to members in
  157. // derived test-class (see test/boykov_kolmogorov_max_flow_test.cpp)
  158. protected:
  159. void augment_direct_paths()
  160. {
  161. // in a first step, we augment all direct paths from
  162. // source->NODE->sink and additionally paths from source->sink. This
  163. // improves especially graphcuts for segmentation, as most of the
  164. // nodes have source/sink connects but shouldn't have an impact on
  165. // other maxflow problems (this is done in grow() anyway)
  166. out_edge_iterator ei, e_end;
  167. for (boost::tie(ei, e_end) = out_edges(m_source, m_g); ei != e_end;
  168. ++ei)
  169. {
  170. edge_descriptor from_source = *ei;
  171. vertex_descriptor current_node = target(from_source, m_g);
  172. if (current_node == m_sink)
  173. {
  174. tEdgeVal cap = get(m_res_cap_map, from_source);
  175. put(m_res_cap_map, from_source, 0);
  176. m_flow += cap;
  177. continue;
  178. }
  179. edge_descriptor to_sink;
  180. bool is_there;
  181. boost::tie(to_sink, is_there)
  182. = lookup_edge(current_node, m_sink, m_g);
  183. if (is_there)
  184. {
  185. tEdgeVal cap_from_source = get(m_res_cap_map, from_source);
  186. tEdgeVal cap_to_sink = get(m_res_cap_map, to_sink);
  187. if (cap_from_source > cap_to_sink)
  188. {
  189. set_tree(current_node, tColorTraits::black());
  190. add_active_node(current_node);
  191. set_edge_to_parent(current_node, from_source);
  192. put(m_dist_map, current_node, 1);
  193. put(m_time_map, current_node, 1);
  194. // add stuff to flow and update residuals. we dont need
  195. // to update reverse_edges, as incoming/outgoing edges
  196. // to/from source/sink don't count for max-flow
  197. put(m_res_cap_map, from_source,
  198. get(m_res_cap_map, from_source) - cap_to_sink);
  199. put(m_res_cap_map, to_sink, 0);
  200. m_flow += cap_to_sink;
  201. }
  202. else if (cap_to_sink > 0)
  203. {
  204. set_tree(current_node, tColorTraits::white());
  205. add_active_node(current_node);
  206. set_edge_to_parent(current_node, to_sink);
  207. put(m_dist_map, current_node, 1);
  208. put(m_time_map, current_node, 1);
  209. // add stuff to flow and update residuals. we dont need
  210. // to update reverse_edges, as incoming/outgoing edges
  211. // to/from source/sink don't count for max-flow
  212. put(m_res_cap_map, to_sink,
  213. get(m_res_cap_map, to_sink) - cap_from_source);
  214. put(m_res_cap_map, from_source, 0);
  215. m_flow += cap_from_source;
  216. }
  217. }
  218. else if (get(m_res_cap_map, from_source))
  219. {
  220. // there is no sink connect, so we can't augment this path,
  221. // but to avoid adding m_source to the active nodes, we just
  222. // activate this node and set the approciate things
  223. set_tree(current_node, tColorTraits::black());
  224. set_edge_to_parent(current_node, from_source);
  225. put(m_dist_map, current_node, 1);
  226. put(m_time_map, current_node, 1);
  227. add_active_node(current_node);
  228. }
  229. }
  230. for (boost::tie(ei, e_end) = out_edges(m_sink, m_g); ei != e_end;
  231. ++ei)
  232. {
  233. edge_descriptor to_sink = get(m_rev_edge_map, *ei);
  234. vertex_descriptor current_node = source(to_sink, m_g);
  235. if (get(m_res_cap_map, to_sink))
  236. {
  237. set_tree(current_node, tColorTraits::white());
  238. set_edge_to_parent(current_node, to_sink);
  239. put(m_dist_map, current_node, 1);
  240. put(m_time_map, current_node, 1);
  241. add_active_node(current_node);
  242. }
  243. }
  244. }
  245. /**
  246. * Returns a pair of an edge and a boolean. if the bool is true, the
  247. * edge is a connection of a found path from s->t , read "the link" and
  248. * source(returnVal, m_g) is the end of the path found in the
  249. * source-tree target(returnVal, m_g) is the beginning of the path found
  250. * in the sink-tree
  251. */
  252. std::pair< edge_descriptor, bool > grow()
  253. {
  254. BOOST_ASSERT(m_orphans.empty());
  255. vertex_descriptor current_node;
  256. while ((current_node = get_next_active_node())
  257. != graph_traits< Graph >::null_vertex())
  258. { // if there is one
  259. BOOST_ASSERT(get_tree(current_node) != tColorTraits::gray()
  260. && (has_parent(current_node) || current_node == m_source
  261. || current_node == m_sink));
  262. if (get_tree(current_node) == tColorTraits::black())
  263. {
  264. // source tree growing
  265. out_edge_iterator ei, e_end;
  266. if (current_node != m_last_grow_vertex)
  267. {
  268. m_last_grow_vertex = current_node;
  269. boost::tie(m_last_grow_edge_it, m_last_grow_edge_end)
  270. = out_edges(current_node, m_g);
  271. }
  272. for (; m_last_grow_edge_it != m_last_grow_edge_end;
  273. ++m_last_grow_edge_it)
  274. {
  275. edge_descriptor out_edge = *m_last_grow_edge_it;
  276. if (get(m_res_cap_map, out_edge) > 0)
  277. { // check if we have capacity left on this edge
  278. vertex_descriptor other_node
  279. = target(out_edge, m_g);
  280. if (get_tree(other_node) == tColorTraits::gray())
  281. { // it's a free node
  282. set_tree(other_node,
  283. tColorTraits::black()); // aquire other node
  284. // to our search
  285. // tree
  286. set_edge_to_parent(
  287. other_node, out_edge); // set us as parent
  288. put(m_dist_map, other_node,
  289. get(m_dist_map, current_node)
  290. + 1); // and update the
  291. // distance-heuristic
  292. put(m_time_map, other_node,
  293. get(m_time_map, current_node));
  294. add_active_node(other_node);
  295. }
  296. else if (get_tree(other_node)
  297. == tColorTraits::black())
  298. {
  299. // we do this to get shorter paths. check if we
  300. // are nearer to the source as its parent is
  301. if (is_closer_to_terminal(
  302. current_node, other_node))
  303. {
  304. set_edge_to_parent(other_node, out_edge);
  305. put(m_dist_map, other_node,
  306. get(m_dist_map, current_node) + 1);
  307. put(m_time_map, other_node,
  308. get(m_time_map, current_node));
  309. }
  310. }
  311. else
  312. {
  313. BOOST_ASSERT(get_tree(other_node)
  314. == tColorTraits::white());
  315. // kewl, found a path from one to the other
  316. // search tree, return
  317. // the connecting edge in src->sink dir
  318. return std::make_pair(out_edge, true);
  319. }
  320. }
  321. } // for all out-edges
  322. } // source-tree-growing
  323. else
  324. {
  325. BOOST_ASSERT(
  326. get_tree(current_node) == tColorTraits::white());
  327. out_edge_iterator ei, e_end;
  328. if (current_node != m_last_grow_vertex)
  329. {
  330. m_last_grow_vertex = current_node;
  331. boost::tie(m_last_grow_edge_it, m_last_grow_edge_end)
  332. = out_edges(current_node, m_g);
  333. }
  334. for (; m_last_grow_edge_it != m_last_grow_edge_end;
  335. ++m_last_grow_edge_it)
  336. {
  337. edge_descriptor in_edge
  338. = get(m_rev_edge_map, *m_last_grow_edge_it);
  339. if (get(m_res_cap_map, in_edge) > 0)
  340. { // check if there is capacity left
  341. vertex_descriptor other_node = source(in_edge, m_g);
  342. if (get_tree(other_node) == tColorTraits::gray())
  343. { // it's a free node
  344. set_tree(other_node,
  345. tColorTraits::white()); // aquire that node
  346. // to our search
  347. // tree
  348. set_edge_to_parent(
  349. other_node, in_edge); // set us as parent
  350. add_active_node(
  351. other_node); // activate that node
  352. put(m_dist_map, other_node,
  353. get(m_dist_map, current_node)
  354. + 1); // set its distance
  355. put(m_time_map, other_node,
  356. get(m_time_map, current_node)); // and time
  357. }
  358. else if (get_tree(other_node)
  359. == tColorTraits::white())
  360. {
  361. if (is_closer_to_terminal(
  362. current_node, other_node))
  363. {
  364. // we are closer to the sink than its parent
  365. // is, so we "adopt" him
  366. set_edge_to_parent(other_node, in_edge);
  367. put(m_dist_map, other_node,
  368. get(m_dist_map, current_node) + 1);
  369. put(m_time_map, other_node,
  370. get(m_time_map, current_node));
  371. }
  372. }
  373. else
  374. {
  375. BOOST_ASSERT(get_tree(other_node)
  376. == tColorTraits::black());
  377. // kewl, found a path from one to the other
  378. // search tree,
  379. // return the connecting edge in src->sink dir
  380. return std::make_pair(in_edge, true);
  381. }
  382. }
  383. } // for all out-edges
  384. } // sink-tree growing
  385. // all edges of that node are processed, and no more paths were
  386. // found.
  387. // remove if from the front of the active queue
  388. finish_node(current_node);
  389. } // while active_nodes not empty
  390. // no active nodes anymore and no path found, we're done
  391. return std::make_pair(edge_descriptor(), false);
  392. }
  393. /**
  394. * augments path from s->t and updates residual graph
  395. * source(e, m_g) is the end of the path found in the source-tree
  396. * target(e, m_g) is the beginning of the path found in the sink-tree
  397. * this phase generates orphans on satured edges, if the attached verts
  398. * are from different search-trees orphans are ordered in distance to
  399. * sink/source. first the farest from the source are front_inserted into
  400. * the orphans list, and after that the sink-tree-orphans are
  401. * front_inserted. when going to adoption stage the orphans are
  402. * popped_front, and so we process the nearest verts to the terminals
  403. * first
  404. */
  405. void augment(edge_descriptor e)
  406. {
  407. BOOST_ASSERT(get_tree(target(e, m_g)) == tColorTraits::white());
  408. BOOST_ASSERT(get_tree(source(e, m_g)) == tColorTraits::black());
  409. BOOST_ASSERT(m_orphans.empty());
  410. const tEdgeVal bottleneck = find_bottleneck(e);
  411. // now we push the found flow through the path
  412. // for each edge we saturate we have to look for the verts that
  413. // belong to that edge, one of them becomes an orphans now process
  414. // the connecting edge
  415. put(m_res_cap_map, e, get(m_res_cap_map, e) - bottleneck);
  416. BOOST_ASSERT(get(m_res_cap_map, e) >= 0);
  417. put(m_res_cap_map, get(m_rev_edge_map, e),
  418. get(m_res_cap_map, get(m_rev_edge_map, e)) + bottleneck);
  419. // now we follow the path back to the source
  420. vertex_descriptor current_node = source(e, m_g);
  421. while (current_node != m_source)
  422. {
  423. edge_descriptor pred = get_edge_to_parent(current_node);
  424. put(m_res_cap_map, pred, get(m_res_cap_map, pred) - bottleneck);
  425. BOOST_ASSERT(get(m_res_cap_map, pred) >= 0);
  426. put(m_res_cap_map, get(m_rev_edge_map, pred),
  427. get(m_res_cap_map, get(m_rev_edge_map, pred)) + bottleneck);
  428. if (get(m_res_cap_map, pred) == 0)
  429. {
  430. set_no_parent(current_node);
  431. m_orphans.push_front(current_node);
  432. }
  433. current_node = source(pred, m_g);
  434. }
  435. // then go forward in the sink-tree
  436. current_node = target(e, m_g);
  437. while (current_node != m_sink)
  438. {
  439. edge_descriptor pred = get_edge_to_parent(current_node);
  440. put(m_res_cap_map, pred, get(m_res_cap_map, pred) - bottleneck);
  441. BOOST_ASSERT(get(m_res_cap_map, pred) >= 0);
  442. put(m_res_cap_map, get(m_rev_edge_map, pred),
  443. get(m_res_cap_map, get(m_rev_edge_map, pred)) + bottleneck);
  444. if (get(m_res_cap_map, pred) == 0)
  445. {
  446. set_no_parent(current_node);
  447. m_orphans.push_front(current_node);
  448. }
  449. current_node = target(pred, m_g);
  450. }
  451. // and add it to the max-flow
  452. m_flow += bottleneck;
  453. }
  454. /**
  455. * returns the bottleneck of a s->t path (end_of_path is last vertex in
  456. * source-tree, begin_of_path is first vertex in sink-tree)
  457. */
  458. inline tEdgeVal find_bottleneck(edge_descriptor e)
  459. {
  460. BOOST_USING_STD_MIN();
  461. tEdgeVal minimum_cap = get(m_res_cap_map, e);
  462. vertex_descriptor current_node = source(e, m_g);
  463. // first go back in the source tree
  464. while (current_node != m_source)
  465. {
  466. edge_descriptor pred = get_edge_to_parent(current_node);
  467. minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(
  468. minimum_cap, get(m_res_cap_map, pred));
  469. current_node = source(pred, m_g);
  470. }
  471. // then go forward in the sink-tree
  472. current_node = target(e, m_g);
  473. while (current_node != m_sink)
  474. {
  475. edge_descriptor pred = get_edge_to_parent(current_node);
  476. minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(
  477. minimum_cap, get(m_res_cap_map, pred));
  478. current_node = target(pred, m_g);
  479. }
  480. return minimum_cap;
  481. }
  482. /**
  483. * rebuild search trees
  484. * empty the queue of orphans, and find new parents for them or just
  485. * drop them from the search trees
  486. */
  487. void adopt()
  488. {
  489. while (!m_orphans.empty() || !m_child_orphans.empty())
  490. {
  491. vertex_descriptor current_node;
  492. if (m_child_orphans.empty())
  493. {
  494. // get the next orphan from the main-queue and remove it
  495. current_node = m_orphans.front();
  496. m_orphans.pop_front();
  497. }
  498. else
  499. {
  500. current_node = m_child_orphans.front();
  501. m_child_orphans.pop();
  502. }
  503. if (get_tree(current_node) == tColorTraits::black())
  504. {
  505. // we're in the source-tree
  506. tDistanceVal min_distance
  507. = (std::numeric_limits< tDistanceVal >::max)();
  508. edge_descriptor new_parent_edge;
  509. out_edge_iterator ei, e_end;
  510. for (boost::tie(ei, e_end) = out_edges(current_node, m_g);
  511. ei != e_end; ++ei)
  512. {
  513. const edge_descriptor in_edge
  514. = get(m_rev_edge_map, *ei);
  515. BOOST_ASSERT(target(in_edge, m_g)
  516. == current_node); // we should be the target of this
  517. // edge
  518. if (get(m_res_cap_map, in_edge) > 0)
  519. {
  520. vertex_descriptor other_node = source(in_edge, m_g);
  521. if (get_tree(other_node) == tColorTraits::black()
  522. && has_source_connect(other_node))
  523. {
  524. if (get(m_dist_map, other_node) < min_distance)
  525. {
  526. min_distance = get(m_dist_map, other_node);
  527. new_parent_edge = in_edge;
  528. }
  529. }
  530. }
  531. }
  532. if (min_distance
  533. != (std::numeric_limits< tDistanceVal >::max)())
  534. {
  535. set_edge_to_parent(current_node, new_parent_edge);
  536. put(m_dist_map, current_node, min_distance + 1);
  537. put(m_time_map, current_node, m_time);
  538. }
  539. else
  540. {
  541. put(m_time_map, current_node, 0);
  542. for (boost::tie(ei, e_end)
  543. = out_edges(current_node, m_g);
  544. ei != e_end; ++ei)
  545. {
  546. edge_descriptor in_edge = get(m_rev_edge_map, *ei);
  547. vertex_descriptor other_node = source(in_edge, m_g);
  548. if (get_tree(other_node) == tColorTraits::black()
  549. && other_node != m_source)
  550. {
  551. if (get(m_res_cap_map, in_edge) > 0)
  552. {
  553. add_active_node(other_node);
  554. }
  555. if (has_parent(other_node)
  556. && source(
  557. get_edge_to_parent(other_node), m_g)
  558. == current_node)
  559. {
  560. // we are the parent of that node
  561. // it has to find a new parent, too
  562. set_no_parent(other_node);
  563. m_child_orphans.push(other_node);
  564. }
  565. }
  566. }
  567. set_tree(current_node, tColorTraits::gray());
  568. } // no parent found
  569. } // source-tree-adoption
  570. else
  571. {
  572. // now we should be in the sink-tree, check that...
  573. BOOST_ASSERT(
  574. get_tree(current_node) == tColorTraits::white());
  575. out_edge_iterator ei, e_end;
  576. edge_descriptor new_parent_edge;
  577. tDistanceVal min_distance
  578. = (std::numeric_limits< tDistanceVal >::max)();
  579. for (boost::tie(ei, e_end) = out_edges(current_node, m_g);
  580. ei != e_end; ++ei)
  581. {
  582. const edge_descriptor out_edge = *ei;
  583. if (get(m_res_cap_map, out_edge) > 0)
  584. {
  585. const vertex_descriptor other_node
  586. = target(out_edge, m_g);
  587. if (get_tree(other_node) == tColorTraits::white()
  588. && has_sink_connect(other_node))
  589. if (get(m_dist_map, other_node) < min_distance)
  590. {
  591. min_distance = get(m_dist_map, other_node);
  592. new_parent_edge = out_edge;
  593. }
  594. }
  595. }
  596. if (min_distance
  597. != (std::numeric_limits< tDistanceVal >::max)())
  598. {
  599. set_edge_to_parent(current_node, new_parent_edge);
  600. put(m_dist_map, current_node, min_distance + 1);
  601. put(m_time_map, current_node, m_time);
  602. }
  603. else
  604. {
  605. put(m_time_map, current_node, 0);
  606. for (boost::tie(ei, e_end)
  607. = out_edges(current_node, m_g);
  608. ei != e_end; ++ei)
  609. {
  610. const edge_descriptor out_edge = *ei;
  611. const vertex_descriptor other_node
  612. = target(out_edge, m_g);
  613. if (get_tree(other_node) == tColorTraits::white()
  614. && other_node != m_sink)
  615. {
  616. if (get(m_res_cap_map, out_edge) > 0)
  617. {
  618. add_active_node(other_node);
  619. }
  620. if (has_parent(other_node)
  621. && target(
  622. get_edge_to_parent(other_node), m_g)
  623. == current_node)
  624. {
  625. // we were it's parent, so it has to find a
  626. // new one, too
  627. set_no_parent(other_node);
  628. m_child_orphans.push(other_node);
  629. }
  630. }
  631. }
  632. set_tree(current_node, tColorTraits::gray());
  633. } // no parent found
  634. } // sink-tree adoption
  635. } // while !orphans.empty()
  636. } // adopt
  637. /**
  638. * return next active vertex if there is one, otherwise a null_vertex
  639. */
  640. inline vertex_descriptor get_next_active_node()
  641. {
  642. while (true)
  643. {
  644. if (m_active_nodes.empty())
  645. return graph_traits< Graph >::null_vertex();
  646. vertex_descriptor v = m_active_nodes.front();
  647. // if it has no parent, this node can't be active (if its not
  648. // source or sink)
  649. if (!has_parent(v) && v != m_source && v != m_sink)
  650. {
  651. m_active_nodes.pop();
  652. put(m_in_active_list_map, v, false);
  653. }
  654. else
  655. {
  656. BOOST_ASSERT(get_tree(v) == tColorTraits::black()
  657. || get_tree(v) == tColorTraits::white());
  658. return v;
  659. }
  660. }
  661. }
  662. /**
  663. * adds v as an active vertex, but only if its not in the list already
  664. */
  665. inline void add_active_node(vertex_descriptor v)
  666. {
  667. BOOST_ASSERT(get_tree(v) != tColorTraits::gray());
  668. if (get(m_in_active_list_map, v))
  669. {
  670. if (m_last_grow_vertex == v)
  671. {
  672. m_last_grow_vertex = graph_traits< Graph >::null_vertex();
  673. }
  674. return;
  675. }
  676. else
  677. {
  678. put(m_in_active_list_map, v, true);
  679. m_active_nodes.push(v);
  680. }
  681. }
  682. /**
  683. * finish_node removes a node from the front of the active queue (its
  684. * called in grow phase, if no more paths can be found using this node)
  685. */
  686. inline void finish_node(vertex_descriptor v)
  687. {
  688. BOOST_ASSERT(m_active_nodes.front() == v);
  689. m_active_nodes.pop();
  690. put(m_in_active_list_map, v, false);
  691. m_last_grow_vertex = graph_traits< Graph >::null_vertex();
  692. }
  693. /**
  694. * removes a vertex from the queue of active nodes (actually this does
  695. * nothing, but checks if this node has no parent edge, as this is the
  696. * criteria for being no more active)
  697. */
  698. inline void remove_active_node(vertex_descriptor v)
  699. {
  700. BOOST_ASSERT(!has_parent(v));
  701. }
  702. /**
  703. * returns the search tree of v; tColorValue::black() for source tree,
  704. * white() for sink tree, gray() for no tree
  705. */
  706. inline tColorValue get_tree(vertex_descriptor v) const
  707. {
  708. return get(m_tree_map, v);
  709. }
  710. /**
  711. * sets search tree of v; tColorValue::black() for source tree, white()
  712. * for sink tree, gray() for no tree
  713. */
  714. inline void set_tree(vertex_descriptor v, tColorValue t)
  715. {
  716. put(m_tree_map, v, t);
  717. }
  718. /**
  719. * returns edge to parent vertex of v;
  720. */
  721. inline edge_descriptor get_edge_to_parent(vertex_descriptor v) const
  722. {
  723. return get(m_pre_map, v);
  724. }
  725. /**
  726. * returns true if the edge stored in m_pre_map[v] is a valid entry
  727. */
  728. inline bool has_parent(vertex_descriptor v) const
  729. {
  730. return get(m_has_parent_map, v);
  731. }
  732. /**
  733. * sets edge to parent vertex of v;
  734. */
  735. inline void set_edge_to_parent(
  736. vertex_descriptor v, edge_descriptor f_edge_to_parent)
  737. {
  738. BOOST_ASSERT(get(m_res_cap_map, f_edge_to_parent) > 0);
  739. put(m_pre_map, v, f_edge_to_parent);
  740. put(m_has_parent_map, v, true);
  741. }
  742. /**
  743. * removes the edge to parent of v (this is done by invalidating the
  744. * entry an additional map)
  745. */
  746. inline void set_no_parent(vertex_descriptor v)
  747. {
  748. put(m_has_parent_map, v, false);
  749. }
  750. /**
  751. * checks if vertex v has a connect to the sink-vertex (@var m_sink)
  752. * @param v the vertex which is checked
  753. * @return true if a path to the sink was found, false if not
  754. */
  755. inline bool has_sink_connect(vertex_descriptor v)
  756. {
  757. tDistanceVal current_distance = 0;
  758. vertex_descriptor current_vertex = v;
  759. while (true)
  760. {
  761. if (get(m_time_map, current_vertex) == m_time)
  762. {
  763. // we found a node which was already checked this round. use
  764. // it for distance calculations
  765. current_distance += get(m_dist_map, current_vertex);
  766. break;
  767. }
  768. if (current_vertex == m_sink)
  769. {
  770. put(m_time_map, m_sink, m_time);
  771. break;
  772. }
  773. if (has_parent(current_vertex))
  774. {
  775. // it has a parent, so get it
  776. current_vertex
  777. = target(get_edge_to_parent(current_vertex), m_g);
  778. ++current_distance;
  779. }
  780. else
  781. {
  782. // no path found
  783. return false;
  784. }
  785. }
  786. current_vertex = v;
  787. while (get(m_time_map, current_vertex) != m_time)
  788. {
  789. put(m_dist_map, current_vertex, current_distance);
  790. --current_distance;
  791. put(m_time_map, current_vertex, m_time);
  792. current_vertex
  793. = target(get_edge_to_parent(current_vertex), m_g);
  794. }
  795. return true;
  796. }
  797. /**
  798. * checks if vertex v has a connect to the source-vertex (@var m_source)
  799. * @param v the vertex which is checked
  800. * @return true if a path to the source was found, false if not
  801. */
  802. inline bool has_source_connect(vertex_descriptor v)
  803. {
  804. tDistanceVal current_distance = 0;
  805. vertex_descriptor current_vertex = v;
  806. while (true)
  807. {
  808. if (get(m_time_map, current_vertex) == m_time)
  809. {
  810. // we found a node which was already checked this round. use
  811. // it for distance calculations
  812. current_distance += get(m_dist_map, current_vertex);
  813. break;
  814. }
  815. if (current_vertex == m_source)
  816. {
  817. put(m_time_map, m_source, m_time);
  818. break;
  819. }
  820. if (has_parent(current_vertex))
  821. {
  822. // it has a parent, so get it
  823. current_vertex
  824. = source(get_edge_to_parent(current_vertex), m_g);
  825. ++current_distance;
  826. }
  827. else
  828. {
  829. // no path found
  830. return false;
  831. }
  832. }
  833. current_vertex = v;
  834. while (get(m_time_map, current_vertex) != m_time)
  835. {
  836. put(m_dist_map, current_vertex, current_distance);
  837. --current_distance;
  838. put(m_time_map, current_vertex, m_time);
  839. current_vertex
  840. = source(get_edge_to_parent(current_vertex), m_g);
  841. }
  842. return true;
  843. }
  844. /**
  845. * returns true, if p is closer to a terminal than q
  846. */
  847. inline bool is_closer_to_terminal(
  848. vertex_descriptor p, vertex_descriptor q)
  849. {
  850. // checks the timestamps first, to build no cycles, and after that
  851. // the real distance
  852. return (get(m_time_map, q) <= get(m_time_map, p)
  853. && get(m_dist_map, q) > get(m_dist_map, p) + 1);
  854. }
  855. ////////
  856. // member vars
  857. ////////
  858. Graph& m_g;
  859. IndexMap m_index_map;
  860. EdgeCapacityMap m_cap_map;
  861. ResidualCapacityEdgeMap m_res_cap_map;
  862. ReverseEdgeMap m_rev_edge_map;
  863. PredecessorMap m_pre_map; // stores paths found in the growth stage
  864. ColorMap m_tree_map; // maps each vertex into one of the two search tree
  865. // or none (gray())
  866. DistanceMap m_dist_map; // stores distance to source/sink nodes
  867. vertex_descriptor m_source;
  868. vertex_descriptor m_sink;
  869. tQueue m_active_nodes;
  870. std::vector< bool > m_in_active_list_vec;
  871. iterator_property_map< std::vector< bool >::iterator, IndexMap >
  872. m_in_active_list_map;
  873. std::list< vertex_descriptor > m_orphans;
  874. tQueue m_child_orphans; // we use a second queuqe for child orphans, as
  875. // they are FIFO processed
  876. std::vector< bool > m_has_parent_vec;
  877. iterator_property_map< std::vector< bool >::iterator, IndexMap >
  878. m_has_parent_map;
  879. std::vector< long > m_time_vec; // timestamp of each node, used for
  880. // sink/source-path calculations
  881. iterator_property_map< std::vector< long >::iterator, IndexMap >
  882. m_time_map;
  883. tEdgeVal m_flow;
  884. long m_time;
  885. vertex_descriptor m_last_grow_vertex;
  886. out_edge_iterator m_last_grow_edge_it;
  887. out_edge_iterator m_last_grow_edge_end;
  888. };
  889. } // namespace boost::detail
  890. /**
  891. * non-named-parameter version, given everything
  892. * this is the catch all version
  893. */
  894. template < class Graph, class CapacityEdgeMap, class ResidualCapacityEdgeMap,
  895. class ReverseEdgeMap, class PredecessorMap, class ColorMap,
  896. class DistanceMap, class IndexMap >
  897. typename property_traits< CapacityEdgeMap >::value_type
  898. boykov_kolmogorov_max_flow(Graph& g, CapacityEdgeMap cap,
  899. ResidualCapacityEdgeMap res_cap, ReverseEdgeMap rev_map,
  900. PredecessorMap pre_map, ColorMap color, DistanceMap dist, IndexMap idx,
  901. typename graph_traits< Graph >::vertex_descriptor src,
  902. typename graph_traits< Graph >::vertex_descriptor sink)
  903. {
  904. typedef typename graph_traits< Graph >::vertex_descriptor vertex_descriptor;
  905. typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor;
  906. // as this method is the last one before we instantiate the solver, we do
  907. // the concept checks here
  908. BOOST_CONCEPT_ASSERT(
  909. (VertexListGraphConcept< Graph >)); // to have vertices(),
  910. // num_vertices(),
  911. BOOST_CONCEPT_ASSERT((EdgeListGraphConcept< Graph >)); // to have edges()
  912. BOOST_CONCEPT_ASSERT(
  913. (IncidenceGraphConcept< Graph >)); // to have source(), target() and
  914. // out_edges()
  915. BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< CapacityEdgeMap,
  916. edge_descriptor >)); // read flow-values from edges
  917. BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept< ResidualCapacityEdgeMap,
  918. edge_descriptor >)); // write flow-values to residuals
  919. BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< ReverseEdgeMap,
  920. edge_descriptor >)); // read out reverse edges
  921. BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept< PredecessorMap,
  922. vertex_descriptor >)); // store predecessor there
  923. BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept< ColorMap,
  924. vertex_descriptor >)); // write corresponding tree
  925. BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept< DistanceMap,
  926. vertex_descriptor >)); // write distance to source/sink
  927. BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< IndexMap,
  928. vertex_descriptor >)); // get index 0...|V|-1
  929. BOOST_ASSERT(num_vertices(g) >= 2 && src != sink);
  930. detail::bk_max_flow< Graph, CapacityEdgeMap, ResidualCapacityEdgeMap,
  931. ReverseEdgeMap, PredecessorMap, ColorMap, DistanceMap, IndexMap >
  932. algo(g, cap, res_cap, rev_map, pre_map, color, dist, idx, src, sink);
  933. return algo.max_flow();
  934. }
  935. /**
  936. * non-named-parameter version, given capacity, residucal_capacity,
  937. * reverse_edges, and an index map.
  938. */
  939. template < class Graph, class CapacityEdgeMap, class ResidualCapacityEdgeMap,
  940. class ReverseEdgeMap, class IndexMap >
  941. typename property_traits< CapacityEdgeMap >::value_type
  942. boykov_kolmogorov_max_flow(Graph& g, CapacityEdgeMap cap,
  943. ResidualCapacityEdgeMap res_cap, ReverseEdgeMap rev, IndexMap idx,
  944. typename graph_traits< Graph >::vertex_descriptor src,
  945. typename graph_traits< Graph >::vertex_descriptor sink)
  946. {
  947. typename graph_traits< Graph >::vertices_size_type n_verts
  948. = num_vertices(g);
  949. std::vector< typename graph_traits< Graph >::edge_descriptor >
  950. predecessor_vec(n_verts);
  951. std::vector< default_color_type > color_vec(n_verts);
  952. std::vector< typename graph_traits< Graph >::vertices_size_type >
  953. distance_vec(n_verts);
  954. return boykov_kolmogorov_max_flow(g, cap, res_cap, rev,
  955. make_iterator_property_map(predecessor_vec.begin(), idx),
  956. make_iterator_property_map(color_vec.begin(), idx),
  957. make_iterator_property_map(distance_vec.begin(), idx), idx, src, sink);
  958. }
  959. /**
  960. * non-named-parameter version, some given: capacity, residual_capacity,
  961. * reverse_edges, color_map and an index map. Use this if you are interested in
  962. * the minimum cut, as the color map provides that info.
  963. */
  964. template < class Graph, class CapacityEdgeMap, class ResidualCapacityEdgeMap,
  965. class ReverseEdgeMap, class ColorMap, class IndexMap >
  966. typename property_traits< CapacityEdgeMap >::value_type
  967. boykov_kolmogorov_max_flow(Graph& g, CapacityEdgeMap cap,
  968. ResidualCapacityEdgeMap res_cap, ReverseEdgeMap rev, ColorMap color,
  969. IndexMap idx, typename graph_traits< Graph >::vertex_descriptor src,
  970. typename graph_traits< Graph >::vertex_descriptor sink)
  971. {
  972. typename graph_traits< Graph >::vertices_size_type n_verts
  973. = num_vertices(g);
  974. std::vector< typename graph_traits< Graph >::edge_descriptor >
  975. predecessor_vec(n_verts);
  976. std::vector< typename graph_traits< Graph >::vertices_size_type >
  977. distance_vec(n_verts);
  978. return boykov_kolmogorov_max_flow(g, cap, res_cap, rev,
  979. make_iterator_property_map(predecessor_vec.begin(), idx), color,
  980. make_iterator_property_map(distance_vec.begin(), idx), idx, src, sink);
  981. }
  982. /**
  983. * named-parameter version, some given
  984. */
  985. template < class Graph, class P, class T, class R >
  986. typename property_traits<
  987. typename property_map< Graph, edge_capacity_t >::const_type >::value_type
  988. boykov_kolmogorov_max_flow(Graph& g,
  989. typename graph_traits< Graph >::vertex_descriptor src,
  990. typename graph_traits< Graph >::vertex_descriptor sink,
  991. const bgl_named_params< P, T, R >& params)
  992. {
  993. return boykov_kolmogorov_max_flow(g,
  994. choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity),
  995. choose_pmap(get_param(params, edge_residual_capacity), g,
  996. edge_residual_capacity),
  997. choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse),
  998. choose_pmap(
  999. get_param(params, vertex_predecessor), g, vertex_predecessor),
  1000. choose_pmap(get_param(params, vertex_color), g, vertex_color),
  1001. choose_pmap(get_param(params, vertex_distance), g, vertex_distance),
  1002. choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
  1003. src, sink);
  1004. }
  1005. /**
  1006. * named-parameter version, none given
  1007. */
  1008. template < class Graph >
  1009. typename property_traits<
  1010. typename property_map< Graph, edge_capacity_t >::const_type >::value_type
  1011. boykov_kolmogorov_max_flow(Graph& g,
  1012. typename graph_traits< Graph >::vertex_descriptor src,
  1013. typename graph_traits< Graph >::vertex_descriptor sink)
  1014. {
  1015. bgl_named_params< int, buffer_param_t > params(0); // bogus empty param
  1016. return boykov_kolmogorov_max_flow(g, src, sink, params);
  1017. }
  1018. } // namespace boost
  1019. #endif // BOOST_BOYKOV_KOLMOGOROV_MAX_FLOW_HPP