[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