boykov_kolmogorov_max_flow.hpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873
  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. namespace detail {
  61. template <class Graph,
  62. class EdgeCapacityMap,
  63. class ResidualCapacityEdgeMap,
  64. class ReverseEdgeMap,
  65. class PredecessorMap,
  66. class ColorMap,
  67. class DistanceMap,
  68. class IndexMap>
  69. class bk_max_flow {
  70. typedef 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> tQueue; //queue of vertices, used in adoption-stage
  78. typedef typename property_traits<ColorMap>::value_type tColorValue;
  79. typedef color_traits<tColorValue> tColorTraits;
  80. typedef typename property_traits<DistanceMap>::value_type tDistanceVal;
  81. public:
  82. bk_max_flow(Graph& g,
  83. EdgeCapacityMap cap,
  84. ResidualCapacityEdgeMap res,
  85. ReverseEdgeMap rev,
  86. PredecessorMap pre,
  87. ColorMap color,
  88. DistanceMap dist,
  89. IndexMap idx,
  90. vertex_descriptor src,
  91. vertex_descriptor sink):
  92. m_g(g),
  93. m_index_map(idx),
  94. m_cap_map(cap),
  95. m_res_cap_map(res),
  96. m_rev_edge_map(rev),
  97. m_pre_map(pre),
  98. m_tree_map(color),
  99. m_dist_map(dist),
  100. m_source(src),
  101. m_sink(sink),
  102. m_active_nodes(),
  103. m_in_active_list_vec(num_vertices(g), false),
  104. m_in_active_list_map(make_iterator_property_map(m_in_active_list_vec.begin(), m_index_map)),
  105. m_has_parent_vec(num_vertices(g), false),
  106. m_has_parent_map(make_iterator_property_map(m_has_parent_vec.begin(), m_index_map)),
  107. m_time_vec(num_vertices(g), 0),
  108. m_time_map(make_iterator_property_map(m_time_vec.begin(), m_index_map)),
  109. m_flow(0),
  110. m_time(1),
  111. m_last_grow_vertex(graph_traits<Graph>::null_vertex()){
  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. set_tree(*vi, tColorTraits::gray());
  116. }
  117. // Initialize flow to zero which means initializing
  118. // the residual capacity equal to the capacity
  119. edge_iterator ei, e_end;
  120. for(boost::tie(ei, e_end) = edges(m_g); ei != e_end; ++ei) {
  121. put(m_res_cap_map, *ei, get(m_cap_map, *ei));
  122. BOOST_ASSERT(get(m_rev_edge_map, get(m_rev_edge_map, *ei)) == *ei); //check if the reverse edge map is build up properly
  123. }
  124. //init the search trees with the two terminals
  125. set_tree(m_source, tColorTraits::black());
  126. set_tree(m_sink, tColorTraits::white());
  127. put(m_time_map, m_source, 1);
  128. put(m_time_map, m_sink, 1);
  129. }
  130. tEdgeVal max_flow(){
  131. //augment direct paths from SOURCE->SINK and SOURCE->VERTEX->SINK
  132. augment_direct_paths();
  133. //start the main-loop
  134. while(true){
  135. bool path_found;
  136. edge_descriptor connecting_edge;
  137. boost::tie(connecting_edge, path_found) = grow(); //find a path from source to sink
  138. if(!path_found){
  139. //we're finished, no more paths were found
  140. break;
  141. }
  142. ++m_time;
  143. augment(connecting_edge); //augment that path
  144. adopt(); //rebuild search tree structure
  145. }
  146. return m_flow;
  147. }
  148. // the complete class is protected, as we want access to members in
  149. // derived test-class (see test/boykov_kolmogorov_max_flow_test.cpp)
  150. protected:
  151. void augment_direct_paths(){
  152. // in a first step, we augment all direct paths from source->NODE->sink
  153. // and additionally paths from source->sink. This improves especially
  154. // graphcuts for segmentation, as most of the nodes have source/sink
  155. // connects but shouldn't have an impact on other maxflow problems
  156. // (this is done in grow() anyway)
  157. out_edge_iterator ei, e_end;
  158. for(boost::tie(ei, e_end) = out_edges(m_source, m_g); ei != e_end; ++ei){
  159. edge_descriptor from_source = *ei;
  160. vertex_descriptor current_node = target(from_source, m_g);
  161. if(current_node == m_sink){
  162. tEdgeVal cap = get(m_res_cap_map, from_source);
  163. put(m_res_cap_map, from_source, 0);
  164. m_flow += cap;
  165. continue;
  166. }
  167. edge_descriptor to_sink;
  168. bool is_there;
  169. boost::tie(to_sink, is_there) = lookup_edge(current_node, m_sink, m_g);
  170. if(is_there){
  171. tEdgeVal cap_from_source = get(m_res_cap_map, from_source);
  172. tEdgeVal cap_to_sink = get(m_res_cap_map, to_sink);
  173. if(cap_from_source > cap_to_sink){
  174. set_tree(current_node, tColorTraits::black());
  175. add_active_node(current_node);
  176. set_edge_to_parent(current_node, from_source);
  177. put(m_dist_map, current_node, 1);
  178. put(m_time_map, current_node, 1);
  179. // add stuff to flow and update residuals. we dont need to
  180. // update reverse_edges, as incoming/outgoing edges to/from
  181. // source/sink don't count for max-flow
  182. put(m_res_cap_map, from_source, get(m_res_cap_map, from_source) - cap_to_sink);
  183. put(m_res_cap_map, to_sink, 0);
  184. m_flow += cap_to_sink;
  185. } else if(cap_to_sink > 0){
  186. set_tree(current_node, tColorTraits::white());
  187. add_active_node(current_node);
  188. set_edge_to_parent(current_node, to_sink);
  189. put(m_dist_map, current_node, 1);
  190. put(m_time_map, current_node, 1);
  191. // add stuff to flow and update residuals. we dont need to update
  192. // reverse_edges, as incoming/outgoing edges to/from source/sink
  193. // don't count for max-flow
  194. put(m_res_cap_map, to_sink, get(m_res_cap_map, to_sink) - cap_from_source);
  195. put(m_res_cap_map, from_source, 0);
  196. m_flow += cap_from_source;
  197. }
  198. } else if(get(m_res_cap_map, from_source)){
  199. // there is no sink connect, so we can't augment this path, but to
  200. // avoid adding m_source to the active nodes, we just activate this
  201. // node and set the approciate things
  202. set_tree(current_node, tColorTraits::black());
  203. set_edge_to_parent(current_node, from_source);
  204. put(m_dist_map, current_node, 1);
  205. put(m_time_map, current_node, 1);
  206. add_active_node(current_node);
  207. }
  208. }
  209. for(boost::tie(ei, e_end) = out_edges(m_sink, m_g); ei != e_end; ++ei){
  210. edge_descriptor to_sink = get(m_rev_edge_map, *ei);
  211. vertex_descriptor current_node = source(to_sink, m_g);
  212. if(get(m_res_cap_map, to_sink)){
  213. set_tree(current_node, tColorTraits::white());
  214. set_edge_to_parent(current_node, to_sink);
  215. put(m_dist_map, current_node, 1);
  216. put(m_time_map, current_node, 1);
  217. add_active_node(current_node);
  218. }
  219. }
  220. }
  221. /**
  222. * Returns a pair of an edge and a boolean. if the bool is true, the
  223. * edge is a connection of a found path from s->t , read "the link" and
  224. * source(returnVal, m_g) is the end of the path found in the source-tree
  225. * target(returnVal, m_g) is the beginning of the path found in the sink-tree
  226. */
  227. std::pair<edge_descriptor, bool> grow(){
  228. BOOST_ASSERT(m_orphans.empty());
  229. vertex_descriptor current_node;
  230. while((current_node = get_next_active_node()) != graph_traits<Graph>::null_vertex()){ //if there is one
  231. BOOST_ASSERT(get_tree(current_node) != tColorTraits::gray() &&
  232. (has_parent(current_node) ||
  233. current_node == m_source ||
  234. current_node == m_sink));
  235. if(get_tree(current_node) == tColorTraits::black()){
  236. //source tree growing
  237. out_edge_iterator ei, e_end;
  238. if(current_node != m_last_grow_vertex){
  239. m_last_grow_vertex = current_node;
  240. boost::tie(m_last_grow_edge_it, m_last_grow_edge_end) = out_edges(current_node, m_g);
  241. }
  242. for(; m_last_grow_edge_it != m_last_grow_edge_end; ++m_last_grow_edge_it) {
  243. edge_descriptor out_edge = *m_last_grow_edge_it;
  244. if(get(m_res_cap_map, out_edge) > 0){ //check if we have capacity left on this edge
  245. vertex_descriptor other_node = target(out_edge, m_g);
  246. if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node
  247. set_tree(other_node, tColorTraits::black()); //aquire other node to our search tree
  248. set_edge_to_parent(other_node, out_edge); //set us as parent
  249. put(m_dist_map, other_node, get(m_dist_map, current_node) + 1); //and update the distance-heuristic
  250. put(m_time_map, other_node, get(m_time_map, current_node));
  251. add_active_node(other_node);
  252. } else if(get_tree(other_node) == tColorTraits::black()) {
  253. // we do this to get shorter paths. check if we are nearer to
  254. // the source as its parent is
  255. if(is_closer_to_terminal(current_node, other_node)){
  256. set_edge_to_parent(other_node, out_edge);
  257. put(m_dist_map, other_node, get(m_dist_map, current_node) + 1);
  258. put(m_time_map, other_node, get(m_time_map, current_node));
  259. }
  260. } else{
  261. BOOST_ASSERT(get_tree(other_node)==tColorTraits::white());
  262. //kewl, found a path from one to the other search tree, return
  263. // the connecting edge in src->sink dir
  264. return std::make_pair(out_edge, true);
  265. }
  266. }
  267. } //for all out-edges
  268. } //source-tree-growing
  269. else{
  270. BOOST_ASSERT(get_tree(current_node) == tColorTraits::white());
  271. out_edge_iterator ei, e_end;
  272. if(current_node != m_last_grow_vertex){
  273. m_last_grow_vertex = current_node;
  274. boost::tie(m_last_grow_edge_it, m_last_grow_edge_end) = out_edges(current_node, m_g);
  275. }
  276. for(; m_last_grow_edge_it != m_last_grow_edge_end; ++m_last_grow_edge_it){
  277. edge_descriptor in_edge = get(m_rev_edge_map, *m_last_grow_edge_it);
  278. if(get(m_res_cap_map, in_edge) > 0){ //check if there is capacity left
  279. vertex_descriptor other_node = source(in_edge, m_g);
  280. if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node
  281. set_tree(other_node, tColorTraits::white()); //aquire that node to our search tree
  282. set_edge_to_parent(other_node, in_edge); //set us as parent
  283. add_active_node(other_node); //activate that node
  284. put(m_dist_map, other_node, get(m_dist_map, current_node) + 1); //set its distance
  285. put(m_time_map, other_node, get(m_time_map, current_node));//and time
  286. } else if(get_tree(other_node) == tColorTraits::white()){
  287. if(is_closer_to_terminal(current_node, other_node)){
  288. //we are closer to the sink than its parent is, so we "adopt" him
  289. set_edge_to_parent(other_node, in_edge);
  290. put(m_dist_map, other_node, get(m_dist_map, current_node) + 1);
  291. put(m_time_map, other_node, get(m_time_map, current_node));
  292. }
  293. } else{
  294. BOOST_ASSERT(get_tree(other_node)==tColorTraits::black());
  295. //kewl, found a path from one to the other search tree,
  296. // return the connecting edge in src->sink dir
  297. return std::make_pair(in_edge, true);
  298. }
  299. }
  300. } //for all out-edges
  301. } //sink-tree growing
  302. //all edges of that node are processed, and no more paths were found.
  303. // remove if from the front of the active queue
  304. finish_node(current_node);
  305. } //while active_nodes not empty
  306. //no active nodes anymore and no path found, we're done
  307. return std::make_pair(edge_descriptor(), false);
  308. }
  309. /**
  310. * augments path from s->t and updates residual graph
  311. * source(e, m_g) is the end of the path found in the source-tree
  312. * target(e, m_g) is the beginning of the path found in the sink-tree
  313. * this phase generates orphans on satured edges, if the attached verts are
  314. * from different search-trees orphans are ordered in distance to
  315. * sink/source. first the farest from the source are front_inserted into
  316. * the orphans list, and after that the sink-tree-orphans are
  317. * front_inserted. when going to adoption stage the orphans are popped_front,
  318. * and so we process the nearest verts to the terminals first
  319. */
  320. void augment(edge_descriptor e) {
  321. BOOST_ASSERT(get_tree(target(e, m_g)) == tColorTraits::white());
  322. BOOST_ASSERT(get_tree(source(e, m_g)) == tColorTraits::black());
  323. BOOST_ASSERT(m_orphans.empty());
  324. const tEdgeVal bottleneck = find_bottleneck(e);
  325. //now we push the found flow through the path
  326. //for each edge we saturate we have to look for the verts that belong to that edge, one of them becomes an orphans
  327. //now process the connecting edge
  328. put(m_res_cap_map, e, get(m_res_cap_map, e) - bottleneck);
  329. BOOST_ASSERT(get(m_res_cap_map, e) >= 0);
  330. put(m_res_cap_map, get(m_rev_edge_map, e), get(m_res_cap_map, get(m_rev_edge_map, e)) + bottleneck);
  331. //now we follow the path back to the source
  332. vertex_descriptor current_node = source(e, m_g);
  333. while(current_node != m_source){
  334. edge_descriptor pred = get_edge_to_parent(current_node);
  335. put(m_res_cap_map, pred, get(m_res_cap_map, pred) - bottleneck);
  336. BOOST_ASSERT(get(m_res_cap_map, pred) >= 0);
  337. put(m_res_cap_map, get(m_rev_edge_map, pred), get(m_res_cap_map, get(m_rev_edge_map, pred)) + bottleneck);
  338. if(get(m_res_cap_map, pred) == 0){
  339. set_no_parent(current_node);
  340. m_orphans.push_front(current_node);
  341. }
  342. current_node = source(pred, m_g);
  343. }
  344. //then go forward in the sink-tree
  345. current_node = target(e, m_g);
  346. while(current_node != m_sink){
  347. edge_descriptor pred = get_edge_to_parent(current_node);
  348. put(m_res_cap_map, pred, get(m_res_cap_map, pred) - bottleneck);
  349. BOOST_ASSERT(get(m_res_cap_map, pred) >= 0);
  350. put(m_res_cap_map, get(m_rev_edge_map, pred), get(m_res_cap_map, get(m_rev_edge_map, pred)) + bottleneck);
  351. if(get(m_res_cap_map, pred) == 0){
  352. set_no_parent(current_node);
  353. m_orphans.push_front(current_node);
  354. }
  355. current_node = target(pred, m_g);
  356. }
  357. //and add it to the max-flow
  358. m_flow += bottleneck;
  359. }
  360. /**
  361. * returns the bottleneck of a s->t path (end_of_path is last vertex in
  362. * source-tree, begin_of_path is first vertex in sink-tree)
  363. */
  364. inline tEdgeVal find_bottleneck(edge_descriptor e){
  365. BOOST_USING_STD_MIN();
  366. tEdgeVal minimum_cap = get(m_res_cap_map, e);
  367. vertex_descriptor current_node = source(e, m_g);
  368. //first go back in the source tree
  369. while(current_node != m_source){
  370. edge_descriptor pred = get_edge_to_parent(current_node);
  371. minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, get(m_res_cap_map, pred));
  372. current_node = source(pred, m_g);
  373. }
  374. //then go forward in the sink-tree
  375. current_node = target(e, m_g);
  376. while(current_node != m_sink){
  377. edge_descriptor pred = get_edge_to_parent(current_node);
  378. minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, get(m_res_cap_map, pred));
  379. current_node = target(pred, m_g);
  380. }
  381. return minimum_cap;
  382. }
  383. /**
  384. * rebuild search trees
  385. * empty the queue of orphans, and find new parents for them or just drop
  386. * them from the search trees
  387. */
  388. void adopt(){
  389. while(!m_orphans.empty() || !m_child_orphans.empty()){
  390. vertex_descriptor current_node;
  391. if(m_child_orphans.empty()){
  392. //get the next orphan from the main-queue and remove it
  393. current_node = m_orphans.front();
  394. m_orphans.pop_front();
  395. } else{
  396. current_node = m_child_orphans.front();
  397. m_child_orphans.pop();
  398. }
  399. if(get_tree(current_node) == tColorTraits::black()){
  400. //we're in the source-tree
  401. tDistanceVal min_distance = (std::numeric_limits<tDistanceVal>::max)();
  402. edge_descriptor new_parent_edge;
  403. out_edge_iterator ei, e_end;
  404. for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
  405. const edge_descriptor in_edge = get(m_rev_edge_map, *ei);
  406. BOOST_ASSERT(target(in_edge, m_g) == current_node); //we should be the target of this edge
  407. if(get(m_res_cap_map, in_edge) > 0){
  408. vertex_descriptor other_node = source(in_edge, m_g);
  409. if(get_tree(other_node) == tColorTraits::black() && has_source_connect(other_node)){
  410. if(get(m_dist_map, other_node) < min_distance){
  411. min_distance = get(m_dist_map, other_node);
  412. new_parent_edge = in_edge;
  413. }
  414. }
  415. }
  416. }
  417. if(min_distance != (std::numeric_limits<tDistanceVal>::max)()){
  418. set_edge_to_parent(current_node, new_parent_edge);
  419. put(m_dist_map, current_node, min_distance + 1);
  420. put(m_time_map, current_node, m_time);
  421. } else{
  422. put(m_time_map, current_node, 0);
  423. for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
  424. edge_descriptor in_edge = get(m_rev_edge_map, *ei);
  425. vertex_descriptor other_node = source(in_edge, m_g);
  426. if(get_tree(other_node) == tColorTraits::black() && other_node != m_source){
  427. if(get(m_res_cap_map, in_edge) > 0){
  428. add_active_node(other_node);
  429. }
  430. if(has_parent(other_node) && source(get_edge_to_parent(other_node), m_g) == current_node){
  431. //we are the parent of that node
  432. //it has to find a new parent, too
  433. set_no_parent(other_node);
  434. m_child_orphans.push(other_node);
  435. }
  436. }
  437. }
  438. set_tree(current_node, tColorTraits::gray());
  439. } //no parent found
  440. } //source-tree-adoption
  441. else{
  442. //now we should be in the sink-tree, check that...
  443. BOOST_ASSERT(get_tree(current_node) == tColorTraits::white());
  444. out_edge_iterator ei, e_end;
  445. edge_descriptor new_parent_edge;
  446. tDistanceVal min_distance = (std::numeric_limits<tDistanceVal>::max)();
  447. for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
  448. const edge_descriptor out_edge = *ei;
  449. if(get(m_res_cap_map, out_edge) > 0){
  450. const vertex_descriptor other_node = target(out_edge, m_g);
  451. if(get_tree(other_node) == tColorTraits::white() && has_sink_connect(other_node))
  452. if(get(m_dist_map, other_node) < min_distance){
  453. min_distance = get(m_dist_map, other_node);
  454. new_parent_edge = out_edge;
  455. }
  456. }
  457. }
  458. if(min_distance != (std::numeric_limits<tDistanceVal>::max)()){
  459. set_edge_to_parent(current_node, new_parent_edge);
  460. put(m_dist_map, current_node, min_distance + 1);
  461. put(m_time_map, current_node, m_time);
  462. } else{
  463. put(m_time_map, current_node, 0);
  464. for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
  465. const edge_descriptor out_edge = *ei;
  466. const vertex_descriptor other_node = target(out_edge, m_g);
  467. if(get_tree(other_node) == tColorTraits::white() && other_node != m_sink){
  468. if(get(m_res_cap_map, out_edge) > 0){
  469. add_active_node(other_node);
  470. }
  471. if(has_parent(other_node) && target(get_edge_to_parent(other_node), m_g) == current_node){
  472. //we were it's parent, so it has to find a new one, too
  473. set_no_parent(other_node);
  474. m_child_orphans.push(other_node);
  475. }
  476. }
  477. }
  478. set_tree(current_node, tColorTraits::gray());
  479. } //no parent found
  480. } //sink-tree adoption
  481. } //while !orphans.empty()
  482. } //adopt
  483. /**
  484. * return next active vertex if there is one, otherwise a null_vertex
  485. */
  486. inline vertex_descriptor get_next_active_node(){
  487. while(true){
  488. if(m_active_nodes.empty())
  489. return graph_traits<Graph>::null_vertex();
  490. vertex_descriptor v = m_active_nodes.front();
  491. //if it has no parent, this node can't be active (if its not source or sink)
  492. if(!has_parent(v) && v != m_source && v != m_sink){
  493. m_active_nodes.pop();
  494. put(m_in_active_list_map, v, false);
  495. } else{
  496. BOOST_ASSERT(get_tree(v) == tColorTraits::black() || get_tree(v) == tColorTraits::white());
  497. return v;
  498. }
  499. }
  500. }
  501. /**
  502. * adds v as an active vertex, but only if its not in the list already
  503. */
  504. inline void add_active_node(vertex_descriptor v){
  505. BOOST_ASSERT(get_tree(v) != tColorTraits::gray());
  506. if(get(m_in_active_list_map, v)){
  507. if (m_last_grow_vertex == v) {
  508. m_last_grow_vertex = graph_traits<Graph>::null_vertex();
  509. }
  510. return;
  511. } else{
  512. put(m_in_active_list_map, v, true);
  513. m_active_nodes.push(v);
  514. }
  515. }
  516. /**
  517. * finish_node removes a node from the front of the active queue (its called in grow phase, if no more paths can be found using this node)
  518. */
  519. inline void finish_node(vertex_descriptor v){
  520. BOOST_ASSERT(m_active_nodes.front() == v);
  521. m_active_nodes.pop();
  522. put(m_in_active_list_map, v, false);
  523. m_last_grow_vertex = graph_traits<Graph>::null_vertex();
  524. }
  525. /**
  526. * removes a vertex from the queue of active nodes (actually this does nothing,
  527. * but checks if this node has no parent edge, as this is the criteria for
  528. * being no more active)
  529. */
  530. inline void remove_active_node(vertex_descriptor v){
  531. BOOST_ASSERT(!has_parent(v));
  532. }
  533. /**
  534. * returns the search tree of v; tColorValue::black() for source tree,
  535. * white() for sink tree, gray() for no tree
  536. */
  537. inline tColorValue get_tree(vertex_descriptor v) const {
  538. return get(m_tree_map, v);
  539. }
  540. /**
  541. * sets search tree of v; tColorValue::black() for source tree, white()
  542. * for sink tree, gray() for no tree
  543. */
  544. inline void set_tree(vertex_descriptor v, tColorValue t){
  545. put(m_tree_map, v, t);
  546. }
  547. /**
  548. * returns edge to parent vertex of v;
  549. */
  550. inline edge_descriptor get_edge_to_parent(vertex_descriptor v) const{
  551. return get(m_pre_map, v);
  552. }
  553. /**
  554. * returns true if the edge stored in m_pre_map[v] is a valid entry
  555. */
  556. inline bool has_parent(vertex_descriptor v) const{
  557. return get(m_has_parent_map, v);
  558. }
  559. /**
  560. * sets edge to parent vertex of v;
  561. */
  562. inline void set_edge_to_parent(vertex_descriptor v, edge_descriptor f_edge_to_parent){
  563. BOOST_ASSERT(get(m_res_cap_map, f_edge_to_parent) > 0);
  564. put(m_pre_map, v, f_edge_to_parent);
  565. put(m_has_parent_map, v, true);
  566. }
  567. /**
  568. * removes the edge to parent of v (this is done by invalidating the
  569. * entry an additional map)
  570. */
  571. inline void set_no_parent(vertex_descriptor v){
  572. put(m_has_parent_map, v, false);
  573. }
  574. /**
  575. * checks if vertex v has a connect to the sink-vertex (@var m_sink)
  576. * @param v the vertex which is checked
  577. * @return true if a path to the sink was found, false if not
  578. */
  579. inline bool has_sink_connect(vertex_descriptor v){
  580. tDistanceVal current_distance = 0;
  581. vertex_descriptor current_vertex = v;
  582. while(true){
  583. if(get(m_time_map, current_vertex) == m_time){
  584. //we found a node which was already checked this round. use it for distance calculations
  585. current_distance += get(m_dist_map, current_vertex);
  586. break;
  587. }
  588. if(current_vertex == m_sink){
  589. put(m_time_map, m_sink, m_time);
  590. break;
  591. }
  592. if(has_parent(current_vertex)){
  593. //it has a parent, so get it
  594. current_vertex = target(get_edge_to_parent(current_vertex), m_g);
  595. ++current_distance;
  596. } else{
  597. //no path found
  598. return false;
  599. }
  600. }
  601. current_vertex=v;
  602. while(get(m_time_map, current_vertex) != m_time){
  603. put(m_dist_map, current_vertex, current_distance);
  604. --current_distance;
  605. put(m_time_map, current_vertex, m_time);
  606. current_vertex = target(get_edge_to_parent(current_vertex), m_g);
  607. }
  608. return true;
  609. }
  610. /**
  611. * checks if vertex v has a connect to the source-vertex (@var m_source)
  612. * @param v the vertex which is checked
  613. * @return true if a path to the source was found, false if not
  614. */
  615. inline bool has_source_connect(vertex_descriptor v){
  616. tDistanceVal current_distance = 0;
  617. vertex_descriptor current_vertex = v;
  618. while(true){
  619. if(get(m_time_map, current_vertex) == m_time){
  620. //we found a node which was already checked this round. use it for distance calculations
  621. current_distance += get(m_dist_map, current_vertex);
  622. break;
  623. }
  624. if(current_vertex == m_source){
  625. put(m_time_map, m_source, m_time);
  626. break;
  627. }
  628. if(has_parent(current_vertex)){
  629. //it has a parent, so get it
  630. current_vertex = source(get_edge_to_parent(current_vertex), m_g);
  631. ++current_distance;
  632. } else{
  633. //no path found
  634. return false;
  635. }
  636. }
  637. current_vertex=v;
  638. while(get(m_time_map, current_vertex) != m_time){
  639. put(m_dist_map, current_vertex, current_distance);
  640. --current_distance;
  641. put(m_time_map, current_vertex, m_time);
  642. current_vertex = source(get_edge_to_parent(current_vertex), m_g);
  643. }
  644. return true;
  645. }
  646. /**
  647. * returns true, if p is closer to a terminal than q
  648. */
  649. inline bool is_closer_to_terminal(vertex_descriptor p, vertex_descriptor q){
  650. //checks the timestamps first, to build no cycles, and after that the real distance
  651. return (get(m_time_map, q) <= get(m_time_map, p) &&
  652. get(m_dist_map, q) > get(m_dist_map, p)+1);
  653. }
  654. ////////
  655. // member vars
  656. ////////
  657. Graph& m_g;
  658. IndexMap m_index_map;
  659. EdgeCapacityMap m_cap_map;
  660. ResidualCapacityEdgeMap m_res_cap_map;
  661. ReverseEdgeMap m_rev_edge_map;
  662. PredecessorMap m_pre_map; //stores paths found in the growth stage
  663. ColorMap m_tree_map; //maps each vertex into one of the two search tree or none (gray())
  664. DistanceMap m_dist_map; //stores distance to source/sink nodes
  665. vertex_descriptor m_source;
  666. vertex_descriptor m_sink;
  667. tQueue m_active_nodes;
  668. std::vector<bool> m_in_active_list_vec;
  669. iterator_property_map<std::vector<bool>::iterator, IndexMap> m_in_active_list_map;
  670. std::list<vertex_descriptor> m_orphans;
  671. tQueue m_child_orphans; // we use a second queuqe for child orphans, as they are FIFO processed
  672. std::vector<bool> m_has_parent_vec;
  673. iterator_property_map<std::vector<bool>::iterator, IndexMap> m_has_parent_map;
  674. std::vector<long> m_time_vec; //timestamp of each node, used for sink/source-path calculations
  675. iterator_property_map<std::vector<long>::iterator, IndexMap> m_time_map;
  676. tEdgeVal m_flow;
  677. long m_time;
  678. vertex_descriptor m_last_grow_vertex;
  679. out_edge_iterator m_last_grow_edge_it;
  680. out_edge_iterator m_last_grow_edge_end;
  681. };
  682. } //namespace boost::detail
  683. /**
  684. * non-named-parameter version, given everything
  685. * this is the catch all version
  686. */
  687. template<class Graph,
  688. class CapacityEdgeMap,
  689. class ResidualCapacityEdgeMap,
  690. class ReverseEdgeMap, class PredecessorMap,
  691. class ColorMap,
  692. class DistanceMap,
  693. class IndexMap>
  694. typename property_traits<CapacityEdgeMap>::value_type
  695. boykov_kolmogorov_max_flow(Graph& g,
  696. CapacityEdgeMap cap,
  697. ResidualCapacityEdgeMap res_cap,
  698. ReverseEdgeMap rev_map,
  699. PredecessorMap pre_map,
  700. ColorMap color,
  701. DistanceMap dist,
  702. IndexMap idx,
  703. typename graph_traits<Graph>::vertex_descriptor src,
  704. typename graph_traits<Graph>::vertex_descriptor sink)
  705. {
  706. typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
  707. typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
  708. //as this method is the last one before we instantiate the solver, we do the concept checks here
  709. BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> )); //to have vertices(), num_vertices(),
  710. BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<Graph> )); //to have edges()
  711. BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<Graph> )); //to have source(), target() and out_edges()
  712. BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<CapacityEdgeMap, edge_descriptor> )); //read flow-values from edges
  713. BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<ResidualCapacityEdgeMap, edge_descriptor> )); //write flow-values to residuals
  714. BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<ReverseEdgeMap, edge_descriptor> )); //read out reverse edges
  715. BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<PredecessorMap, vertex_descriptor> )); //store predecessor there
  716. BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<ColorMap, vertex_descriptor> )); //write corresponding tree
  717. BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<DistanceMap, vertex_descriptor> )); //write distance to source/sink
  718. BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<IndexMap, vertex_descriptor> )); //get index 0...|V|-1
  719. BOOST_ASSERT(num_vertices(g) >= 2 && src != sink);
  720. detail::bk_max_flow<
  721. Graph, CapacityEdgeMap, ResidualCapacityEdgeMap, ReverseEdgeMap,
  722. PredecessorMap, ColorMap, DistanceMap, IndexMap
  723. > algo(g, cap, res_cap, rev_map, pre_map, color, dist, idx, src, sink);
  724. return algo.max_flow();
  725. }
  726. /**
  727. * non-named-parameter version, given capacity, residucal_capacity,
  728. * reverse_edges, and an index map.
  729. */
  730. template<class Graph,
  731. class CapacityEdgeMap,
  732. class ResidualCapacityEdgeMap,
  733. class ReverseEdgeMap,
  734. class IndexMap>
  735. typename property_traits<CapacityEdgeMap>::value_type
  736. boykov_kolmogorov_max_flow(Graph& g,
  737. CapacityEdgeMap cap,
  738. ResidualCapacityEdgeMap res_cap,
  739. ReverseEdgeMap rev,
  740. IndexMap idx,
  741. typename graph_traits<Graph>::vertex_descriptor src,
  742. typename graph_traits<Graph>::vertex_descriptor sink)
  743. {
  744. typename graph_traits<Graph>::vertices_size_type n_verts = num_vertices(g);
  745. std::vector<typename graph_traits<Graph>::edge_descriptor> predecessor_vec(n_verts);
  746. std::vector<default_color_type> color_vec(n_verts);
  747. std::vector<typename graph_traits<Graph>::vertices_size_type> distance_vec(n_verts);
  748. return
  749. boykov_kolmogorov_max_flow(
  750. g, cap, res_cap, rev,
  751. make_iterator_property_map(predecessor_vec.begin(), idx),
  752. make_iterator_property_map(color_vec.begin(), idx),
  753. make_iterator_property_map(distance_vec.begin(), idx),
  754. idx, src, sink);
  755. }
  756. /**
  757. * non-named-parameter version, some given: capacity, residual_capacity,
  758. * reverse_edges, color_map and an index map. Use this if you are interested in
  759. * the minimum cut, as the color map provides that info.
  760. */
  761. template<class Graph,
  762. class CapacityEdgeMap,
  763. class ResidualCapacityEdgeMap,
  764. class ReverseEdgeMap,
  765. class ColorMap,
  766. class IndexMap>
  767. typename property_traits<CapacityEdgeMap>::value_type
  768. boykov_kolmogorov_max_flow(Graph& g,
  769. CapacityEdgeMap cap,
  770. ResidualCapacityEdgeMap res_cap,
  771. ReverseEdgeMap rev,
  772. ColorMap color,
  773. IndexMap idx,
  774. typename graph_traits<Graph>::vertex_descriptor src,
  775. typename graph_traits<Graph>::vertex_descriptor sink)
  776. {
  777. typename graph_traits<Graph>::vertices_size_type n_verts = num_vertices(g);
  778. std::vector<typename graph_traits<Graph>::edge_descriptor> predecessor_vec(n_verts);
  779. std::vector<typename graph_traits<Graph>::vertices_size_type> distance_vec(n_verts);
  780. return
  781. boykov_kolmogorov_max_flow(
  782. g, cap, res_cap, rev,
  783. make_iterator_property_map(predecessor_vec.begin(), idx),
  784. color,
  785. make_iterator_property_map(distance_vec.begin(), idx),
  786. idx, src, sink);
  787. }
  788. /**
  789. * named-parameter version, some given
  790. */
  791. template<class Graph, class P, class T, class R>
  792. typename property_traits<typename property_map<Graph, edge_capacity_t>::const_type>::value_type
  793. boykov_kolmogorov_max_flow(Graph& g,
  794. typename graph_traits<Graph>::vertex_descriptor src,
  795. typename graph_traits<Graph>::vertex_descriptor sink,
  796. const bgl_named_params<P, T, R>& params)
  797. {
  798. return
  799. boykov_kolmogorov_max_flow(
  800. g,
  801. choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity),
  802. choose_pmap(get_param(params, edge_residual_capacity), g, edge_residual_capacity),
  803. choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse),
  804. choose_pmap(get_param(params, vertex_predecessor), g, vertex_predecessor),
  805. choose_pmap(get_param(params, vertex_color), g, vertex_color),
  806. choose_pmap(get_param(params, vertex_distance), g, vertex_distance),
  807. choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
  808. src, sink);
  809. }
  810. /**
  811. * named-parameter version, none given
  812. */
  813. template<class Graph>
  814. typename property_traits<typename property_map<Graph, edge_capacity_t>::const_type>::value_type
  815. boykov_kolmogorov_max_flow(Graph& g,
  816. typename graph_traits<Graph>::vertex_descriptor src,
  817. typename graph_traits<Graph>::vertex_descriptor sink)
  818. {
  819. bgl_named_params<int, buffer_param_t> params(0); // bogus empty param
  820. return boykov_kolmogorov_max_flow(g, src, sink, params);
  821. }
  822. } // namespace boost
  823. #endif // BOOST_BOYKOV_KOLMOGOROV_MAX_FLOW_HPP