COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/hugo/preflow.h @ 905:5be029d19c98

Last change on this file since 905:5be029d19c98 was 874:2195bc090dfe, checked in by Alpar Juttner, 20 years ago

Document the file itself.

File size: 20.6 KB
Line 
1// -*- C++ -*-
2#ifndef HUGO_PREFLOW_H
3#define HUGO_PREFLOW_H
4
5#include <vector>
6#include <queue>
7
8#include <hugo/invalid.h>
9#include <hugo/maps.h>
10
11/// \file
12/// \ingroup flowalgs
13/// Implementation of the preflow algorithm.
14
15namespace hugo {
16
17  /// \addtogroup flowalgs
18  /// @{                                                   
19
20  ///%Preflow algorithms class.
21
22  ///This class provides an implementation of the \e preflow \e
23  ///algorithm producing a flow of maximum value in a directed
24  ///graph. The preflow algorithms are the fastest max flow algorithms
25  ///up to now. The \e source node, the \e target node, the \e
26  ///capacity of the edges and the \e starting \e flow value of the
27  ///edges should be passed to the algorithm through the
28  ///constructor. It is possible to change these quantities using the
29  ///functions \ref setSource, \ref setTarget, \ref setCap and \ref
30  ///setFlow.
31  ///
32  ///After running \ref phase1() or \ref preflow(), the actual flow
33  ///value can be obtained by calling \ref flowValue(). The minimum
34  ///value cut can be written into a <tt>bool</tt> node map by
35  ///calling \ref minCut(). (\ref minMinCut() and \ref maxMinCut() writes
36  ///the inclusionwise minimum and maximum of the minimum value cuts,
37  ///resp.)
38  ///
39  ///\param Graph The directed graph type the algorithm runs on.
40  ///\param Num The number type of the capacities and the flow values.
41  ///\param CapMap The capacity map type.
42  ///\param FlowMap The flow map type.
43  ///
44  ///\author Jacint Szabo
45  template <typename Graph, typename Num,
46            typename CapMap=typename Graph::template EdgeMap<Num>,
47            typename FlowMap=typename Graph::template EdgeMap<Num> >
48  class Preflow {
49  protected:
50    typedef typename Graph::Node Node;
51    typedef typename Graph::NodeIt NodeIt;
52    typedef typename Graph::EdgeIt EdgeIt;
53    typedef typename Graph::OutEdgeIt OutEdgeIt;
54    typedef typename Graph::InEdgeIt InEdgeIt;
55
56    typedef typename Graph::template NodeMap<Node> NNMap;
57    typedef typename std::vector<Node> VecNode;
58
59    const Graph* g;
60    Node s;
61    Node t;
62    const CapMap* capacity;
63    FlowMap* flow;
64    int n;      //the number of nodes of G
65   
66    typename Graph::template NodeMap<int> level; 
67    typename Graph::template NodeMap<Num> excess;
68
69    // constants used for heuristics
70    static const int H0=20;
71    static const int H1=1;
72
73    public:
74
75    ///Indicates the property of the starting flow map.
76
77    ///Indicates the property of the starting flow map. The meanings are as follows:
78    ///- \c ZERO_FLOW: constant zero flow
79    ///- \c GEN_FLOW: any flow, i.e. the sum of the in-flows equals to
80    ///the sum of the out-flows in every node except the \e source and
81    ///the \e target.
82    ///- \c PRE_FLOW: any preflow, i.e. the sum of the in-flows is at
83    ///least the sum of the out-flows in every node except the \e source.
84    ///- \c NO_FLOW: indicates an unspecified edge map. \ref flow will be
85    ///set to the constant zero flow in the beginning of the algorithm in this case.
86    ///
87    enum FlowEnum{
88      NO_FLOW,
89      ZERO_FLOW,
90      GEN_FLOW,
91      PRE_FLOW
92    };
93
94    ///Indicates the state of the preflow algorithm.
95
96    ///Indicates the state of the preflow algorithm. The meanings are as follows:
97    ///- \c AFTER_NOTHING: before running the algorithm or at an unspecified state.
98    ///- \c AFTER_PREFLOW_PHASE_1: right after running \c phase1
99    ///- \c AFTER_PREFLOW_PHASE_2: after running \ref phase2()
100    ///
101    enum StatusEnum {
102      AFTER_NOTHING,
103      AFTER_PREFLOW_PHASE_1,     
104      AFTER_PREFLOW_PHASE_2
105    };
106   
107    protected:
108      FlowEnum flow_prop;
109    StatusEnum status; // Do not needle this flag only if necessary.
110   
111  public:
112    ///The constructor of the class.
113
114    ///The constructor of the class.
115    ///\param _G The directed graph the algorithm runs on.
116    ///\param _s The source node.
117    ///\param _t The target node.
118    ///\param _capacity The capacity of the edges.
119    ///\param _flow The flow of the edges.
120    ///Except the graph, all of these parameters can be reset by
121    ///calling \ref setSource, \ref setTarget, \ref setCap and \ref
122    ///setFlow, resp.
123      Preflow(const Graph& _G, Node _s, Node _t,
124              const CapMap& _capacity, FlowMap& _flow) :
125        g(&_G), s(_s), t(_t), capacity(&_capacity),
126        flow(&_flow), n(_G.nodeNum()), level(_G), excess(_G,0),
127        flow_prop(NO_FLOW), status(AFTER_NOTHING) { }
128
129
130                                                                             
131    ///Runs the preflow algorithm. 
132
133    ///Runs the preflow algorithm.
134    ///
135    void run() {
136      phase1(flow_prop);
137      phase2();
138    }
139   
140    ///Runs the preflow algorithm. 
141   
142    ///Runs the preflow algorithm.
143    ///\pre The starting flow map must be
144    /// - a constant zero flow if \c fp is \c ZERO_FLOW,
145    /// - an arbitrary flow if \c fp is \c GEN_FLOW,
146    /// - an arbitrary preflow if \c fp is \c PRE_FLOW,
147    /// - any map if \c fp is NO_FLOW.
148    ///If the starting flow map is a flow or a preflow then
149    ///the algorithm terminates faster.
150    void run(FlowEnum fp) {
151      flow_prop=fp;
152      run();
153    }
154     
155    ///Runs the first phase of the preflow algorithm.
156
157    ///The preflow algorithm consists of two phases, this method runs the
158    ///first phase. After the first phase the maximum flow value and a
159    ///minimum value cut can already be computed, though a maximum flow
160    ///is not yet obtained. So after calling this method \ref flowValue
161    ///and \ref minCut gives proper results.
162    ///\warning \ref minMinCut and \ref maxMinCut do not
163    ///give minimum value cuts unless calling \ref phase2.
164    ///\pre The starting flow must be
165    /// - a constant zero flow if \c fp is \c ZERO_FLOW,
166    /// - an arbitary flow if \c fp is \c GEN_FLOW,
167    /// - an arbitary preflow if \c fp is \c PRE_FLOW,
168    /// - any map if \c fp is NO_FLOW.
169    void phase1(FlowEnum fp)
170    {
171      flow_prop=fp;
172      phase1();
173    }
174
175   
176    ///Runs the first phase of the preflow algorithm.
177
178    ///The preflow algorithm consists of two phases, this method runs the
179    ///first phase. After the first phase the maximum flow value and a
180    ///minimum value cut can already be computed, though a maximum flow
181    ///is not yet obtained. So after calling this method \ref flowValue
182    ///and \ref actMinCut gives proper results.
183    ///\warning \ref minCut, \ref minMinCut and \ref maxMinCut do not
184    ///give minimum value cuts unless calling \ref phase2.
185    void phase1()
186    {
187      int heur0=(int)(H0*n);  //time while running 'bound decrease'
188      int heur1=(int)(H1*n);  //time while running 'highest label'
189      int heur=heur1;         //starting time interval (#of relabels)
190      int numrelabel=0;
191
192      bool what_heur=1;
193      //It is 0 in case 'bound decrease' and 1 in case 'highest label'
194
195      bool end=false;
196      //Needed for 'bound decrease', true means no active
197      //nodes are above bound b.
198
199      int k=n-2;  //bound on the highest level under n containing a node
200      int b=k;    //bound on the highest level under n of an active node
201
202      VecNode first(n, INVALID);
203      NNMap next(*g, INVALID);
204
205      NNMap left(*g, INVALID);
206      NNMap right(*g, INVALID);
207      VecNode level_list(n,INVALID);
208      //List of the nodes in level i<n, set to n.
209
210      preflowPreproc(first, next, level_list, left, right);
211
212      //Push/relabel on the highest level active nodes.
213      while ( true ) {
214        if ( b == 0 ) {
215          if ( !what_heur && !end && k > 0 ) {
216            b=k;
217            end=true;
218          } else break;
219        }
220
221        if ( first[b]==INVALID ) --b;
222        else {
223          end=false;
224          Node w=first[b];
225          first[b]=next[w];
226          int newlevel=push(w, next, first);
227          if ( excess[w] > 0 ) relabel(w, newlevel, first, next, level_list,
228                                       left, right, b, k, what_heur);
229
230          ++numrelabel;
231          if ( numrelabel >= heur ) {
232            numrelabel=0;
233            if ( what_heur ) {
234              what_heur=0;
235              heur=heur0;
236              end=false;
237            } else {
238              what_heur=1;
239              heur=heur1;
240              b=k;
241            }
242          }
243        }
244      }
245      flow_prop=PRE_FLOW;
246      status=AFTER_PREFLOW_PHASE_1;
247    }
248    // Heuristics:
249    //   2 phase
250    //   gap
251    //   list 'level_list' on the nodes on level i implemented by hand
252    //   stack 'active' on the active nodes on level i     
253    //   runs heuristic 'highest label' for H1*n relabels
254    //   runs heuristic 'bound decrease' for H0*n relabels, starts with 'highest label'
255    //   Parameters H0 and H1 are initialized to 20 and 1.
256
257
258    ///Runs the second phase of the preflow algorithm.
259
260    ///The preflow algorithm consists of two phases, this method runs
261    ///the second phase. After calling \ref phase1 and then
262    ///\ref phase2 the methods \ref flowValue, \ref minCut,
263    ///\ref minMinCut and \ref maxMinCut give proper results.
264    ///\pre \ref phase1 must be called before.
265    void phase2()
266    {
267
268      int k=n-2;  //bound on the highest level under n containing a node
269      int b=k;    //bound on the highest level under n of an active node
270
271   
272      VecNode first(n, INVALID);
273      NNMap next(*g, INVALID);
274      level.set(s,0);
275      std::queue<Node> bfs_queue;
276      bfs_queue.push(s);
277
278      while ( !bfs_queue.empty() ) {
279
280        Node v=bfs_queue.front();
281        bfs_queue.pop();
282        int l=level[v]+1;
283
284        for(InEdgeIt e(*g,v); e!=INVALID; ++e) {
285          if ( (*capacity)[e] <= (*flow)[e] ) continue;
286          Node u=g->tail(e);
287          if ( level[u] >= n ) {
288            bfs_queue.push(u);
289            level.set(u, l);
290            if ( excess[u] > 0 ) {
291              next.set(u,first[l]);
292              first[l]=u;
293            }
294          }
295        }
296
297        for(OutEdgeIt e(*g,v); e!=INVALID; ++e) {
298          if ( 0 >= (*flow)[e] ) continue;
299          Node u=g->head(e);
300          if ( level[u] >= n ) {
301            bfs_queue.push(u);
302            level.set(u, l);
303            if ( excess[u] > 0 ) {
304              next.set(u,first[l]);
305              first[l]=u;
306            }
307          }
308        }
309      }
310      b=n-2;
311
312      while ( true ) {
313
314        if ( b == 0 ) break;
315        if ( first[b]==INVALID ) --b;
316        else {
317          Node w=first[b];
318          first[b]=next[w];
319          int newlevel=push(w,next, first);
320         
321          //relabel
322          if ( excess[w] > 0 ) {
323            level.set(w,++newlevel);
324            next.set(w,first[newlevel]);
325            first[newlevel]=w;
326            b=newlevel;
327          }
328        }
329      } // while(true)
330      flow_prop=GEN_FLOW;
331      status=AFTER_PREFLOW_PHASE_2;
332    }
333
334    /// Returns the value of the maximum flow.
335
336    /// Returns the value of the maximum flow by returning the excess
337    /// of the target node \ref t. This value equals to the value of
338    /// the maximum flow already after running \ref phase1.
339    Num flowValue() const {
340      return excess[t];
341    }
342
343
344    ///Returns a minimum value cut.
345
346    ///Sets \c M to the characteristic vector of a minimum value
347    ///cut. This method can be called both after running \ref
348    ///phase1 and \ref phase2. It is much faster after
349    ///\ref phase1.  \pre M should be a bool-valued node-map. \pre
350    ///If \ref mincut is called after \ref phase2 then M should
351    ///be initialized to false.
352    template<typename _CutMap>
353    void minCut(_CutMap& M) const {
354      switch ( status ) {
355        case AFTER_PREFLOW_PHASE_1:
356        for(NodeIt v(*g); v!=INVALID; ++v) {
357          if (level[v] < n) {
358            M.set(v, false);
359          } else {
360            M.set(v, true);
361          }
362        }
363        break;
364        case AFTER_PREFLOW_PHASE_2:
365        minMinCut(M);
366        break;
367        case AFTER_NOTHING:
368        break;
369      }
370    }
371
372    ///Returns the inclusionwise minimum of the minimum value cuts.
373
374    ///Sets \c M to the characteristic vector of the minimum value cut
375    ///which is inclusionwise minimum. It is computed by processing a
376    ///bfs from the source node \c s in the residual graph.  \pre M
377    ///should be a node map of bools initialized to false.  \pre \ref
378    ///phase2 should already be run.
379    template<typename _CutMap>
380    void minMinCut(_CutMap& M) const {
381
382      std::queue<Node> queue;
383      M.set(s,true);
384      queue.push(s);
385     
386      while (!queue.empty()) {
387        Node w=queue.front();
388        queue.pop();
389       
390        for(OutEdgeIt e(*g,w) ; e!=INVALID; ++e) {
391          Node v=g->head(e);
392          if (!M[v] && (*flow)[e] < (*capacity)[e] ) {
393            queue.push(v);
394            M.set(v, true);
395          }
396        }
397       
398        for(InEdgeIt e(*g,w) ; e!=INVALID; ++e) {
399          Node v=g->tail(e);
400          if (!M[v] && (*flow)[e] > 0 ) {
401            queue.push(v);
402            M.set(v, true);
403          }
404        }
405      }
406    }
407   
408    ///Returns the inclusionwise maximum of the minimum value cuts.
409
410    ///Sets \c M to the characteristic vector of the minimum value cut
411    ///which is inclusionwise maximum. It is computed by processing a
412    ///backward bfs from the target node \c t in the residual graph.
413    ///\pre \ref phase2() or preflow() should already be run.
414    template<typename _CutMap>
415    void maxMinCut(_CutMap& M) const {
416
417      for(NodeIt v(*g) ; v!=INVALID; ++v) M.set(v, true);
418
419      std::queue<Node> queue;
420
421      M.set(t,false);
422      queue.push(t);
423
424      while (!queue.empty()) {
425        Node w=queue.front();
426        queue.pop();
427
428        for(InEdgeIt e(*g,w) ; e!=INVALID; ++e) {
429          Node v=g->tail(e);
430          if (M[v] && (*flow)[e] < (*capacity)[e] ) {
431            queue.push(v);
432            M.set(v, false);
433          }
434        }
435
436        for(OutEdgeIt e(*g,w) ; e!=INVALID; ++e) {
437          Node v=g->head(e);
438          if (M[v] && (*flow)[e] > 0 ) {
439            queue.push(v);
440            M.set(v, false);
441          }
442        }
443      }
444    }
445
446    ///Sets the source node to \c _s.
447
448    ///Sets the source node to \c _s.
449    ///
450    void setSource(Node _s) {
451      s=_s;
452      if ( flow_prop != ZERO_FLOW ) flow_prop=NO_FLOW;
453      status=AFTER_NOTHING;
454    }
455
456    ///Sets the target node to \c _t.
457
458    ///Sets the target node to \c _t.
459    ///
460    void setTarget(Node _t) {
461      t=_t;
462      if ( flow_prop == GEN_FLOW ) flow_prop=PRE_FLOW;
463      status=AFTER_NOTHING;
464    }
465
466    /// Sets the edge map of the capacities to _cap.
467
468    /// Sets the edge map of the capacities to _cap.
469    ///
470    void setCap(const CapMap& _cap) {
471      capacity=&_cap;
472      status=AFTER_NOTHING;
473    }
474
475    /// Sets the edge map of the flows to _flow.
476
477    /// Sets the edge map of the flows to _flow.
478    ///
479    void setFlow(FlowMap& _flow) {
480      flow=&_flow;
481      flow_prop=NO_FLOW;
482      status=AFTER_NOTHING;
483    }
484
485
486  private:
487
488    int push(Node w, NNMap& next, VecNode& first) {
489
490      int lev=level[w];
491      Num exc=excess[w];
492      int newlevel=n;       //bound on the next level of w
493
494      for(OutEdgeIt e(*g,w) ; e!=INVALID; ++e) {
495        if ( (*flow)[e] >= (*capacity)[e] ) continue;
496        Node v=g->head(e);
497
498        if( lev > level[v] ) { //Push is allowed now
499         
500          if ( excess[v]<=0 && v!=t && v!=s ) {
501            next.set(v,first[level[v]]);
502            first[level[v]]=v;
503          }
504
505          Num cap=(*capacity)[e];
506          Num flo=(*flow)[e];
507          Num remcap=cap-flo;
508         
509          if ( remcap >= exc ) { //A nonsaturating push.
510           
511            flow->set(e, flo+exc);
512            excess.set(v, excess[v]+exc);
513            exc=0;
514            break;
515
516          } else { //A saturating push.
517            flow->set(e, cap);
518            excess.set(v, excess[v]+remcap);
519            exc-=remcap;
520          }
521        } else if ( newlevel > level[v] ) newlevel = level[v];
522      } //for out edges wv
523
524      if ( exc > 0 ) {
525        for(InEdgeIt e(*g,w) ; e!=INVALID; ++e) {
526         
527          if( (*flow)[e] <= 0 ) continue;
528          Node v=g->tail(e);
529
530          if( lev > level[v] ) { //Push is allowed now
531
532            if ( excess[v]<=0 && v!=t && v!=s ) {
533              next.set(v,first[level[v]]);
534              first[level[v]]=v;
535            }
536
537            Num flo=(*flow)[e];
538
539            if ( flo >= exc ) { //A nonsaturating push.
540
541              flow->set(e, flo-exc);
542              excess.set(v, excess[v]+exc);
543              exc=0;
544              break;
545            } else {  //A saturating push.
546
547              excess.set(v, excess[v]+flo);
548              exc-=flo;
549              flow->set(e,0);
550            }
551          } else if ( newlevel > level[v] ) newlevel = level[v];
552        } //for in edges vw
553
554      } // if w still has excess after the out edge for cycle
555
556      excess.set(w, exc);
557     
558      return newlevel;
559    }
560   
561   
562   
563    void preflowPreproc(VecNode& first, NNMap& next,
564                        VecNode& level_list, NNMap& left, NNMap& right)
565    {
566      for(NodeIt v(*g); v!=INVALID; ++v) level.set(v,n);
567      std::queue<Node> bfs_queue;
568     
569      if ( flow_prop == GEN_FLOW || flow_prop == PRE_FLOW ) {
570        //Reverse_bfs from t in the residual graph,
571        //to find the starting level.
572        level.set(t,0);
573        bfs_queue.push(t);
574       
575        while ( !bfs_queue.empty() ) {
576         
577          Node v=bfs_queue.front();
578          bfs_queue.pop();
579          int l=level[v]+1;
580         
581          for(InEdgeIt e(*g,v) ; e!=INVALID; ++e) {
582            if ( (*capacity)[e] <= (*flow)[e] ) continue;
583            Node w=g->tail(e);
584            if ( level[w] == n && w != s ) {
585              bfs_queue.push(w);
586              Node z=level_list[l];
587              if ( z!=INVALID ) left.set(z,w);
588              right.set(w,z);
589              level_list[l]=w;
590              level.set(w, l);
591            }
592          }
593         
594          for(OutEdgeIt e(*g,v) ; e!=INVALID; ++e) {
595            if ( 0 >= (*flow)[e] ) continue;
596            Node w=g->head(e);
597            if ( level[w] == n && w != s ) {
598              bfs_queue.push(w);
599              Node z=level_list[l];
600              if ( z!=INVALID ) left.set(z,w);
601              right.set(w,z);
602              level_list[l]=w;
603              level.set(w, l);
604            }
605          }
606        } //while
607      } //if
608
609
610      switch (flow_prop) {
611        case NO_FLOW: 
612        for(EdgeIt e(*g); e!=INVALID; ++e) flow->set(e,0);
613        case ZERO_FLOW:
614        for(NodeIt v(*g); v!=INVALID; ++v) excess.set(v,0);
615       
616        //Reverse_bfs from t, to find the starting level.
617        level.set(t,0);
618        bfs_queue.push(t);
619       
620        while ( !bfs_queue.empty() ) {
621         
622          Node v=bfs_queue.front();
623          bfs_queue.pop();
624          int l=level[v]+1;
625         
626          for(InEdgeIt e(*g,v) ; e!=INVALID; ++e) {
627            Node w=g->tail(e);
628            if ( level[w] == n && w != s ) {
629              bfs_queue.push(w);
630              Node z=level_list[l];
631              if ( z!=INVALID ) left.set(z,w);
632              right.set(w,z);
633              level_list[l]=w;
634              level.set(w, l);
635            }
636          }
637        }
638       
639        //the starting flow
640        for(OutEdgeIt e(*g,s) ; e!=INVALID; ++e) {
641          Num c=(*capacity)[e];
642          if ( c <= 0 ) continue;
643          Node w=g->head(e);
644          if ( level[w] < n ) {
645            if ( excess[w] <= 0 && w!=t ) { //putting into the stack
646              next.set(w,first[level[w]]);
647              first[level[w]]=w;
648            }
649            flow->set(e, c);
650            excess.set(w, excess[w]+c);
651          }
652        }
653        break;
654
655        case GEN_FLOW:
656        for(NodeIt v(*g); v!=INVALID; ++v) excess.set(v,0);
657        {
658          Num exc=0;
659          for(InEdgeIt e(*g,t) ; e!=INVALID; ++e) exc+=(*flow)[e];
660          for(OutEdgeIt e(*g,t) ; e!=INVALID; ++e) exc-=(*flow)[e];
661          excess.set(t,exc);
662        }
663
664        //the starting flow
665        for(OutEdgeIt e(*g,s); e!=INVALID; ++e) {
666          Num rem=(*capacity)[e]-(*flow)[e];
667          if ( rem <= 0 ) continue;
668          Node w=g->head(e);
669          if ( level[w] < n ) {
670            if ( excess[w] <= 0 && w!=t ) { //putting into the stack
671              next.set(w,first[level[w]]);
672              first[level[w]]=w;
673            }   
674            flow->set(e, (*capacity)[e]);
675            excess.set(w, excess[w]+rem);
676          }
677        }
678       
679        for(InEdgeIt e(*g,s); e!=INVALID; ++e) {
680          if ( (*flow)[e] <= 0 ) continue;
681          Node w=g->tail(e);
682          if ( level[w] < n ) {
683            if ( excess[w] <= 0 && w!=t ) {
684              next.set(w,first[level[w]]);
685              first[level[w]]=w;
686            } 
687            excess.set(w, excess[w]+(*flow)[e]);
688            flow->set(e, 0);
689          }
690        }
691        break;
692
693        case PRE_FLOW: 
694        //the starting flow
695        for(OutEdgeIt e(*g,s) ; e!=INVALID; ++e) {
696          Num rem=(*capacity)[e]-(*flow)[e];
697          if ( rem <= 0 ) continue;
698          Node w=g->head(e);
699          if ( level[w] < n ) flow->set(e, (*capacity)[e]);
700        }
701       
702        for(InEdgeIt e(*g,s) ; e!=INVALID; ++e) {
703          if ( (*flow)[e] <= 0 ) continue;
704          Node w=g->tail(e);
705          if ( level[w] < n ) flow->set(e, 0);
706        }
707       
708        //computing the excess
709        for(NodeIt w(*g); w!=INVALID; ++w) {
710          Num exc=0;
711          for(InEdgeIt e(*g,w); e!=INVALID; ++e) exc+=(*flow)[e];
712          for(OutEdgeIt e(*g,w); e!=INVALID; ++e) exc-=(*flow)[e];
713          excess.set(w,exc);
714         
715          //putting the active nodes into the stack
716          int lev=level[w];
717            if ( exc > 0 && lev < n && Node(w) != t ) {
718              next.set(w,first[lev]);
719              first[lev]=w;
720            }
721        }
722        break;
723      } //switch
724    } //preflowPreproc
725
726
727    void relabel(Node w, int newlevel, VecNode& first, NNMap& next,
728                 VecNode& level_list, NNMap& left,
729                 NNMap& right, int& b, int& k, bool what_heur )
730    {
731
732      int lev=level[w];
733
734      Node right_n=right[w];
735      Node left_n=left[w];
736
737      //unlacing starts
738      if ( right_n!=INVALID ) {
739        if ( left_n!=INVALID ) {
740          right.set(left_n, right_n);
741          left.set(right_n, left_n);
742        } else {
743          level_list[lev]=right_n;
744          left.set(right_n, INVALID);
745        }
746      } else {
747        if ( left_n!=INVALID ) {
748          right.set(left_n, INVALID);
749        } else {
750          level_list[lev]=INVALID;
751        }
752      }
753      //unlacing ends
754
755      if ( level_list[lev]==INVALID ) {
756
757        //gapping starts
758        for (int i=lev; i!=k ; ) {
759          Node v=level_list[++i];
760          while ( v!=INVALID ) {
761            level.set(v,n);
762            v=right[v];
763          }
764          level_list[i]=INVALID;
765          if ( !what_heur ) first[i]=INVALID;
766        }
767
768        level.set(w,n);
769        b=lev-1;
770        k=b;
771        //gapping ends
772
773      } else {
774
775        if ( newlevel == n ) level.set(w,n);
776        else {
777          level.set(w,++newlevel);
778          next.set(w,first[newlevel]);
779          first[newlevel]=w;
780          if ( what_heur ) b=newlevel;
781          if ( k < newlevel ) ++k;      //now k=newlevel
782          Node z=level_list[newlevel];
783          if ( z!=INVALID ) left.set(z,w);
784          right.set(w,z);
785          left.set(w,INVALID);
786          level_list[newlevel]=w;
787        }
788      }
789    } //relabel
790
791  };
792} //namespace hugo
793
794#endif //HUGO_PREFLOW_H
795
796
797
798
Note: See TracBrowser for help on using the repository browser.