Krita Source Code Documentation
Loading...
Searching...
No Matches
patched_boykov_kolmogorov_max_flow.hpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2006 Stephan Diederich
2//
3// This code may be used under either of the following two licences:
4//
5// SPDX-License-Identifier: MIT OR BSL-1.0
6
7#ifndef BOOST_BOYKOV_KOLMOGOROV_MAX_FLOW_HPP
8#define BOOST_BOYKOV_KOLMOGOROV_MAX_FLOW_HPP
9
10#include <boost/config.hpp>
11#include <boost/assert.hpp>
12#include <vector>
13#include <list>
14#include <utility>
15#include <iosfwd>
16#include <algorithm> // for std::min and std::max
17
18#include <boost/pending/queue.hpp>
19#include <boost/limits.hpp>
20#include <boost/property_map/property_map.hpp>
21#include <boost/none_t.hpp>
22#include <boost/graph/graph_concepts.hpp>
23#include <boost/graph/named_function_params.hpp>
24#include <boost/graph/lookup_edge.hpp>
25#include <boost/concept/assert.hpp>
26
27// The algorithm implemented here is described in:
28//
29// Boykov, Y., Kolmogorov, V. "An Experimental Comparison of Min-Cut/Max-Flow
30// Algorithms for Energy Minimization in Vision", In IEEE Transactions on
31// Pattern Analysis and Machine Intelligence, vol. 26, no. 9, pp. 1124-1137,
32// Sep 2004.
33//
34// For further reading, also see:
35//
36// Kolmogorov, V. "Graph Based Algorithms for Scene Reconstruction from Two or
37// More Views". PhD thesis, Cornell University, Sep 2003.
38
39namespace boost {
40
41namespace detail {
42
43template <class Graph,
44 class EdgeCapacityMap,
45 class ResidualCapacityEdgeMap,
46 class ReverseEdgeMap,
47 class PredecessorMap,
48 class ColorMap,
49 class DistanceMap,
50 class IndexMap>
52 typedef typename property_traits<EdgeCapacityMap>::value_type tEdgeVal;
53 typedef graph_traits<Graph> tGraphTraits;
54 typedef typename tGraphTraits::vertex_iterator vertex_iterator;
55 typedef typename tGraphTraits::vertex_descriptor vertex_descriptor;
56 typedef typename tGraphTraits::edge_descriptor edge_descriptor;
57 typedef typename tGraphTraits::edge_iterator edge_iterator;
58 typedef typename tGraphTraits::out_edge_iterator out_edge_iterator;
59 typedef boost::queue<vertex_descriptor> tQueue; //queue of vertices, used in adoption-stage
60 typedef typename property_traits<ColorMap>::value_type tColorValue;
61 typedef color_traits<tColorValue> tColorTraits;
62 typedef typename property_traits<DistanceMap>::value_type tDistanceVal;
63
64 public:
65 bk_max_flow(Graph& g,
66 EdgeCapacityMap cap,
67 ResidualCapacityEdgeMap res,
68 ReverseEdgeMap rev,
70 ColorMap color,
71 DistanceMap dist,
72 IndexMap idx,
75 m_g(g),
76 m_index_map(idx),
77 m_cap_map(cap),
78 m_res_cap_map(res),
79 m_rev_edge_map(rev),
80 m_pre_map(pre),
81 m_tree_map(color),
82 m_dist_map(dist),
83 m_source(src),
84 m_sink(sink),
86 m_in_active_list_vec(num_vertices(g), false),
87 m_in_active_list_map(make_iterator_property_map(m_in_active_list_vec.begin(), m_index_map)),
88 m_has_parent_vec(num_vertices(g), false),
89 m_has_parent_map(make_iterator_property_map(m_has_parent_vec.begin(), m_index_map)),
90 m_time_vec(num_vertices(g), 0),
91 m_time_map(make_iterator_property_map(m_time_vec.begin(), m_index_map)),
92 m_flow(0),
93 m_time(1),
94 m_last_grow_vertex(graph_traits<Graph>::null_vertex()){
95 // initialize the color-map with gray-values
96 vertex_iterator vi, v_end;
97 for(boost::tie(vi, v_end) = vertices(m_g); vi != v_end; ++vi){
98 set_tree(*vi, tColorTraits::gray());
99 }
100 // Initialize flow to zero which means initializing
101 // the residual capacity equal to the capacity
102 edge_iterator ei, e_end;
103 for(boost::tie(ei, e_end) = edges(m_g); ei != e_end; ++ei) {
104 put(m_res_cap_map, *ei, get(m_cap_map, *ei));
105 BOOST_ASSERT(get(m_rev_edge_map, get(m_rev_edge_map, *ei)) == *ei); //check if the reverse edge map is build up properly
106 }
107 //init the search trees with the two terminals
108 set_tree(m_source, tColorTraits::black());
109 set_tree(m_sink, tColorTraits::white());
111 put(m_time_map, m_sink, 1);
112 }
113
115 //augment direct paths from SOURCE->SINK and SOURCE->VERTEX->SINK
117 //start the main-loop
118 while(true){
119 bool path_found;
120 edge_descriptor connecting_edge;
121 boost::tie(connecting_edge, path_found) = grow(); //find a path from source to sink
122 if(!path_found){
123 //we're finished, no more paths were found
124 break;
125 }
126 ++m_time;
127 augment(connecting_edge); //augment that path
128 adopt(); //rebuild search tree structure
129 }
130 return m_flow;
131 }
132
133 // the complete class is protected, as we want access to members in
134 // derived test-class (see test/boykov_kolmogorov_max_flow_test.cpp)
135 protected:
137 // in a first step, we augment all direct paths from source->NODE->sink
138 // and additionally paths from source->sink. This improves especially
139 // graphcuts for segmentation, as most of the nodes have source/sink
140 // connects but shouldn't have an impact on other maxflow problems
141 // (this is done in grow() anyway)
142 out_edge_iterator ei, e_end;
143 for(boost::tie(ei, e_end) = out_edges(m_source, m_g); ei != e_end; ++ei){
144 edge_descriptor from_source = *ei;
145 vertex_descriptor current_node = target(from_source, m_g);
146 if(current_node == m_sink){
147 tEdgeVal cap = get(m_res_cap_map, from_source);
148 put(m_res_cap_map, from_source, 0);
149 m_flow += cap;
150 continue;
151 }
152 edge_descriptor to_sink;
153 bool is_there;
154 boost::tie(to_sink, is_there) = lookup_edge(current_node, m_sink, m_g);
155 if(is_there){
156 tEdgeVal cap_from_source = get(m_res_cap_map, from_source);
157 tEdgeVal cap_to_sink = get(m_res_cap_map, to_sink);
158 if(cap_from_source > cap_to_sink){
159 set_tree(current_node, tColorTraits::black());
160 add_active_node(current_node);
161 set_edge_to_parent(current_node, from_source);
162 put(m_dist_map, current_node, 1);
163 put(m_time_map, current_node, 1);
164 // add stuff to flow and update residuals. we don't need to
165 // update reverse_edges, as incoming/outgoing edges to/from
166 // source/sink don't count for max-flow
167 put(m_res_cap_map, from_source, get(m_res_cap_map, from_source) - cap_to_sink);
168 put(m_res_cap_map, to_sink, 0);
169 m_flow += cap_to_sink;
170 } else if(cap_to_sink > 0){
171 set_tree(current_node, tColorTraits::white());
172 add_active_node(current_node);
173 set_edge_to_parent(current_node, to_sink);
174 put(m_dist_map, current_node, 1);
175 put(m_time_map, current_node, 1);
176 // add stuff to flow and update residuals. we don't need to update
177 // reverse_edges, as incoming/outgoing edges to/from source/sink
178 // don't count for max-flow
179 put(m_res_cap_map, to_sink, get(m_res_cap_map, to_sink) - cap_from_source);
180 put(m_res_cap_map, from_source, 0);
181 m_flow += cap_from_source;
182 }
183 } else if(get(m_res_cap_map, from_source)){
184 // there is no sink connect, so we can't augment this path, but to
185 // avoid adding m_source to the active nodes, we just activate this
186 // node and set the appropriate things
187 set_tree(current_node, tColorTraits::black());
188 set_edge_to_parent(current_node, from_source);
189 put(m_dist_map, current_node, 1);
190 put(m_time_map, current_node, 1);
191 add_active_node(current_node);
192 }
193 }
194 for(boost::tie(ei, e_end) = out_edges(m_sink, m_g); ei != e_end; ++ei){
195 edge_descriptor to_sink = get(m_rev_edge_map, *ei);
196 vertex_descriptor current_node = source(to_sink, m_g);
197 if(get(m_res_cap_map, to_sink)){
198 set_tree(current_node, tColorTraits::white());
199 set_edge_to_parent(current_node, to_sink);
200 put(m_dist_map, current_node, 1);
201 put(m_time_map, current_node, 1);
202 add_active_node(current_node);
203 }
204 }
205 }
206
213 std::pair<edge_descriptor, bool> grow(){
214 BOOST_ASSERT(m_orphans.empty());
215 vertex_descriptor current_node;
216 while((current_node = get_next_active_node()) != graph_traits<Graph>::null_vertex()){ //if there is one
217 BOOST_ASSERT(get_tree(current_node) != tColorTraits::gray() &&
218 (has_parent(current_node) ||
219 current_node == m_source ||
220 current_node == m_sink));
221
222 if(get_tree(current_node) == tColorTraits::black()){
223 //source tree growing
224 out_edge_iterator ei, e_end;
225 if(current_node != m_last_grow_vertex){
226 m_last_grow_vertex = current_node;
227 boost::tie(m_last_grow_edge_it, m_last_grow_edge_end) = out_edges(current_node, m_g);
228 }
231 if(get(m_res_cap_map, out_edge) > 0){ //check if we have capacity left on this edge
232 vertex_descriptor other_node = target(out_edge, m_g);
233 if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node
234 set_tree(other_node, tColorTraits::black()); //acquire other node to our search tree
235 set_edge_to_parent(other_node, out_edge); //set us as parent
236 put(m_dist_map, other_node, get(m_dist_map, current_node) + 1); //and update the distance-heuristic
237 put(m_time_map, other_node, get(m_time_map, current_node));
238 add_active_node(other_node);
239 } else if(get_tree(other_node) == tColorTraits::black()) {
240 // we do this to get shorter paths. check if we are nearer to
241 // the source as its parent is
242 if(is_closer_to_terminal(current_node, other_node)){
243 set_edge_to_parent(other_node, out_edge);
244 put(m_dist_map, other_node, get(m_dist_map, current_node) + 1);
245 put(m_time_map, other_node, get(m_time_map, current_node));
246 }
247 } else{
248 BOOST_ASSERT(get_tree(other_node)==tColorTraits::white());
249 //kewl, found a path from one to the other search tree, return
250 // the connecting edge in src->sink dir
251 return std::make_pair(out_edge, true);
252 }
253 }
254 } //for all out-edges
255 } //source-tree-growing
256 else{
257 BOOST_ASSERT(get_tree(current_node) == tColorTraits::white());
258 out_edge_iterator ei, e_end;
259 if(current_node != m_last_grow_vertex){
260 m_last_grow_vertex = current_node;
261 boost::tie(m_last_grow_edge_it, m_last_grow_edge_end) = out_edges(current_node, m_g);
262 }
265 if(get(m_res_cap_map, in_edge) > 0){ //check if there is capacity left
266 vertex_descriptor other_node = source(in_edge, m_g);
267 if(get_tree(other_node) == tColorTraits::gray()){ //it's a free node
268 set_tree(other_node, tColorTraits::white()); //acquire that node to our search tree
269 set_edge_to_parent(other_node, in_edge); //set us as parent
270 add_active_node(other_node); //activate that node
271 put(m_dist_map, other_node, get(m_dist_map, current_node) + 1); //set its distance
272 put(m_time_map, other_node, get(m_time_map, current_node));//and time
273 } else if(get_tree(other_node) == tColorTraits::white()){
274 if(is_closer_to_terminal(current_node, other_node)){
275 //we are closer to the sink than its parent is, so we "adopt" him
276 set_edge_to_parent(other_node, in_edge);
277 put(m_dist_map, other_node, get(m_dist_map, current_node) + 1);
278 put(m_time_map, other_node, get(m_time_map, current_node));
279 }
280 } else{
281 BOOST_ASSERT(get_tree(other_node)==tColorTraits::black());
282 //kewl, found a path from one to the other search tree,
283 // return the connecting edge in src->sink dir
284 return std::make_pair(in_edge, true);
285 }
286 }
287 } //for all out-edges
288 } //sink-tree growing
289
290 //all edges of that node are processed, and no more paths were found.
291 // remove if from the front of the active queue
292 finish_node(current_node);
293 } //while active_nodes not empty
294
295 //no active nodes anymore and no path found, we're done
296 return std::make_pair(edge_descriptor(), false);
297 }
298
311 BOOST_ASSERT(get_tree(target(e, m_g)) == tColorTraits::white());
312 BOOST_ASSERT(get_tree(source(e, m_g)) == tColorTraits::black());
313 BOOST_ASSERT(m_orphans.empty());
314
315 const tEdgeVal bottleneck = find_bottleneck(e);
316 //now we push the found flow through the path
317 //for each edge we saturate we have to look for the verts that belong to that edge, one of them becomes an orphans
318 //now process the connecting edge
319 put(m_res_cap_map, e, get(m_res_cap_map, e) - bottleneck);
320 BOOST_ASSERT(get(m_res_cap_map, e) >= 0);
322
323 //now we follow the path back to the source
324 vertex_descriptor current_node = source(e, m_g);
325 while(current_node != m_source){
326 edge_descriptor pred = get_edge_to_parent(current_node);
327 const tEdgeVal new_pred_cap = get(m_res_cap_map, pred) - bottleneck;
328 put(m_res_cap_map, pred, new_pred_cap);
329 BOOST_ASSERT(get(m_res_cap_map, pred) >= 0);
330
331 const edge_descriptor pred_rev = get(m_rev_edge_map, pred);
332 put(m_res_cap_map, pred_rev, get(m_res_cap_map, pred_rev) + bottleneck);
333
334 if(new_pred_cap == 0){
335 set_no_parent(current_node);
336 m_orphans.push_front(current_node);
337 }
338 current_node = source(pred, m_g);
339 }
340 //then go forward in the sink-tree
341 current_node = target(e, m_g);
342 while(current_node != m_sink){
343 edge_descriptor pred = get_edge_to_parent(current_node);
344 const tEdgeVal new_pred_cap = get(m_res_cap_map, pred) - bottleneck;
345 put(m_res_cap_map, pred, new_pred_cap);
346 BOOST_ASSERT(get(m_res_cap_map, pred) >= 0);
347
348 const edge_descriptor pred_rev = get(m_rev_edge_map, pred);
349 put(m_res_cap_map, pred_rev, get(m_res_cap_map, pred_rev) + bottleneck);
350
351 if(new_pred_cap == 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
366 BOOST_USING_STD_MIN();
367 tEdgeVal minimum_cap = get(m_res_cap_map, e);
368 vertex_descriptor current_node = source(e, m_g);
369 //first go back in the source tree
370 while(current_node != m_source){
371 edge_descriptor pred = get_edge_to_parent(current_node);
372 minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, get(m_res_cap_map, pred));
373 current_node = source(pred, m_g);
374 }
375 //then go forward in the sink-tree
376 current_node = target(e, m_g);
377 while(current_node != m_sink){
378 edge_descriptor pred = get_edge_to_parent(current_node);
379 minimum_cap = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum_cap, get(m_res_cap_map, pred));
380 current_node = target(pred, m_g);
381 }
382 return minimum_cap;
383 }
384
390 void adopt(){
391 while(!m_orphans.empty() || !m_child_orphans.empty()){
392 vertex_descriptor current_node;
393 if(m_child_orphans.empty()){
394 //get the next orphan from the main-queue and remove it
395 current_node = m_orphans.front();
396 m_orphans.pop_front();
397 } else{
398 current_node = m_child_orphans.front();
399 m_child_orphans.pop();
400 }
401 if(get_tree(current_node) == tColorTraits::black()){
402 //we're in the source-tree
403 tDistanceVal min_distance = (std::numeric_limits<tDistanceVal>::max)();
404 edge_descriptor new_parent_edge;
405 out_edge_iterator ei, e_end;
406 for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
407 const edge_descriptor in_edge = get(m_rev_edge_map, *ei);
408 BOOST_ASSERT(target(in_edge, m_g) == current_node); //we should be the target of this edge
409 if(get(m_res_cap_map, in_edge) > 0){
410 vertex_descriptor other_node = source(in_edge, m_g);
411 if(get_tree(other_node) == tColorTraits::black() && has_source_connect(other_node)){
412 if(get(m_dist_map, other_node) < min_distance){
413 min_distance = get(m_dist_map, other_node);
414 new_parent_edge = in_edge;
415 }
416 }
417 }
418 }
419 if(min_distance != (std::numeric_limits<tDistanceVal>::max)()){
420 set_edge_to_parent(current_node, new_parent_edge);
421 put(m_dist_map, current_node, min_distance + 1);
422 put(m_time_map, current_node, m_time);
423 } else{
424 put(m_time_map, current_node, 0);
425 for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
426 edge_descriptor in_edge = get(m_rev_edge_map, *ei);
427 vertex_descriptor other_node = source(in_edge, m_g);
428 if(get_tree(other_node) == tColorTraits::black() && other_node != m_source){
429 if(get(m_res_cap_map, in_edge) > 0){
430 add_active_node(other_node);
431 }
432 if(has_parent(other_node) && source(get_edge_to_parent(other_node), m_g) == current_node){
433 //we are the parent of that node
434 //it has to find a new parent, too
435 set_no_parent(other_node);
436 m_child_orphans.push(other_node);
437 }
438 }
439 }
440 set_tree(current_node, tColorTraits::gray());
441 } //no parent found
442 } //source-tree-adoption
443 else{
444 //now we should be in the sink-tree, check that...
445 BOOST_ASSERT(get_tree(current_node) == tColorTraits::white());
446 out_edge_iterator ei, e_end;
447 edge_descriptor new_parent_edge;
448 tDistanceVal min_distance = (std::numeric_limits<tDistanceVal>::max)();
449 for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
450 const edge_descriptor out_edge = *ei;
451 if(get(m_res_cap_map, out_edge) > 0){
452 const vertex_descriptor other_node = target(out_edge, m_g);
453 if(get_tree(other_node) == tColorTraits::white() && has_sink_connect(other_node))
454 if(get(m_dist_map, other_node) < min_distance){
455 min_distance = get(m_dist_map, other_node);
456 new_parent_edge = out_edge;
457 }
458 }
459 }
460 if(min_distance != (std::numeric_limits<tDistanceVal>::max)()){
461 set_edge_to_parent(current_node, new_parent_edge);
462 put(m_dist_map, current_node, min_distance + 1);
463 put(m_time_map, current_node, m_time);
464 } else{
465 put(m_time_map, current_node, 0);
466 for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
467 const edge_descriptor out_edge = *ei;
468 const vertex_descriptor other_node = target(out_edge, m_g);
469 if(get_tree(other_node) == tColorTraits::white() && other_node != m_sink){
470 if(get(m_res_cap_map, out_edge) > 0){
471 add_active_node(other_node);
472 }
473 if(has_parent(other_node) && target(get_edge_to_parent(other_node), m_g) == current_node){
474 //we were it's parent, so it has to find a new one, too
475 set_no_parent(other_node);
476 m_child_orphans.push(other_node);
477 }
478 }
479 }
480 set_tree(current_node, tColorTraits::gray());
481 } //no parent found
482 } //sink-tree adoption
483 } //while !orphans.empty()
484 } //adopt
485
490 while(true){
491 if(m_active_nodes.empty())
492 return graph_traits<Graph>::null_vertex();
494
495 //if it has no parent, this node can't be active (if its not source or sink)
496 if(!has_parent(v) && v != m_source && v != m_sink){
497 m_active_nodes.pop();
498 put(m_in_active_list_map, v, false);
499 } else{
500 BOOST_ASSERT(get_tree(v) == tColorTraits::black() || get_tree(v) == tColorTraits::white());
501 return v;
502 }
503 }
504 }
505
510 BOOST_ASSERT(get_tree(v) != tColorTraits::gray());
512 if (m_last_grow_vertex == v) {
513 m_last_grow_vertex = graph_traits<Graph>::null_vertex();
514 }
515 return;
516 } else{
517 put(m_in_active_list_map, v, true);
518 m_active_nodes.push(v);
519 }
520 }
521
526 BOOST_ASSERT(m_active_nodes.front() == v);
527 m_active_nodes.pop();
528 put(m_in_active_list_map, v, false);
529 m_last_grow_vertex = graph_traits<Graph>::null_vertex();
530 }
531
538 (void)v; // disable unused parameter warning
539 BOOST_ASSERT(!has_parent(v));
540 }
541
547 return get(m_tree_map, v);
548 }
549
555 put(m_tree_map, v, t);
556 }
557
564
568 inline bool has_parent(vertex_descriptor v) const{
569 return get(m_has_parent_map, v);
570 }
571
576 BOOST_ASSERT(get(m_res_cap_map, f_edge_to_parent) > 0);
577 put(m_pre_map, v, f_edge_to_parent);
578 put(m_has_parent_map, v, true);
579 }
580
586 put(m_has_parent_map, v, false);
587 }
588
595 tDistanceVal current_distance = 0;
596 vertex_descriptor current_vertex = v;
597 while(true){
598 if(get(m_time_map, current_vertex) == m_time){
599 //we found a node which was already checked this round. use it for distance calculations
600 current_distance += get(m_dist_map, current_vertex);
601 break;
602 }
603 if(current_vertex == m_sink){
605 break;
606 }
607 if(has_parent(current_vertex)){
608 //it has a parent, so get it
609 current_vertex = target(get_edge_to_parent(current_vertex), m_g);
610 ++current_distance;
611 } else{
612 //no path found
613 return false;
614 }
615 }
616 current_vertex=v;
617 while(get(m_time_map, current_vertex) != m_time){
618 put(m_dist_map, current_vertex, current_distance);
619 --current_distance;
620 put(m_time_map, current_vertex, m_time);
621 current_vertex = target(get_edge_to_parent(current_vertex), m_g);
622 }
623 return true;
624 }
625
632 tDistanceVal current_distance = 0;
633 vertex_descriptor current_vertex = v;
634 while(true){
635 if(get(m_time_map, current_vertex) == m_time){
636 //we found a node which was already checked this round. use it for distance calculations
637 current_distance += get(m_dist_map, current_vertex);
638 break;
639 }
640 if(current_vertex == m_source){
642 break;
643 }
644 if(has_parent(current_vertex)){
645 //it has a parent, so get it
646 current_vertex = source(get_edge_to_parent(current_vertex), m_g);
647 ++current_distance;
648 } else{
649 //no path found
650 return false;
651 }
652 }
653 current_vertex=v;
654 while(get(m_time_map, current_vertex) != m_time){
655 put(m_dist_map, current_vertex, current_distance);
656 --current_distance;
657 put(m_time_map, current_vertex, m_time);
658 current_vertex = source(get_edge_to_parent(current_vertex), m_g);
659 }
660 return true;
661 }
662
667 //checks the timestamps first, to build no cycles, and after that the real distance
668 return (get(m_time_map, q) <= get(m_time_map, p) &&
669 get(m_dist_map, q) > get(m_dist_map, p)+1);
670 }
671
673 // member vars
675 Graph& m_g;
676 IndexMap m_index_map;
677 EdgeCapacityMap m_cap_map;
678 ResidualCapacityEdgeMap m_res_cap_map;
679 ReverseEdgeMap m_rev_edge_map;
680 PredecessorMap m_pre_map; //stores paths found in the growth stage
681 ColorMap m_tree_map; //maps each vertex into one of the two search tree or none (gray())
682 DistanceMap m_dist_map; //stores distance to source/sink nodes
685
687 std::vector<bool> m_in_active_list_vec;
688 iterator_property_map<std::vector<bool>::iterator, IndexMap> m_in_active_list_map;
689
690 std::list<vertex_descriptor> m_orphans;
691 tQueue m_child_orphans; // we use a second queue for child orphans, as they are FIFO processed
692
693 std::vector<bool> m_has_parent_vec;
694 iterator_property_map<std::vector<bool>::iterator, IndexMap> m_has_parent_map;
695
696 std::vector<long> m_time_vec; //timestamp of each node, used for sink/source-path calculations
697 iterator_property_map<std::vector<long>::iterator, IndexMap> m_time_map;
699 long m_time;
703};
704
705} //namespace boost::detail
706
711template<class Graph,
712 class CapacityEdgeMap,
713 class ResidualCapacityEdgeMap,
714 class ReverseEdgeMap, class PredecessorMap,
715 class ColorMap,
716 class DistanceMap,
717 class IndexMap>
718typename property_traits<CapacityEdgeMap>::value_type
720 CapacityEdgeMap cap,
721 ResidualCapacityEdgeMap res_cap,
722 ReverseEdgeMap rev_map,
723 PredecessorMap pre_map,
724 ColorMap color,
725 DistanceMap dist,
726 IndexMap idx,
727 typename graph_traits<Graph>::vertex_descriptor src,
728 typename graph_traits<Graph>::vertex_descriptor sink)
729{
730 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
731 typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
732
733 //as this method is the last one before we instantiate the solver, we do the concept checks here
734 BOOST_CONCEPT_ASSERT(( VertexListGraphConcept<Graph> )); //to have vertices(), num_vertices(),
735 BOOST_CONCEPT_ASSERT(( EdgeListGraphConcept<Graph> )); //to have edges()
736 BOOST_CONCEPT_ASSERT(( IncidenceGraphConcept<Graph> )); //to have source(), target() and out_edges()
737 BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<CapacityEdgeMap, edge_descriptor> )); //read flow-values from edges
738 BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<ResidualCapacityEdgeMap, edge_descriptor> )); //write flow-values to residuals
739 BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<ReverseEdgeMap, edge_descriptor> )); //read out reverse edges
740 BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<PredecessorMap, vertex_descriptor> )); //store predecessor there
741 BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<ColorMap, vertex_descriptor> )); //write corresponding tree
742 BOOST_CONCEPT_ASSERT(( ReadWritePropertyMapConcept<DistanceMap, vertex_descriptor> )); //write distance to source/sink
743 BOOST_CONCEPT_ASSERT(( ReadablePropertyMapConcept<IndexMap, vertex_descriptor> )); //get index 0...|V|-1
744 BOOST_ASSERT(num_vertices(g) >= 2 && src != sink);
745
747 Graph, CapacityEdgeMap, ResidualCapacityEdgeMap, ReverseEdgeMap,
748 PredecessorMap, ColorMap, DistanceMap, IndexMap
749 > algo(g, cap, res_cap, rev_map, pre_map, color, dist, idx, src, sink);
750
751 return algo.max_flow();
752}
753
758template<class Graph,
759 class CapacityEdgeMap,
760 class ResidualCapacityEdgeMap,
761 class ReverseEdgeMap,
762 class IndexMap>
763typename property_traits<CapacityEdgeMap>::value_type
765 CapacityEdgeMap cap,
766 ResidualCapacityEdgeMap res_cap,
767 ReverseEdgeMap rev,
768 IndexMap idx,
769 typename graph_traits<Graph>::vertex_descriptor src,
770 typename graph_traits<Graph>::vertex_descriptor sink)
771{
772 typename graph_traits<Graph>::vertices_size_type n_verts = num_vertices(g);
773 std::vector<typename graph_traits<Graph>::edge_descriptor> predecessor_vec(n_verts);
774 std::vector<default_color_type> color_vec(n_verts);
775 std::vector<typename graph_traits<Graph>::vertices_size_type> distance_vec(n_verts);
776 return
778 g, cap, res_cap, rev,
779 make_iterator_property_map(predecessor_vec.begin(), idx),
780 make_iterator_property_map(color_vec.begin(), idx),
781 make_iterator_property_map(distance_vec.begin(), idx),
782 idx, src, sink);
783}
784
790template<class Graph,
791 class CapacityEdgeMap,
792 class ResidualCapacityEdgeMap,
793 class ReverseEdgeMap,
794 class ColorMap,
795 class IndexMap>
796typename property_traits<CapacityEdgeMap>::value_type
798 CapacityEdgeMap cap,
799 ResidualCapacityEdgeMap res_cap,
800 ReverseEdgeMap rev,
801 ColorMap color,
802 IndexMap idx,
803 typename graph_traits<Graph>::vertex_descriptor src,
804 typename graph_traits<Graph>::vertex_descriptor sink)
805{
806 typename graph_traits<Graph>::vertices_size_type n_verts = num_vertices(g);
807 std::vector<typename graph_traits<Graph>::edge_descriptor> predecessor_vec(n_verts);
808 std::vector<typename graph_traits<Graph>::vertices_size_type> distance_vec(n_verts);
809 return
811 g, cap, res_cap, rev,
812 make_iterator_property_map(predecessor_vec.begin(), idx),
813 color,
814 make_iterator_property_map(distance_vec.begin(), idx),
815 idx, src, sink);
816}
817
821template<class Graph, class P, class T, class R>
822typename property_traits<typename property_map<Graph, edge_capacity_t>::const_type>::value_type
824 typename graph_traits<Graph>::vertex_descriptor src,
825 typename graph_traits<Graph>::vertex_descriptor sink,
826 const bgl_named_params<P, T, R>& params)
827{
828 return
830 g,
831 choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity),
832 choose_pmap(get_param(params, edge_residual_capacity), g, edge_residual_capacity),
833 choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse),
834 choose_pmap(get_param(params, vertex_predecessor), g, vertex_predecessor),
835 choose_pmap(get_param(params, vertex_color), g, vertex_color),
836 choose_pmap(get_param(params, vertex_distance), g, vertex_distance),
837 choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
838 src, sink);
839}
840
844template<class Graph>
845typename property_traits<typename property_map<Graph, edge_capacity_t>::const_type>::value_type
847 typename graph_traits<Graph>::vertex_descriptor src,
848 typename graph_traits<Graph>::vertex_descriptor sink)
849{
850 bgl_named_params<int, buffer_param_t> params(0); // bogus empty param
851 return boykov_kolmogorov_max_flow(g, src, sink, params);
852}
853
854} // namespace boost
855
856#endif // BOOST_BOYKOV_KOLMOGOROV_MAX_FLOW_HPP
857
const Params2D p
qreal v
std::pair< KisMagneticGraph::out_edge_iterator, KisMagneticGraph::out_edge_iterator > out_edges(typename KisMagneticGraph::vertex_descriptor v, KisMagneticGraph g)
KisMagneticGraph::vertex_descriptor target(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
KisMagneticGraph::vertex_descriptor source(typename KisMagneticGraph::edge_descriptor e, KisMagneticGraph g)
VertexDescriptor get(PredecessorMap const &m, VertexDescriptor v)
void put(PredecessorMap &m, VertexDescriptor key, VertexDescriptor value)
iterator_property_map< std::vector< long >::iterator, IndexMap > m_time_map
iterator_property_map< std::vector< bool >::iterator, IndexMap > m_has_parent_map
boost::queue< vertex_descriptor > tQueue
property_traits< DistanceMap >::value_type tDistanceVal
tGraphTraits::vertex_iterator vertex_iterator
iterator_property_map< std::vector< bool >::iterator, IndexMap > m_in_active_list_map
void set_edge_to_parent(vertex_descriptor v, edge_descriptor f_edge_to_parent)
void set_tree(vertex_descriptor v, tColorValue t)
property_traits< EdgeCapacityMap >::value_type tEdgeVal
bk_max_flow(Graph &g, EdgeCapacityMap cap, ResidualCapacityEdgeMap res, ReverseEdgeMap rev, PredecessorMap pre, ColorMap color, DistanceMap dist, IndexMap idx, vertex_descriptor src, vertex_descriptor sink)
std::pair< edge_descriptor, bool > grow()
tGraphTraits::vertex_descriptor vertex_descriptor
tColorValue get_tree(vertex_descriptor v) const
tGraphTraits::edge_descriptor edge_descriptor
tGraphTraits::out_edge_iterator out_edge_iterator
edge_descriptor get_edge_to_parent(vertex_descriptor v) const
bool is_closer_to_terminal(vertex_descriptor p, vertex_descriptor q)
property_traits< ColorMap >::value_type tColorValue
typedef void(QOPENGLF_APIENTRYP PFNGLINVALIDATEBUFFERDATAPROC)(GLuint buffer)
property_traits< CapacityEdgeMap >::value_type boykov_kolmogorov_max_flow(Graph &g, CapacityEdgeMap cap, ResidualCapacityEdgeMap res_cap, ReverseEdgeMap rev_map, PredecessorMap pre_map, ColorMap color, DistanceMap dist, IndexMap idx, typename graph_traits< Graph >::vertex_descriptor src, typename graph_traits< Graph >::vertex_descriptor sink)