[Lemon-commits] [lemon_svn] jacint: r1135 - hugo/trunk/src/hugo

Lemon SVN svn at lemon.cs.elte.hu
Mon Nov 6 20:43:27 CET 2006


Author: jacint
Date: Mon Sep 13 15:57:13 2004
New Revision: 1135

Added:
   hugo/trunk/src/hugo/preflow.h
      - copied, changed from r1125, /hugo/trunk/src/hugo/max_flow.h
Removed:
   hugo/trunk/src/hugo/max_flow.h

Log:
preflow last changes

Copied: hugo/trunk/src/hugo/preflow.h (from r1125, /hugo/trunk/src/hugo/max_flow.h)
==============================================================================
--- /hugo/trunk/src/hugo/max_flow.h	(original)
+++ hugo/trunk/src/hugo/preflow.h	Mon Sep 13 15:57:13 2004
@@ -1,11 +1,10 @@
 // -*- C++ -*-
-#ifndef HUGO_MAX_FLOW_H
-#define HUGO_MAX_FLOW_H
+#ifndef HUGO_PREFLOW_H
+#define HUGO_PREFLOW_H
 
 #include <vector>
 #include <queue>
 
-//#include <hugo/graph_wrapper.h>
 #include <hugo/invalid.h>
 #include <hugo/maps.h>
 
@@ -17,34 +16,35 @@
   /// \addtogroup flowalgs
   /// @{                                                   
 
-  ///Maximum flow algorithms class.
+  ///Preflow algorithms class.
 
-  ///This class provides various algorithms for finding a flow of
-  ///maximum value in a directed graph. The \e source node, the \e
-  ///target node, the \e capacity of the edges and the \e starting \e
-  ///flow value of the edges should be passed to the algorithm through the
+  ///This class provides an implementation of the \e preflow \e
+  ///algorithm producing a flow of maximum value in a directed
+  ///graph. The preflow algorithms are the fastest max flow algorithms
+  ///up-to-date. The \e source node, the \e target node, the \e
+  ///capacity of the edges and the \e starting \e flow value of the
+  ///edges should be passed to the algorithm through the
   ///constructor. It is possible to change these quantities using the
-  ///functions \ref setSource, \ref setTarget, \ref setCap and
-  ///\ref setFlow. Before any subsequent runs of any algorithm of
-  ///the class \ref setFlow should be called. 
+  ///functions \ref setSource, \ref setTarget, \ref setCap and \ref
+  ///setFlow.
   ///
-  ///After running an algorithm of the class, the actual flow value 
-  ///can be obtained by calling \ref flowValue(). The minimum
+  ///After running \c phase1 or \c preflow, the actual flow
+  ///value can be obtained by calling \ref flowValue(). The minimum
   ///value cut can be written into a \c node map of \c bools by
   ///calling \ref minCut. (\ref minMinCut and \ref maxMinCut writes
-  ///the inclusionwise minimum and maximum of the minimum value
-  ///cuts, resp.)
+  ///the inclusionwise minimum and maximum of the minimum value cuts,
+  ///resp.)
   ///
   ///\param Graph The directed graph type the algorithm runs on.
   ///\param Num The number type of the capacities and the flow values.
   ///\param CapMap The capacity map type.
   ///\param FlowMap The flow map type.
   ///
-  ///\author Marton Makai, Jacint Szabo 
+  ///\author Jacint Szabo 
   template <typename Graph, typename Num,
 	    typename CapMap=typename Graph::template EdgeMap<Num>,
             typename FlowMap=typename Graph::template EdgeMap<Num> >
-  class MaxFlow {
+  class Preflow {
   protected:
     typedef typename Graph::Node Node;
     typedef typename Graph::NodeIt NodeIt;
@@ -52,7 +52,6 @@
     typedef typename Graph::OutEdgeIt OutEdgeIt;
     typedef typename Graph::InEdgeIt InEdgeIt;
 
-    typedef typename std::vector<Node> VecFirst;
     typedef typename Graph::template NodeMap<Node> NNMap;
     typedef typename std::vector<Node> VecNode;
 
@@ -62,30 +61,19 @@
     const CapMap* capacity;
     FlowMap* flow;
     int n;      //the number of nodes of G
-    //    typedef ResGraphWrapper<const Graph, Num, CapMap, FlowMap> ResGW;   
-    //typedef ExpResGraphWrapper<const Graph, Num, CapMap, FlowMap> ResGW;
-    //    typedef typename ResGW::OutEdgeIt ResGWOutEdgeIt;
-    //    typedef typename ResGW::Edge ResGWEdge;
-    typedef typename Graph::template NodeMap<int> ReachedMap;
-
-
-    //level works as a bool map in augmenting path algorithms and is
-    //used by bfs for storing reached information.  In preflow, it
-    //shows the levels of nodes.     
-    ReachedMap level;
-
-    //excess is needed only in preflow
+    
+    typename Graph::template NodeMap<int> level;  
     typename Graph::template NodeMap<Num> excess;
 
     // constants used for heuristics
     static const int H0=20;
     static const int H1=1;
 
-  public:
+    public:
 
-    ///Indicates the property of the starting flow.
+    ///Indicates the property of the starting flow map.
 
-    ///Indicates the property of the starting flow. The meanings are as follows:
+    ///Indicates the property of the starting flow map. The meanings are as follows:
     ///- \c ZERO_FLOW: constant zero flow
     ///- \c GEN_FLOW: any flow, i.e. the sum of the in-flows equals to
     ///the sum of the out-flows in every node except the \e source and
@@ -94,94 +82,95 @@
     ///least the sum of the out-flows in every node except the \e source.
     ///- \c NO_FLOW: indicates an unspecified edge map. \ref flow will be 
     ///set to the constant zero flow in the beginning of the algorithm in this case.
+    ///
     enum FlowEnum{
+      NO_FLOW,
       ZERO_FLOW,
       GEN_FLOW,
-      PRE_FLOW,
-      NO_FLOW
+      PRE_FLOW
     };
 
+    ///Indicates the state of the preflow algorithm.
+
+    ///Indicates the state of the preflow algorithm. The meanings are as follows:
+    ///- \c AFTER_NOTHING: before running the algorithm or at an unspecified state.
+    ///- \c AFTER_PREFLOW_PHASE_1: right after running \c phase1
+    ///- \c AFTER_PREFLOW_PHASE_2: after running \ref phase2()
+    ///
     enum StatusEnum {
       AFTER_NOTHING,
-      AFTER_AUGMENTING,
-      AFTER_FAST_AUGMENTING, 
-      AFTER_PRE_FLOW_PHASE_1,      
-      AFTER_PRE_FLOW_PHASE_2
+      AFTER_PREFLOW_PHASE_1,      
+      AFTER_PREFLOW_PHASE_2
     };
+    
+    protected: 
+      FlowEnum flow_prop;
+    StatusEnum status; // Do not needle this flag only if necessary.
+    
+  public: 
+    ///The constructor of the class.
 
-    /// Do not needle this flag only if necessary.
-    StatusEnum status;
+    ///The constructor of the class. 
+    ///\param _G The directed graph the algorithm runs on. 
+    ///\param _s The source node.
+    ///\param _t The target node.
+    ///\param _capacity The capacity of the edges. 
+    ///\param _flow The flow of the edges. 
+    ///Except the graph, all of these parameters can be reset by
+    ///calling \ref setSource, \ref setTarget, \ref setCap and \ref
+    ///setFlow, resp.
+      Preflow(const Graph& _G, Node _s, Node _t, 
+	      const CapMap& _capacity, FlowMap& _flow) :
+	g(&_G), s(_s), t(_t), capacity(&_capacity),
+	flow(&_flow), n(_G.nodeNum()), level(_G), excess(_G,0), 
+	flow_prop(NO_FLOW), status(AFTER_NOTHING) { }
 
-    //     int number_of_augmentations;
 
+                                                                              
+    ///Runs the preflow algorithm.  
 
-    //     template<typename IntMap>
-    //     class TrickyReachedMap {
-    //     protected:
-    //       IntMap* map;
-    //       int* number_of_augmentations;
-    //     public:
-    //       TrickyReachedMap(IntMap& _map, int& _number_of_augmentations) : 
-    // 	map(&_map), number_of_augmentations(&_number_of_augmentations) { }
-    //       void set(const Node& n, bool b) {
-    // 	if (b)
-    // 	  map->set(n, *number_of_augmentations);
-    // 	else 
-    // 	  map->set(n, *number_of_augmentations-1);
-    //       }
-    //       bool operator[](const Node& n) const { 
-    // 	return (*map)[n]==*number_of_augmentations; 
-    //       }
-    //     };
+    ///Runs the preflow algorithm. 
+    void run() {
+      phase1(flow_prop);
+      phase2();
+    }
     
-    ///Constructor
-
-    ///\todo Document, please.
-    ///
-    MaxFlow(const Graph& _G, Node _s, Node _t,
-	    const CapMap& _capacity, FlowMap& _flow) :
-      g(&_G), s(_s), t(_t), capacity(&_capacity),
-      flow(&_flow), n(_G.nodeNum()), level(_G), excess(_G,0), 
-      status(AFTER_NOTHING) { }
-
-    ///Runs a maximum flow algorithm.
-
-    ///Runs a preflow algorithm, which is the fastest maximum flow
-    ///algorithm up-to-date. The default for \c fe is ZERO_FLOW.
-    ///\pre The starting flow must be
-    /// - a constant zero flow if \c fe is \c ZERO_FLOW,
-    /// - an arbitary flow if \c fe is \c GEN_FLOW,
-    /// - an arbitary preflow if \c fe is \c PRE_FLOW,
-    /// - any map if \c fe is NO_FLOW.
-    void run(FlowEnum fe=ZERO_FLOW) {
-      preflow(fe);
+    ///Runs the preflow algorithm.  
+    
+    ///Runs the preflow algorithm. 
+    ///\pre The starting flow map must be
+    /// - a constant zero flow if \c fp is \c ZERO_FLOW,
+    /// - an arbitrary flow if \c fp is \c GEN_FLOW,
+    /// - an arbitrary preflow if \c fp is \c PRE_FLOW,
+    /// - any map if \c fp is NO_FLOW.
+    ///If the starting flow map is a flow or a preflow then 
+    ///the algorithm terminates faster.
+    void run(FlowEnum fp) {
+      flow_prop=fp;
+      run();
     }
+      
+    ///Runs the first phase of the preflow algorithm.
 
-                                                                              
-    ///Runs a preflow algorithm.  
-
-    ///Runs a preflow algorithm. The preflow algorithms provide the
-    ///fastest way to compute a maximum flow in a directed graph.
+    ///The preflow algorithm consists of two phases, this method runs the
+    ///first phase. After the first phase the maximum flow value and a
+    ///minimum value cut can already be computed, though a maximum flow
+    ///is not yet obtained. So after calling this method \ref flowValue
+    ///and \ref minCut gives proper results.
+    ///\warning: \ref minMinCut and \ref maxMinCut do not
+    ///give minimum value cuts unless calling \ref phase2.
     ///\pre The starting flow must be
-    /// - a constant zero flow if \c fe is \c ZERO_FLOW,
-    /// - an arbitary flow if \c fe is \c GEN_FLOW,
-    /// - an arbitary preflow if \c fe is \c PRE_FLOW,
-    /// - any map if \c fe is NO_FLOW.
-    ///
-    ///\todo NO_FLOW should be the default flow.
-    void preflow(FlowEnum fe) {
-      preflowPhase1(fe);
-      preflowPhase2();
+    /// - a constant zero flow if \c fp is \c ZERO_FLOW,
+    /// - an arbitary flow if \c fp is \c GEN_FLOW,
+    /// - an arbitary preflow if \c fp is \c PRE_FLOW,
+    /// - any map if \c fp is NO_FLOW.
+    void phase1(FlowEnum fp)
+    {
+      flow_prop=fp;
+      phase1();
     }
-    // Heuristics:
-    //   2 phase
-    //   gap
-    //   list 'level_list' on the nodes on level i implemented by hand
-    //   stack 'active' on the active nodes on level i                                                                                    
-    //   runs heuristic 'highest label' for H1*n relabels
-    //   runs heuristic 'bound decrease' for H0*n relabels, starts with 'highest label'
-    //   Parameters H0 and H1 are initialized to 20 and 1.
 
+    
     ///Runs the first phase of the preflow algorithm.
 
     ///The preflow algorithm consists of two phases, this method runs the
@@ -190,15 +179,9 @@
     ///is not yet obtained. So after calling this method \ref flowValue
     ///and \ref actMinCut gives proper results.
     ///\warning: \ref minCut, \ref minMinCut and \ref maxMinCut do not
-    ///give minimum value cuts unless calling \ref preflowPhase2.
-    ///\pre The starting flow must be
-    /// - a constant zero flow if \c fe is \c ZERO_FLOW,
-    /// - an arbitary flow if \c fe is \c GEN_FLOW,
-    /// - an arbitary preflow if \c fe is \c PRE_FLOW,
-    /// - any map if \c fe is NO_FLOW.
-    void preflowPhase1(FlowEnum fe)
+    ///give minimum value cuts unless calling \ref phase2.
+    void phase1()
     {
-
       int heur0=(int)(H0*n);  //time while running 'bound decrease'
       int heur1=(int)(H1*n);  //time while running 'highest label'
       int heur=heur1;         //starting time interval (#of relabels)
@@ -208,22 +191,21 @@
       //It is 0 in case 'bound decrease' and 1 in case 'highest label'
 
       bool end=false;
-      //Needed for 'bound decrease', true means no active nodes are above bound
-      //b.
+      //Needed for 'bound decrease', true means no active 
+      //nodes are above bound b.
 
       int k=n-2;  //bound on the highest level under n containing a node
       int b=k;    //bound on the highest level under n of an active node
 
-      VecFirst first(n, INVALID);
-      NNMap next(*g, INVALID); //maybe INVALID is not needed
+      VecNode first(n, INVALID);
+      NNMap next(*g, INVALID);
 
       NNMap left(*g, INVALID);
       NNMap right(*g, INVALID);
       VecNode level_list(n,INVALID);
       //List of the nodes in level i<n, set to n.
 
-      preflowPreproc(fe, next, first, level_list, left, right);
-      //End of preprocessing
+      preflowPreproc(first, next, level_list, left, right);
 
       //Push/relabel on the highest level active nodes.
       while ( true ) {
@@ -240,7 +222,7 @@
 	  Node w=first[b];
 	  first[b]=next[w];
 	  int newlevel=push(w, next, first);
-	  if ( excess[w] > 0 ) relabel(w, newlevel, next, first, level_list,
+	  if ( excess[w] > 0 ) relabel(w, newlevel, first, next, level_list, 
 				       left, right, b, k, what_heur);
 
 	  ++numrelabel;
@@ -258,32 +240,40 @@
 	  }
 	}
       }
-
-      status=AFTER_PRE_FLOW_PHASE_1;
+      flow_prop=PRE_FLOW;
+      status=AFTER_PREFLOW_PHASE_1;
     }
+    // Heuristics:
+    //   2 phase
+    //   gap
+    //   list 'level_list' on the nodes on level i implemented by hand
+    //   stack 'active' on the active nodes on level i      
+    //   runs heuristic 'highest label' for H1*n relabels
+    //   runs heuristic 'bound decrease' for H0*n relabels, starts with 'highest label'
+    //   Parameters H0 and H1 are initialized to 20 and 1.
 
 
     ///Runs the second phase of the preflow algorithm.
 
     ///The preflow algorithm consists of two phases, this method runs
-    ///the second phase. After calling \ref preflowPhase1 and then
-    ///\ref preflowPhase2 the methods \ref flowValue, \ref minCut,
+    ///the second phase. After calling \ref phase1 and then
+    ///\ref phase2 the methods \ref flowValue, \ref minCut,
     ///\ref minMinCut and \ref maxMinCut give proper results.
-    ///\pre \ref preflowPhase1 must be called before.
-    void preflowPhase2()
+    ///\pre \ref phase1 must be called before.
+    void phase2()
     {
 
       int k=n-2;  //bound on the highest level under n containing a node
       int b=k;    //bound on the highest level under n of an active node
 
     
-      VecFirst first(n, INVALID);
-      NNMap next(*g, INVALID); //maybe INVALID is not needed
+      VecNode first(n, INVALID);
+      NNMap next(*g, INVALID); 
       level.set(s,0);
       std::queue<Node> bfs_queue;
       bfs_queue.push(s);
 
-      while (!bfs_queue.empty()) {
+      while ( !bfs_queue.empty() ) {
 
 	Node v=bfs_queue.front();
 	bfs_queue.pop();
@@ -320,14 +310,12 @@
       while ( true ) {
 
 	if ( b == 0 ) break;
-
 	if ( first[b]==INVALID ) --b;
 	else {
-
 	  Node w=first[b];
 	  first[b]=next[w];
-	  int newlevel=push(w,next, first/*active*/);
-
+	  int newlevel=push(w,next, first);
+	  
 	  //relabel
 	  if ( excess[w] > 0 ) {
 	    level.set(w,++newlevel);
@@ -337,43 +325,32 @@
 	  }
 	} 
       } // while(true)
-
-      status=AFTER_PRE_FLOW_PHASE_2;
+      flow_prop=GEN_FLOW;
+      status=AFTER_PREFLOW_PHASE_2;
     }
 
-
     /// Returns the value of the maximum flow.
 
-    /// Returns the excess of the target node \ref t. 
-    /// After running \ref preflowPhase1, this is the value of 
-    /// the maximum flow.
-    /// It can be called already after running \ref preflowPhase1.
+    /// Returns the value of the maximum flow by returning the excess
+    /// of the target node \ref t. This value equals to the value of
+    /// the maximum flow already after running \ref phase1.
     Num flowValue() const {
-      //       Num a=0;
-      //       for(InEdgeIt e(*g,t);g->valid(e);g->next(e)) a+=(*flow)[e];
-      //       for(OutEdgeIt e(*g,t);g->valid(e);g->next(e)) a-=(*flow)[e];
-      //       return a;
       return excess[t];
-      //marci figyu: excess[t] epp ezt adja preflow 1. fazisa utan   
     }
 
 
-    ///Returns a minimum value cut after calling \ref preflowPhase1.
+    ///Returns a minimum value cut.
 
-    ///After the first phase of the preflow algorithm the maximum flow
-    ///value and a minimum value cut can already be computed. This
-    ///method can be called after running \ref preflowPhase1 for
-    ///obtaining a minimum value cut.
-    /// \warning Gives proper result only right after calling \ref
-    /// preflowPhase1.
-    /// \todo We have to make some status variable which shows the
-    /// actual state
-    /// of the class. This enables us to determine which methods are valid
-    /// for MinCut computation
+    ///Sets \c M to the characteristic vector of a minimum value
+    ///cut. This method can be called both after running \ref
+    ///phase1 and \ref phase2. It is much faster after
+    ///\ref phase1.  \pre M should be a node map of bools. \pre
+    ///If \ref mincut is called after \ref phase2 then M should
+    ///be initialized to false.
     template<typename _CutMap>
-    void actMinCut(_CutMap& M) const {
-      switch (status) {
-	case AFTER_PRE_FLOW_PHASE_1:
+    void minCut(_CutMap& M) const {
+      switch ( status ) {
+	case AFTER_PREFLOW_PHASE_1:
 	for(NodeIt v(*g); v!=INVALID; ++v) {
 	  if (level[v] < n) {
 	    M.set(v, false);
@@ -382,33 +359,32 @@
 	  }
 	}
 	break;
-	case AFTER_PRE_FLOW_PHASE_2:
-	case AFTER_NOTHING:
-	case AFTER_AUGMENTING:
-	case AFTER_FAST_AUGMENTING:
+	case AFTER_PREFLOW_PHASE_2:
 	minMinCut(M);
 	break;
+	case AFTER_NOTHING:
+	break;
       }
     }
 
     ///Returns the inclusionwise minimum of the minimum value cuts.
 
     ///Sets \c M to the characteristic vector of the minimum value cut
-    ///which is inclusionwise minimum. It is computed by processing
-    ///a bfs from the source node \c s in the residual graph.
-    ///\pre M should be a node map of bools initialized to false.
-    ///\pre \c flow must be a maximum flow.
+    ///which is inclusionwise minimum. It is computed by processing a
+    ///bfs from the source node \c s in the residual graph.  \pre M
+    ///should be a node map of bools initialized to false.  \pre \ref
+    ///phase2 should already be run.
     template<typename _CutMap>
     void minMinCut(_CutMap& M) const {
-      std::queue<Node> queue;
 
+      std::queue<Node> queue;
       M.set(s,true);
       queue.push(s);
-
+      
       while (!queue.empty()) {
-        Node w=queue.front();
+	Node w=queue.front();
 	queue.pop();
-
+	
 	for(OutEdgeIt e(*g,w) ; e!=INVALID; ++e) {
 	  Node v=g->head(e);
 	  if (!M[v] && (*flow)[e] < (*capacity)[e] ) {
@@ -416,7 +392,7 @@
 	    M.set(v, true);
 	  }
 	}
-
+	
 	for(InEdgeIt e(*g,w) ; e!=INVALID; ++e) {
 	  Node v=g->tail(e);
 	  if (!M[v] && (*flow)[e] > 0 ) {
@@ -426,14 +402,13 @@
 	}
       }
     }
-
+    
     ///Returns the inclusionwise maximum of the minimum value cuts.
 
     ///Sets \c M to the characteristic vector of the minimum value cut
     ///which is inclusionwise maximum. It is computed by processing a
     ///backward bfs from the target node \c t in the residual graph.
-    ///\pre M should be a node map of bools initialized to false.
-    ///\pre \c flow must be a maximum flow. 
+    ///\pre \ref phase2() or preflow() should already be run.
     template<typename _CutMap>
     void maxMinCut(_CutMap& M) const {
 
@@ -466,43 +441,49 @@
       }
     }
 
-    ///Returns a minimum value cut.
-
-    ///Sets \c M to the characteristic vector of a minimum value cut.
-    ///\pre M should be a node map of bools initialized to false.
-    ///\pre \c flow must be a maximum flow.    
-    template<typename CutMap>
-    void minCut(CutMap& M) const { minMinCut(M); }
-
     ///Sets the source node to \c _s.
 
     ///Sets the source node to \c _s.
     /// 
-    void setSource(Node _s) { s=_s; status=AFTER_NOTHING; }
+    void setSource(Node _s) { 
+      s=_s; 
+      if ( flow_prop != ZERO_FLOW ) flow_prop=NO_FLOW;
+      status=AFTER_NOTHING; 
+    }
 
     ///Sets the target node to \c _t.
 
     ///Sets the target node to \c _t.
     ///
-    void setTarget(Node _t) { t=_t; status=AFTER_NOTHING; }
+    void setTarget(Node _t) { 
+      t=_t; 
+      if ( flow_prop == GEN_FLOW ) flow_prop=PRE_FLOW;
+      status=AFTER_NOTHING; 
+    }
 
     /// Sets the edge map of the capacities to _cap.
 
     /// Sets the edge map of the capacities to _cap.
     /// 
-    void setCap(const CapMap& _cap)
-    { capacity=&_cap; status=AFTER_NOTHING; }
+    void setCap(const CapMap& _cap) { 
+      capacity=&_cap; 
+      status=AFTER_NOTHING; 
+    }
 
     /// Sets the edge map of the flows to _flow.
 
     /// Sets the edge map of the flows to _flow.
     /// 
-    void setFlow(FlowMap& _flow) { flow=&_flow; status=AFTER_NOTHING; }
+    void setFlow(FlowMap& _flow) { 
+      flow=&_flow; 
+      flow_prop=NO_FLOW;
+      status=AFTER_NOTHING; 
+    }
 
 
   private:
 
-    int push(Node w, NNMap& next, VecFirst& first) {
+    int push(Node w, NNMap& next, VecNode& first) {
 
       int lev=level[w];
       Num exc=excess[w];
@@ -577,86 +558,19 @@
     
     
     
-    void preflowPreproc(FlowEnum fe, NNMap& next, VecFirst& first,
+    void preflowPreproc(VecNode& first, NNMap& next, 
 			VecNode& level_list, NNMap& left, NNMap& right)
     {
-      switch (fe) {  //setting excess
-	case NO_FLOW: 
-	for(EdgeIt e(*g); e!=INVALID; ++e) flow->set(e,0);
-	for(NodeIt v(*g); v!=INVALID; ++v) excess.set(v,0);
-	break;
-	case ZERO_FLOW: 
-	for(NodeIt v(*g); v!=INVALID; ++v) excess.set(v,0);
-	break;
-	case GEN_FLOW:
-	for(NodeIt v(*g); v!=INVALID; ++v) excess.set(v,0);
-	{
-	  Num exc=0;
-	  for(InEdgeIt e(*g,t) ; e!=INVALID; ++e) exc+=(*flow)[e];
-	  for(OutEdgeIt e(*g,t) ; e!=INVALID; ++e) exc-=(*flow)[e];
-	  excess.set(t,exc);
-	}
-	break;
-	default:
-	break;
-      }
-      
       for(NodeIt v(*g); v!=INVALID; ++v) level.set(v,n);
-      //setting each node to level n
-      
       std::queue<Node> bfs_queue;
-
-
-      switch (fe) {
-      case NO_FLOW:   //flow is already set to const zero
-      case ZERO_FLOW:
-	//Reverse_bfs from t, to find the starting level.
-	level.set(t,0);
-	bfs_queue.push(t);
-	
-	while (!bfs_queue.empty()) {
-	  
-	  Node v=bfs_queue.front();
-	  bfs_queue.pop();
-	  int l=level[v]+1;
-	  
-	  for(InEdgeIt e(*g,v) ; e!=INVALID; ++e) {
-	    Node w=g->tail(e);
-	    if ( level[w] == n && w != s ) {
-	      bfs_queue.push(w);
-	      Node z=level_list[l];
-	      if ( z!=INVALID ) left.set(z,w);
-	      right.set(w,z);
-	      level_list[l]=w;
-	      level.set(w, l);
-	    }
-	  }
-	}
-	
-	//the starting flow
-	for(OutEdgeIt e(*g,s) ; e!=INVALID; ++e)
-	  {
-	    Num c=(*capacity)[e];
-	    if ( c <= 0 ) continue;
-	    Node w=g->head(e);
-	    if ( level[w] < n ) {
-	      if ( excess[w] <= 0 && w!=t ) //putting into the stack
-		{ 
-		  next.set(w,first[level[w]]);
-		  first[level[w]]=w;
-		}
-	      flow->set(e, c);
-	      excess.set(w, excess[w]+c);
-	    }
-	  }
-	break;
-      case GEN_FLOW:
+      
+      if ( flow_prop == GEN_FLOW || flow_prop == PRE_FLOW ) {
 	//Reverse_bfs from t in the residual graph,
 	//to find the starting level.
 	level.set(t,0);
 	bfs_queue.push(t);
 	
-	while (!bfs_queue.empty()) {
+	while ( !bfs_queue.empty() ) {
 	  
 	  Node v=bfs_queue.front();
 	  bfs_queue.pop();
@@ -687,54 +601,27 @@
 	      level.set(w, l);
 	    }
 	  }
-	}
-	
-	//the starting flow
-	for(OutEdgeIt e(*g,s); e!=INVALID; ++e)
-	  {
-	    Num rem=(*capacity)[e]-(*flow)[e];
-	    if ( rem <= 0 ) continue;
-	    Node w=g->head(e);
-	    if ( level[w] < n ) {
-	      if ( excess[w] <= 0 && w!=t ) //putting into the stack
-		{
-		  next.set(w,first[level[w]]);
-		  first[level[w]]=w;
-		}   
-	      flow->set(e, (*capacity)[e]);
-	      excess.set(w, excess[w]+rem);
-	    }
-	  }
+	} //while
+      } //if
+
+
+      switch (flow_prop) {
+	case NO_FLOW:  
+	for(EdgeIt e(*g); e!=INVALID; ++e) flow->set(e,0);
+	case ZERO_FLOW:
+	for(NodeIt v(*g); v!=INVALID; ++v) excess.set(v,0);
 	
-	for(InEdgeIt e(*g,s); e!=INVALID; ++e)
-	  {
-	    if ( (*flow)[e] <= 0 ) continue;
-	    Node w=g->tail(e);
-	    if ( level[w] < n ) {
-	      if ( excess[w] <= 0 && w!=t )
-		{
-		  next.set(w,first[level[w]]);
-		  first[level[w]]=w;
-		}  
-	      excess.set(w, excess[w]+(*flow)[e]);
-	      flow->set(e, 0);
-	    }
-	  }
-	break;
-      case PRE_FLOW:
-	//Reverse_bfs from t in the residual graph,
-	//to find the starting level.
+	//Reverse_bfs from t, to find the starting level.
 	level.set(t,0);
 	bfs_queue.push(t);
 	
-	while (!bfs_queue.empty()) {
+	while ( !bfs_queue.empty() ) {
 	  
 	  Node v=bfs_queue.front();
 	  bfs_queue.pop();
 	  int l=level[v]+1;
 	  
 	  for(InEdgeIt e(*g,v) ; e!=INVALID; ++e) {
-	    if ( (*capacity)[e] <= (*flow)[e] ) continue;
 	    Node w=g->tail(e);
 	    if ( level[w] == n && w != s ) {
 	      bfs_queue.push(w);
@@ -745,56 +632,87 @@
 	      level.set(w, l);
 	    }
 	  }
-	  
-	  for(OutEdgeIt e(*g,v) ; e!=INVALID; ++e) {
-	    if ( 0 >= (*flow)[e] ) continue;
-	    Node w=g->head(e);
-	    if ( level[w] == n && w != s ) {
-	      bfs_queue.push(w);
-	      Node z=level_list[l];
-	      if ( z!=INVALID ) left.set(z,w);
-	      right.set(w,z);
-	      level_list[l]=w;
-	      level.set(w, l);
-	    }
-	  }
 	}
 	
-	
 	//the starting flow
 	for(OutEdgeIt e(*g,s) ; e!=INVALID; ++e) {
+	  Num c=(*capacity)[e];
+	  if ( c <= 0 ) continue;
+	  Node w=g->head(e);
+	  if ( level[w] < n ) {
+	    if ( excess[w] <= 0 && w!=t ) { //putting into the stack
+	      next.set(w,first[level[w]]);
+	      first[level[w]]=w;
+	    }
+	    flow->set(e, c);
+	    excess.set(w, excess[w]+c);
+	  }
+	}
+	break;
+
+	case GEN_FLOW:
+	for(NodeIt v(*g); v!=INVALID; ++v) excess.set(v,0);
+	{
+	  Num exc=0;
+	  for(InEdgeIt e(*g,t) ; e!=INVALID; ++e) exc+=(*flow)[e];
+	  for(OutEdgeIt e(*g,t) ; e!=INVALID; ++e) exc-=(*flow)[e];
+	  excess.set(t,exc);
+	}
+
+	//the starting flow
+	for(OutEdgeIt e(*g,s); e!=INVALID; ++e)	{
 	  Num rem=(*capacity)[e]-(*flow)[e];
 	  if ( rem <= 0 ) continue;
 	  Node w=g->head(e);
 	  if ( level[w] < n ) {
+	    if ( excess[w] <= 0 && w!=t ) { //putting into the stack
+	      next.set(w,first[level[w]]);
+	      first[level[w]]=w;
+	    }   
 	    flow->set(e, (*capacity)[e]);
 	    excess.set(w, excess[w]+rem);
 	  }
 	}
 	
-	for(InEdgeIt e(*g,s) ; e!=INVALID; ++e) {
+	for(InEdgeIt e(*g,s); e!=INVALID; ++e) {
 	  if ( (*flow)[e] <= 0 ) continue;
 	  Node w=g->tail(e);
 	  if ( level[w] < n ) {
+	    if ( excess[w] <= 0 && w!=t ) {
+	      next.set(w,first[level[w]]);
+	      first[level[w]]=w;
+	    }  
 	    excess.set(w, excess[w]+(*flow)[e]);
 	    flow->set(e, 0);
 	  }
 	}
+	break;
+
+	case PRE_FLOW:	
+	//the starting flow
+	for(OutEdgeIt e(*g,s) ; e!=INVALID; ++e) {
+	  Num rem=(*capacity)[e]-(*flow)[e];
+	  if ( rem <= 0 ) continue;
+	  Node w=g->head(e);
+	  if ( level[w] < n ) flow->set(e, (*capacity)[e]);
+	}
+	
+	for(InEdgeIt e(*g,s) ; e!=INVALID; ++e) {
+	  if ( (*flow)[e] <= 0 ) continue;
+	  Node w=g->tail(e);
+	  if ( level[w] < n ) flow->set(e, 0);
+	}
 	
 	//computing the excess
 	for(NodeIt w(*g); w!=INVALID; ++w) {
 	  Num exc=0;
-	  
-	  for(InEdgeIt e(*g,w) ; e!=INVALID; ++e) exc+=(*flow)[e];
-	  for(OutEdgeIt e(*g,w) ; e!=INVALID; ++e) exc-=(*flow)[e];
-	  
+	  for(InEdgeIt e(*g,w); e!=INVALID; ++e) exc+=(*flow)[e];
+	  for(OutEdgeIt e(*g,w); e!=INVALID; ++e) exc-=(*flow)[e];
 	  excess.set(w,exc);
 	  
 	  //putting the active nodes into the stack
 	  int lev=level[w];
-	    if ( exc > 0 && lev < n && Node(w) != t ) 
-	      ///\bug	    if ( exc > 0 && lev < n && w != t ) temporarily for working with wrappers. 
-	    {
+	    if ( exc > 0 && lev < n && Node(w) != t ) {
 	      next.set(w,first[lev]);
 	      first[lev]=w;
 	    }
@@ -804,7 +722,7 @@
     } //preflowPreproc
 
 
-    void relabel(Node w, int newlevel, NNMap& next, VecFirst& first,
+    void relabel(Node w, int newlevel, VecNode& first, NNMap& next, 
 		 VecNode& level_list, NNMap& left,
 		 NNMap& right, int& b, int& k, bool what_heur )
     {
@@ -868,35 +786,10 @@
       }
     } //relabel
 
-    void printexcess() {////
-      std::cout << "Excesses:" <<std::endl;
-
-      for(NodeIt v(*g); v!=INVALID ; ++v) {
-	std::cout << 1+(g->id(v)) << ":" << excess[v]<<std::endl; 
-      }
-    }
-
-    void printlevel() {////
-      std::cout << "Levels:" <<std::endl;
-
-      for(NodeIt v(*g); v!=INVALID ; ++v) {
-	std::cout << 1+(g->id(v)) << ":" << level[v]<<std::endl; 
-      }
-    }
-
-    void printactive() {////
-      std::cout << "Levels:" <<std::endl;
-
-      for(NodeIt v(*g); v!=INVALID ; ++v) {
-	std::cout << 1+(g->id(v)) << ":" << level[v]<<std::endl; 
-      }
-    }
-
-
-  };  //class MaxFlow
+  }; 
 } //namespace hugo
 
-#endif //HUGO_MAX_FLOW_H
+#endif //HUGO_PREFLOW_H
 
 
 



More information about the Lemon-commits mailing list