2 * src/hugo/preflow.h - Part of HUGOlib, a generic C++ optimization library
4 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Combinatorial Optimization Research Group, EGRES).
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
17 #ifndef HUGO_PREFLOW_H
18 #define HUGO_PREFLOW_H
23 #include <hugo/invalid.h>
24 #include <hugo/maps.h>
28 /// Implementation of the preflow algorithm.
32 /// \addtogroup flowalgs
35 ///%Preflow algorithms class.
37 ///This class provides an implementation of the \e preflow \e
38 ///algorithm producing a flow of maximum value in a directed
39 ///graph. The preflow algorithms are the fastest max flow algorithms
40 ///up to now. The \e source node, the \e target node, the \e
41 ///capacity of the edges and the \e starting \e flow value of the
42 ///edges should be passed to the algorithm through the
43 ///constructor. It is possible to change these quantities using the
44 ///functions \ref setSource, \ref setTarget, \ref setCap and \ref
47 ///After running \ref phase1() or \ref preflow(), the actual flow
48 ///value can be obtained by calling \ref flowValue(). The minimum
49 ///value cut can be written into a <tt>bool</tt> node map by
50 ///calling \ref minCut(). (\ref minMinCut() and \ref maxMinCut() writes
51 ///the inclusionwise minimum and maximum of the minimum value cuts,
54 ///\param Graph The directed graph type the algorithm runs on.
55 ///\param Num The number type of the capacities and the flow values.
56 ///\param CapMap The capacity map type.
57 ///\param FlowMap The flow map type.
59 ///\author Jacint Szabo
60 template <typename Graph, typename Num,
61 typename CapMap=typename Graph::template EdgeMap<Num>,
62 typename FlowMap=typename Graph::template EdgeMap<Num> >
65 typedef typename Graph::Node Node;
66 typedef typename Graph::NodeIt NodeIt;
67 typedef typename Graph::EdgeIt EdgeIt;
68 typedef typename Graph::OutEdgeIt OutEdgeIt;
69 typedef typename Graph::InEdgeIt InEdgeIt;
71 typedef typename Graph::template NodeMap<Node> NNMap;
72 typedef typename std::vector<Node> VecNode;
77 const CapMap* capacity;
79 int n; //the number of nodes of G
81 typename Graph::template NodeMap<int> level;
82 typename Graph::template NodeMap<Num> excess;
84 // constants used for heuristics
85 static const int H0=20;
86 static const int H1=1;
90 ///Indicates the property of the starting flow map.
92 ///Indicates the property of the starting flow map. The meanings are as follows:
93 ///- \c ZERO_FLOW: constant zero flow
94 ///- \c GEN_FLOW: any flow, i.e. the sum of the in-flows equals to
95 ///the sum of the out-flows in every node except the \e source and
97 ///- \c PRE_FLOW: any preflow, i.e. the sum of the in-flows is at
98 ///least the sum of the out-flows in every node except the \e source.
99 ///- \c NO_FLOW: indicates an unspecified edge map. \ref flow will be
100 ///set to the constant zero flow in the beginning of the algorithm in this case.
109 ///Indicates the state of the preflow algorithm.
111 ///Indicates the state of the preflow algorithm. The meanings are as follows:
112 ///- \c AFTER_NOTHING: before running the algorithm or at an unspecified state.
113 ///- \c AFTER_PREFLOW_PHASE_1: right after running \c phase1
114 ///- \c AFTER_PREFLOW_PHASE_2: after running \ref phase2()
118 AFTER_PREFLOW_PHASE_1,
119 AFTER_PREFLOW_PHASE_2
124 StatusEnum status; // Do not needle this flag only if necessary.
127 ///The constructor of the class.
129 ///The constructor of the class.
130 ///\param _G The directed graph the algorithm runs on.
131 ///\param _s The source node.
132 ///\param _t The target node.
133 ///\param _capacity The capacity of the edges.
134 ///\param _flow The flow of the edges.
135 ///Except the graph, all of these parameters can be reset by
136 ///calling \ref setSource, \ref setTarget, \ref setCap and \ref
138 Preflow(const Graph& _G, Node _s, Node _t,
139 const CapMap& _capacity, FlowMap& _flow) :
140 g(&_G), s(_s), t(_t), capacity(&_capacity),
141 flow(&_flow), n(_G.nodeNum()), level(_G), excess(_G,0),
142 flow_prop(NO_FLOW), status(AFTER_NOTHING) { }
146 ///Runs the preflow algorithm.
148 ///Runs the preflow algorithm.
155 ///Runs the preflow algorithm.
157 ///Runs the preflow algorithm.
158 ///\pre The starting flow map must be
159 /// - a constant zero flow if \c fp is \c ZERO_FLOW,
160 /// - an arbitrary flow if \c fp is \c GEN_FLOW,
161 /// - an arbitrary preflow if \c fp is \c PRE_FLOW,
162 /// - any map if \c fp is NO_FLOW.
163 ///If the starting flow map is a flow or a preflow then
164 ///the algorithm terminates faster.
165 void run(FlowEnum fp) {
170 ///Runs the first phase of the preflow algorithm.
172 ///The preflow algorithm consists of two phases, this method runs the
173 ///first phase. After the first phase the maximum flow value and a
174 ///minimum value cut can already be computed, though a maximum flow
175 ///is not yet obtained. So after calling this method \ref flowValue
176 ///and \ref minCut gives proper results.
177 ///\warning \ref minMinCut and \ref maxMinCut do not
178 ///give minimum value cuts unless calling \ref phase2.
179 ///\pre The starting flow must be
180 /// - a constant zero flow if \c fp is \c ZERO_FLOW,
181 /// - an arbitary flow if \c fp is \c GEN_FLOW,
182 /// - an arbitary preflow if \c fp is \c PRE_FLOW,
183 /// - any map if \c fp is NO_FLOW.
184 void phase1(FlowEnum fp)
191 ///Runs the first phase of the preflow algorithm.
193 ///The preflow algorithm consists of two phases, this method runs the
194 ///first phase. After the first phase the maximum flow value and a
195 ///minimum value cut can already be computed, though a maximum flow
196 ///is not yet obtained. So after calling this method \ref flowValue
197 ///and \ref actMinCut gives proper results.
198 ///\warning \ref minCut, \ref minMinCut and \ref maxMinCut do not
199 ///give minimum value cuts unless calling \ref phase2.
202 int heur0=(int)(H0*n); //time while running 'bound decrease'
203 int heur1=(int)(H1*n); //time while running 'highest label'
204 int heur=heur1; //starting time interval (#of relabels)
208 //It is 0 in case 'bound decrease' and 1 in case 'highest label'
211 //Needed for 'bound decrease', true means no active
212 //nodes are above bound b.
214 int k=n-2; //bound on the highest level under n containing a node
215 int b=k; //bound on the highest level under n of an active node
217 VecNode first(n, INVALID);
218 NNMap next(*g, INVALID);
220 NNMap left(*g, INVALID);
221 NNMap right(*g, INVALID);
222 VecNode level_list(n,INVALID);
223 //List of the nodes in level i<n, set to n.
225 preflowPreproc(first, next, level_list, left, right);
227 //Push/relabel on the highest level active nodes.
230 if ( !what_heur && !end && k > 0 ) {
236 if ( first[b]==INVALID ) --b;
241 int newlevel=push(w, next, first);
242 if ( excess[w] > 0 ) relabel(w, newlevel, first, next, level_list,
243 left, right, b, k, what_heur);
246 if ( numrelabel >= heur ) {
261 status=AFTER_PREFLOW_PHASE_1;
266 // list 'level_list' on the nodes on level i implemented by hand
267 // stack 'active' on the active nodes on level i
268 // runs heuristic 'highest label' for H1*n relabels
269 // runs heuristic 'bound decrease' for H0*n relabels, starts with 'highest label'
270 // Parameters H0 and H1 are initialized to 20 and 1.
273 ///Runs the second phase of the preflow algorithm.
275 ///The preflow algorithm consists of two phases, this method runs
276 ///the second phase. After calling \ref phase1 and then
277 ///\ref phase2 the methods \ref flowValue, \ref minCut,
278 ///\ref minMinCut and \ref maxMinCut give proper results.
279 ///\pre \ref phase1 must be called before.
283 int k=n-2; //bound on the highest level under n containing a node
284 int b=k; //bound on the highest level under n of an active node
287 VecNode first(n, INVALID);
288 NNMap next(*g, INVALID);
290 std::queue<Node> bfs_queue;
293 while ( !bfs_queue.empty() ) {
295 Node v=bfs_queue.front();
299 for(InEdgeIt e(*g,v); e!=INVALID; ++e) {
300 if ( (*capacity)[e] <= (*flow)[e] ) continue;
302 if ( level[u] >= n ) {
305 if ( excess[u] > 0 ) {
306 next.set(u,first[l]);
312 for(OutEdgeIt e(*g,v); e!=INVALID; ++e) {
313 if ( 0 >= (*flow)[e] ) continue;
315 if ( level[u] >= n ) {
318 if ( excess[u] > 0 ) {
319 next.set(u,first[l]);
330 if ( first[b]==INVALID ) --b;
334 int newlevel=push(w,next, first);
337 if ( excess[w] > 0 ) {
338 level.set(w,++newlevel);
339 next.set(w,first[newlevel]);
346 status=AFTER_PREFLOW_PHASE_2;
349 /// Returns the value of the maximum flow.
351 /// Returns the value of the maximum flow by returning the excess
352 /// of the target node \ref t. This value equals to the value of
353 /// the maximum flow already after running \ref phase1.
354 Num flowValue() const {
359 ///Returns a minimum value cut.
361 ///Sets \c M to the characteristic vector of a minimum value
362 ///cut. This method can be called both after running \ref
363 ///phase1 and \ref phase2. It is much faster after
364 ///\ref phase1. \pre M should be a bool-valued node-map. \pre
365 ///If \ref mincut is called after \ref phase2 then M should
366 ///be initialized to false.
367 template<typename _CutMap>
368 void minCut(_CutMap& M) const {
370 case AFTER_PREFLOW_PHASE_1:
371 for(NodeIt v(*g); v!=INVALID; ++v) {
379 case AFTER_PREFLOW_PHASE_2:
387 ///Returns the inclusionwise minimum of the minimum value cuts.
389 ///Sets \c M to the characteristic vector of the minimum value cut
390 ///which is inclusionwise minimum. It is computed by processing a
391 ///bfs from the source node \c s in the residual graph. \pre M
392 ///should be a node map of bools initialized to false. \pre \ref
393 ///phase2 should already be run.
394 template<typename _CutMap>
395 void minMinCut(_CutMap& M) const {
397 std::queue<Node> queue;
401 while (!queue.empty()) {
402 Node w=queue.front();
405 for(OutEdgeIt e(*g,w) ; e!=INVALID; ++e) {
407 if (!M[v] && (*flow)[e] < (*capacity)[e] ) {
413 for(InEdgeIt e(*g,w) ; e!=INVALID; ++e) {
415 if (!M[v] && (*flow)[e] > 0 ) {
423 ///Returns the inclusionwise maximum of the minimum value cuts.
425 ///Sets \c M to the characteristic vector of the minimum value cut
426 ///which is inclusionwise maximum. It is computed by processing a
427 ///backward bfs from the target node \c t in the residual graph.
428 ///\pre \ref phase2() or preflow() should already be run.
429 template<typename _CutMap>
430 void maxMinCut(_CutMap& M) const {
432 for(NodeIt v(*g) ; v!=INVALID; ++v) M.set(v, true);
434 std::queue<Node> queue;
439 while (!queue.empty()) {
440 Node w=queue.front();
443 for(InEdgeIt e(*g,w) ; e!=INVALID; ++e) {
445 if (M[v] && (*flow)[e] < (*capacity)[e] ) {
451 for(OutEdgeIt e(*g,w) ; e!=INVALID; ++e) {
453 if (M[v] && (*flow)[e] > 0 ) {
461 ///Sets the source node to \c _s.
463 ///Sets the source node to \c _s.
465 void setSource(Node _s) {
467 if ( flow_prop != ZERO_FLOW ) flow_prop=NO_FLOW;
468 status=AFTER_NOTHING;
471 ///Sets the target node to \c _t.
473 ///Sets the target node to \c _t.
475 void setTarget(Node _t) {
477 if ( flow_prop == GEN_FLOW ) flow_prop=PRE_FLOW;
478 status=AFTER_NOTHING;
481 /// Sets the edge map of the capacities to _cap.
483 /// Sets the edge map of the capacities to _cap.
485 void setCap(const CapMap& _cap) {
487 status=AFTER_NOTHING;
490 /// Sets the edge map of the flows to _flow.
492 /// Sets the edge map of the flows to _flow.
494 void setFlow(FlowMap& _flow) {
497 status=AFTER_NOTHING;
503 int push(Node w, NNMap& next, VecNode& first) {
507 int newlevel=n; //bound on the next level of w
509 for(OutEdgeIt e(*g,w) ; e!=INVALID; ++e) {
510 if ( (*flow)[e] >= (*capacity)[e] ) continue;
513 if( lev > level[v] ) { //Push is allowed now
515 if ( excess[v]<=0 && v!=t && v!=s ) {
516 next.set(v,first[level[v]]);
520 Num cap=(*capacity)[e];
524 if ( remcap >= exc ) { //A nonsaturating push.
526 flow->set(e, flo+exc);
527 excess.set(v, excess[v]+exc);
531 } else { //A saturating push.
533 excess.set(v, excess[v]+remcap);
536 } else if ( newlevel > level[v] ) newlevel = level[v];
540 for(InEdgeIt e(*g,w) ; e!=INVALID; ++e) {
542 if( (*flow)[e] <= 0 ) continue;
545 if( lev > level[v] ) { //Push is allowed now
547 if ( excess[v]<=0 && v!=t && v!=s ) {
548 next.set(v,first[level[v]]);
554 if ( flo >= exc ) { //A nonsaturating push.
556 flow->set(e, flo-exc);
557 excess.set(v, excess[v]+exc);
560 } else { //A saturating push.
562 excess.set(v, excess[v]+flo);
566 } else if ( newlevel > level[v] ) newlevel = level[v];
569 } // if w still has excess after the out edge for cycle
578 void preflowPreproc(VecNode& first, NNMap& next,
579 VecNode& level_list, NNMap& left, NNMap& right)
581 for(NodeIt v(*g); v!=INVALID; ++v) level.set(v,n);
582 std::queue<Node> bfs_queue;
584 if ( flow_prop == GEN_FLOW || flow_prop == PRE_FLOW ) {
585 //Reverse_bfs from t in the residual graph,
586 //to find the starting level.
590 while ( !bfs_queue.empty() ) {
592 Node v=bfs_queue.front();
596 for(InEdgeIt e(*g,v) ; e!=INVALID; ++e) {
597 if ( (*capacity)[e] <= (*flow)[e] ) continue;
599 if ( level[w] == n && w != s ) {
601 Node z=level_list[l];
602 if ( z!=INVALID ) left.set(z,w);
609 for(OutEdgeIt e(*g,v) ; e!=INVALID; ++e) {
610 if ( 0 >= (*flow)[e] ) continue;
612 if ( level[w] == n && w != s ) {
614 Node z=level_list[l];
615 if ( z!=INVALID ) left.set(z,w);
627 for(EdgeIt e(*g); e!=INVALID; ++e) flow->set(e,0);
629 for(NodeIt v(*g); v!=INVALID; ++v) excess.set(v,0);
631 //Reverse_bfs from t, to find the starting level.
635 while ( !bfs_queue.empty() ) {
637 Node v=bfs_queue.front();
641 for(InEdgeIt e(*g,v) ; e!=INVALID; ++e) {
643 if ( level[w] == n && w != s ) {
645 Node z=level_list[l];
646 if ( z!=INVALID ) left.set(z,w);
655 for(OutEdgeIt e(*g,s) ; e!=INVALID; ++e) {
656 Num c=(*capacity)[e];
657 if ( c <= 0 ) continue;
659 if ( level[w] < n ) {
660 if ( excess[w] <= 0 && w!=t ) { //putting into the stack
661 next.set(w,first[level[w]]);
665 excess.set(w, excess[w]+c);
671 for(NodeIt v(*g); v!=INVALID; ++v) excess.set(v,0);
674 for(InEdgeIt e(*g,t) ; e!=INVALID; ++e) exc+=(*flow)[e];
675 for(OutEdgeIt e(*g,t) ; e!=INVALID; ++e) exc-=(*flow)[e];
680 for(OutEdgeIt e(*g,s); e!=INVALID; ++e) {
681 Num rem=(*capacity)[e]-(*flow)[e];
682 if ( rem <= 0 ) continue;
684 if ( level[w] < n ) {
685 if ( excess[w] <= 0 && w!=t ) { //putting into the stack
686 next.set(w,first[level[w]]);
689 flow->set(e, (*capacity)[e]);
690 excess.set(w, excess[w]+rem);
694 for(InEdgeIt e(*g,s); e!=INVALID; ++e) {
695 if ( (*flow)[e] <= 0 ) continue;
697 if ( level[w] < n ) {
698 if ( excess[w] <= 0 && w!=t ) {
699 next.set(w,first[level[w]]);
702 excess.set(w, excess[w]+(*flow)[e]);
710 for(OutEdgeIt e(*g,s) ; e!=INVALID; ++e) {
711 Num rem=(*capacity)[e]-(*flow)[e];
712 if ( rem <= 0 ) continue;
714 if ( level[w] < n ) flow->set(e, (*capacity)[e]);
717 for(InEdgeIt e(*g,s) ; e!=INVALID; ++e) {
718 if ( (*flow)[e] <= 0 ) continue;
720 if ( level[w] < n ) flow->set(e, 0);
723 //computing the excess
724 for(NodeIt w(*g); w!=INVALID; ++w) {
726 for(InEdgeIt e(*g,w); e!=INVALID; ++e) exc+=(*flow)[e];
727 for(OutEdgeIt e(*g,w); e!=INVALID; ++e) exc-=(*flow)[e];
730 //putting the active nodes into the stack
732 if ( exc > 0 && lev < n && Node(w) != t ) {
733 next.set(w,first[lev]);
742 void relabel(Node w, int newlevel, VecNode& first, NNMap& next,
743 VecNode& level_list, NNMap& left,
744 NNMap& right, int& b, int& k, bool what_heur )
749 Node right_n=right[w];
753 if ( right_n!=INVALID ) {
754 if ( left_n!=INVALID ) {
755 right.set(left_n, right_n);
756 left.set(right_n, left_n);
758 level_list[lev]=right_n;
759 left.set(right_n, INVALID);
762 if ( left_n!=INVALID ) {
763 right.set(left_n, INVALID);
765 level_list[lev]=INVALID;
770 if ( level_list[lev]==INVALID ) {
773 for (int i=lev; i!=k ; ) {
774 Node v=level_list[++i];
775 while ( v!=INVALID ) {
779 level_list[i]=INVALID;
780 if ( !what_heur ) first[i]=INVALID;
790 if ( newlevel == n ) level.set(w,n);
792 level.set(w,++newlevel);
793 next.set(w,first[newlevel]);
795 if ( what_heur ) b=newlevel;
796 if ( k < newlevel ) ++k; //now k=newlevel
797 Node z=level_list[newlevel];
798 if ( z!=INVALID ) left.set(z,w);
801 level_list[newlevel]=w;
809 #endif //HUGO_PREFLOW_H