[Lemon-commits] [lemon_svn] marci: r847 - hugo/trunk/src/work/jacint

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


Author: marci
Date: Wed May 19 18:09:38 2004
New Revision: 847

Modified:
   hugo/trunk/src/work/jacint/max_flow.h

Log:
the same


Modified: hugo/trunk/src/work/jacint/max_flow.h
==============================================================================
--- hugo/trunk/src/work/jacint/max_flow.h	(original)
+++ hugo/trunk/src/work/jacint/max_flow.h	Wed May 19 18:09:38 2004
@@ -25,22 +25,22 @@
   ///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 can be passed to the algorithm through the
+  ///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 resetSource, \ref resetTarget, \ref resetCap and
   ///\ref resetFlow. Before any subsequent runs of any algorithm of
-  ///the class \ref resetFlow should be called, otherwise it will
-  ///start from a maximum flow.                                                                                                                 
-  ///After running an algorithm of the class, the maximum value of a
-  ///value can be obtained by calling \ref flowValue(). The minimum
+  ///the class \ref resetFlow should be called. 
+
+  ///After running an algorithm of the class, 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.)                                                                                                                               
   ///\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 type of the capacity map.
-  ///\param FlowMap The type of the flow map.                                                                                                           
+  ///\param CapMap The capacity map type.
+  ///\param FlowMap The flow map type.                                                                                                           
   ///\author Marton Makai, Jacint Szabo 
   template <typename Graph, typename Num,
 	    typename CapMap=typename Graph::template EdgeMap<Num>,
@@ -111,17 +111,46 @@
     ///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{
+    enum FlowEnum{
       ZERO_FLOW,
       GEN_FLOW,
       PRE_FLOW,
       NO_FLOW
     };
 
+    enum StatusEnum {
+      AFTER_NOTHING,
+      AFTER_AUGMENTING,
+      AFTER_PRE_FLOW_PHASE_1,      
+      AFTER_PRE_FLOW_PHASE_2
+    };
+
+    /// Don not needle this flag only if necessary.
+    StatusEnum status;
+    int number_of_augmentations;
+
+
+    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) {
+	map->set(n, *number_of_augmentations);
+      }
+      bool operator[](const Node& n) const { 
+	return (*map)[n]==*number_of_augmentations; 
+      }
+    };
+    
     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) {}
+      flow(&_flow), n(_G.nodeNum()), level(_G), excess(_G,0), 
+      status(AFTER_NOTHING), number_of_augmentations(0) { }
 
     ///Runs a maximum flow algorithm.
 
@@ -132,11 +161,11 @@
     /// - 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) {
+    void run(FlowEnum fe=ZERO_FLOW) {
       preflow(fe);
     }
 
-                                                                                             
+                                                                              
     ///Runs a preflow algorithm.  
 
     ///Runs a preflow algorithm. The preflow algorithms provide the
@@ -146,7 +175,7 @@
     /// - 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 preflow(flowEnum fe) {
+    void preflow(FlowEnum fe) {
       preflowPhase1(fe);
       preflowPhase2();
     }
@@ -173,7 +202,7 @@
     /// - 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 );
+    void preflowPhase1(FlowEnum fe);
 
     ///Runs the second phase of the preflow algorithm.
 
@@ -189,6 +218,7 @@
     /// and augments the flow on if any.
     /// The return value shows if the augmentation was succesful.
     bool augmentOnShortestPath();
+    bool augmentOnShortestPath2();
 
     /// Starting from a flow, this method searches for an augmenting blocking
     /// flow according to Dinits' algorithm and augments the flow on if any.
@@ -207,7 +237,7 @@
     /// Returns the maximum value of a flow, by counting the 
     /// over-flow of the target node \ref t.
     /// It can be called already after running \ref preflowPhase1.
-    Num flowValue() {
+    Num flowValue() const {
       Num a=0;
       FOR_EACH_INC_LOC(InEdgeIt, e, *g, t) a+=(*flow)[e];
       FOR_EACH_INC_LOC(OutEdgeIt, e, *g, t) a-=(*flow)[e];
@@ -228,14 +258,31 @@
     /// of the class. This enables us to determine which methods are valid
     /// for MinCut computation
     template<typename _CutMap>
-    void actMinCut(_CutMap& M) {
+    void actMinCut(_CutMap& M) const {
       NodeIt v;
-      for(g->first(v); g->valid(v); g->next(v)) {
-	if ( level[v] < n ) {
-	  M.set(v,false);
-	} else {
-	  M.set(v,true);
+      switch (status) {
+	case AFTER_PRE_FLOW_PHASE_1:
+	for(g->first(v); g->valid(v); g->next(v)) {
+	  if (level[v] < n) {
+	    M.set(v, false);
+	  } else {
+	    M.set(v, true);
+	  }
 	}
+	break;
+	case AFTER_PRE_FLOW_PHASE_2:
+	case AFTER_NOTHING:
+	minMinCut(M);
+	break;
+	case AFTER_AUGMENTING:
+	for(g->first(v); g->valid(v); g->next(v)) {
+	  if (level[v]) {
+	    M.set(v, true);
+	  } else {
+	    M.set(v, false);
+	  }
+	}
+	break;
       }
     }
 
@@ -247,8 +294,7 @@
     ///\pre M should be a node map of bools initialized to false.
     ///\pre \c flow must be a maximum flow.
     template<typename _CutMap>
-    void minMinCut(_CutMap& M) {
-
+    void minMinCut(_CutMap& M) const {
       std::queue<Node> queue;
 
       M.set(s,true);
@@ -286,7 +332,7 @@
     ///\pre M should be a node map of bools initialized to false.
     ///\pre \c flow must be a maximum flow. 
     template<typename _CutMap>
-    void maxMinCut(_CutMap& M) {
+    void maxMinCut(_CutMap& M) const {
 
       NodeIt v;
       for(g->first(v) ; g->valid(v); g->next(v)) {
@@ -328,31 +374,31 @@
     ///\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) { minMinCut(M); }
+    void minCut(CutMap& M) const { minMinCut(M); }
 
     ///Resets the source node to \c _s.
 
     ///Resets the source node to \c _s.
     /// 
-    void resetSource(Node _s) { s=_s; }
+    void resetSource(Node _s) { s=_s; status=AFTER_NOTHING; }
 
     ///Resets the target node to \c _t.
 
     ///Resets the target node to \c _t.
     ///
-    void resetTarget(Node _t) { t=_t; }
+    void resetTarget(Node _t) { t=_t; status=AFTER_NOTHING; }
 
     /// Resets the edge map of the capacities to _cap.
 
     /// Resets the edge map of the capacities to _cap.
     /// 
-    void resetCap(const CapMap& _cap) { capacity=&_cap; }
+    void resetCap(const CapMap& _cap) { capacity=&_cap; status=AFTER_NOTHING; }
 
     /// Resets the edge map of the flows to _flow.
 
     /// Resets the edge map of the flows to _flow.
     /// 
-    void resetFlow(FlowMap& _flow) { flow=&_flow; }
+    void resetFlow(FlowMap& _flow) { flow=&_flow; status=AFTER_NOTHING; }
 
 
   private:
@@ -434,7 +480,7 @@
     }
 
 
-    void preflowPreproc(flowEnum fe, VecStack& active,
+    void preflowPreproc(FlowEnum fe, VecStack& active,
 			VecNode& level_list, NNMap& left, NNMap& right)
     {
       std::queue<Node> bfs_queue;
@@ -638,8 +684,9 @@
       void set(const typename MapGraphWrapper::Node& n, int a) {
 	dist.set(n, a);
       }
-      int operator[](const typename MapGraphWrapper::Node& n)
-      { return dist[n]; }
+      int operator[](const typename MapGraphWrapper::Node& n) const { 
+	return dist[n]; 
+      }
       //       int get(const typename MapGraphWrapper::Node& n) const {
       // 	return dist[n]; }
       //       bool get(const typename MapGraphWrapper::Edge& e) const {
@@ -653,7 +700,7 @@
 
 
   template <typename Graph, typename Num, typename CapMap, typename FlowMap>
-  void MaxFlow<Graph, Num, CapMap, FlowMap>::preflowPhase1( flowEnum fe )
+  void MaxFlow<Graph, Num, CapMap, FlowMap>::preflowPhase1(FlowEnum fe)
   {
 
     int heur0=(int)(H0*n);  //time while running 'bound decrease'
@@ -766,6 +813,8 @@
 	}
       }
     }
+
+    status=AFTER_PRE_FLOW_PHASE_1;
   }
 
 
@@ -830,6 +879,8 @@
 	}
       }  // if stack[b] is nonempty
     } // while(true)
+
+    status=AFTER_PRE_FLOW_PHASE_2;
   }
 
 
@@ -878,13 +929,67 @@
       }
     }
 
+    status=AFTER_AUGMENTING;
     return _augment;
   }
 
 
+  template <typename Graph, typename Num, typename CapMap, typename FlowMap>
+  bool MaxFlow<Graph, Num, CapMap, FlowMap>::augmentOnShortestPath2()
+  {
+    ResGW res_graph(*g, *capacity, *flow);
+    bool _augment=false;
+
+    if (status!=AFTER_AUGMENTING) {
+      FOR_EACH_LOC(typename Graph::NodeIt, e, *g) level.set(e, -1); 
+      number_of_augmentations=0;
+    } else {
+      ++number_of_augmentations;
+    }
+    TrickyReachedMap<ReachedMap> 
+      tricky_reached_map(level, number_of_augmentations);
+    //ReachedMap level(res_graph);
+//    FOR_EACH_LOC(typename Graph::NodeIt, e, *g) level.set(e, 0);
+    BfsIterator<ResGW, TrickyReachedMap<ReachedMap> > 
+      bfs(res_graph, tricky_reached_map);
+    bfs.pushAndSetReached(s);
+
+    typename ResGW::template NodeMap<ResGWEdge> pred(res_graph);
+    pred.set(s, INVALID);
 
+    typename ResGW::template NodeMap<Num> free(res_graph);
 
+    //searching for augmenting path
+    while ( !bfs.finished() ) {
+      ResGWOutEdgeIt e=bfs;
+      if (res_graph.valid(e) && bfs.isBNodeNewlyReached()) {
+	Node v=res_graph.tail(e);
+	Node w=res_graph.head(e);
+	pred.set(w, e);
+	if (res_graph.valid(pred[v])) {
+	  free.set(w, std::min(free[v], res_graph.resCap(e)));
+	} else {
+	  free.set(w, res_graph.resCap(e));
+	}
+	if (res_graph.head(e)==t) { _augment=true; break; }
+      }
+
+      ++bfs;
+    } //end of searching augmenting path
 
+    if (_augment) {
+      Node n=t;
+      Num augment_value=free[t];
+      while (res_graph.valid(pred[n])) {
+	ResGWEdge e=pred[n];
+	res_graph.augment(e, augment_value);
+	n=res_graph.tail(e);
+      }
+    }
+
+    status=AFTER_AUGMENTING;
+    return _augment;
+  }
 
 
   template <typename Graph, typename Num, typename CapMap, typename FlowMap>
@@ -999,6 +1104,7 @@
 
     }
 
+    status=AFTER_AUGMENTING;
     return _augment;
   }
 
@@ -1129,6 +1235,7 @@
 
     } //while (__augment)
 
+    status=AFTER_AUGMENTING;
     return _augment;
   }
 



More information about the Lemon-commits mailing list