[Lemon-commits] [lemon_svn] jacint: r599 - hugo/trunk/src/work/jacint
Lemon SVN
svn at lemon.cs.elte.hu
Mon Nov 6 20:40:28 CET 2006
Author: jacint
Date: Wed Apr 28 00:59:15 2004
New Revision: 599
Added:
hugo/trunk/src/work/jacint/preflow.cc
Removed:
hugo/trunk/src/work/jacint/preflow_res_comp.cc
Modified:
hugo/trunk/src/work/jacint/preflow.h
Log:
Changes in the interface and new test program added.
Added: hugo/trunk/src/work/jacint/preflow.cc
==============================================================================
--- (empty file)
+++ hugo/trunk/src/work/jacint/preflow.cc Wed Apr 28 00:59:15 2004
@@ -0,0 +1,239 @@
+#include <iostream>
+
+#include <smart_graph.h>
+#include <dimacs.h>
+#include <preflow.h>
+#include <time_measure.h>
+
+using namespace hugo;
+
+int main(int, char **) {
+
+ typedef SmartGraph Graph;
+
+ typedef Graph::Node Node;
+ typedef Graph::EdgeIt EdgeIt;
+
+ Graph G;
+ Node s, t;
+ Graph::EdgeMap<int> cap(G);
+ readDimacsMaxFlow(std::cin, G, s, t, cap);
+ Timer ts;
+
+ std::cout <<
+ "\n Testing preflow.h on a graph with " <<
+ G.nodeNum() << " nodes and " << G.edgeNum() << " edges..."
+ << std::endl;
+
+
+ Graph::EdgeMap<int> flow(G,0);
+ Preflow<Graph, int> preflow_test(G, s, t, cap, flow);
+ std::cout << "\nCalling run() (flow must be constant zero)..."<<std::endl;
+ ts.reset();
+ preflow_test.run();
+ std::cout << "Elapsed time: " << ts << std::endl;
+
+ Graph::NodeMap<bool> mincut(G);
+ preflow_test.minMinCut(mincut);
+ int min_min_cut_value=0;
+ Graph::NodeMap<bool> cut(G);
+ preflow_test.minCut(cut);
+ int min_cut_value=0;
+ Graph::NodeMap<bool> maxcut(G);
+ preflow_test.maxMinCut(maxcut);
+ int max_min_cut_value=0;
+ EdgeIt e;
+ for(G.first(e); G.valid(e); G.next(e)) {
+ int c=cap[e];
+ if (mincut[G.tail(e)] && !mincut[G.head(e)]) min_min_cut_value+=c;
+ if (cut[G.tail(e)] && !cut[G.head(e)]) min_cut_value+=c;
+ if (maxcut[G.tail(e)] && !maxcut[G.head(e)]) max_min_cut_value+=c;
+ }
+
+ std::cout << "\nChecking the result: " <<std::endl;
+ std::cout << "Flow value: "<< preflow_test.flowValue() << std::endl;
+ std::cout << "Min cut value: "<< min_cut_value << std::endl;
+ std::cout << "Min min cut value: "<< min_min_cut_value << std::endl;
+ std::cout << "Max min cut value: "<< max_min_cut_value <<
+ std::endl;
+
+ if ( preflow_test.flowValue() == min_cut_value &&
+ min_cut_value == min_min_cut_value &&
+ min_min_cut_value == max_min_cut_value )
+ std::cout << "They are equal. " <<std::endl;
+
+
+
+
+
+ Preflow<Graph, int> preflow_test2(G, s, t, cap, flow);
+ std::cout << "\n\nCalling preflow(GEN_FLOW) with the given maximum flow..."<<std::endl;
+ ts.reset();
+ preflow_test2.preflow(preflow_test2.GEN_FLOW);
+ std::cout << "Elapsed time: " << ts << std::endl;
+
+ Graph::NodeMap<bool> mincut2(G);
+ preflow_test.minMinCut(mincut2);
+ int min_min_cut2_value=0;
+ Graph::NodeMap<bool> cut2(G);
+ preflow_test.minCut(cut2);
+ int min_cut2_value=0;
+ Graph::NodeMap<bool> maxcut2(G);
+ preflow_test.maxMinCut(maxcut2);
+ int max_min_cut2_value=0;
+ for(G.first(e); G.valid(e); G.next(e)) {
+ int c=cap[e];
+ if (mincut2[G.tail(e)] && !mincut2[G.head(e)]) min_min_cut2_value+=c;
+ if (cut2[G.tail(e)] && !cut2[G.head(e)]) min_cut2_value+=c;
+ if (maxcut2[G.tail(e)] && !maxcut2[G.head(e)]) max_min_cut2_value+=c;
+ }
+
+ std::cout << "\nThe given flow value is "
+ << preflow_test2.flowValue();
+
+ if ( preflow_test2.flowValue() == min_cut2_value &&
+ min_cut2_value == min_min_cut2_value &&
+ min_min_cut2_value == max_min_cut2_value )
+ std::cout <<", which is equal to all three min cut values."
+ <<std::endl;
+
+
+
+
+
+ Graph::EdgeMap<int> flow3(G,0);
+ Preflow<Graph, int> preflow_test3(G, s, t, cap, flow3);
+ std::cout << "\n\nCalling preflowPhase0(PREFLOW) on the constant zero flow..."<<std::endl;
+ ts.reset();
+ preflow_test3.preflowPhase0(preflow_test3.PREFLOW);
+ std::cout << "Elapsed time: " << ts << std::endl;
+ Graph::NodeMap<bool> actcut3(G);
+ std::cout << "\nCalling actMinCut()..."<<std::endl;
+ preflow_test3.actMinCut(actcut3);
+ std::cout << "Calling preflowPhase1() on the given flow..."<<std::endl;
+ ts.reset();
+ preflow_test3.preflowPhase1();
+ std::cout << "Elapsed time: " << ts << std::endl;
+
+ int act_min_cut3_value=0;
+
+ Graph::NodeMap<bool> mincut3(G);
+ preflow_test.minMinCut(mincut3);
+ int min_min_cut3_value=0;
+
+ Graph::NodeMap<bool> cut3(G);
+ preflow_test.minCut(cut3);
+ int min_cut3_value=0;
+
+ Graph::NodeMap<bool> maxcut3(G);
+ preflow_test.maxMinCut(maxcut3);
+ int max_min_cut3_value=0;
+
+ for(G.first(e); G.valid(e); G.next(e)) {
+ int c=cap[e];
+ if (mincut3[G.tail(e)] && !mincut3[G.head(e)]) min_min_cut3_value+=c;
+ if (cut3[G.tail(e)] && !cut3[G.head(e)]) min_cut3_value+=c;
+ if (maxcut3[G.tail(e)] && !maxcut3[G.head(e)]) max_min_cut3_value+=c;
+ if (actcut3[G.tail(e)] && !actcut3[G.head(e)]) act_min_cut3_value+=c;
+ }
+
+ std::cout << "\nThe min cut value given by actMinCut() after phase 0 is "<<
+ act_min_cut3_value;
+
+ if ( preflow_test3.flowValue() == min_cut3_value &&
+ min_cut3_value == min_min_cut3_value &&
+ min_min_cut3_value == max_min_cut3_value &&
+ max_min_cut3_value == act_min_cut3_value ) {
+ std::cout <<
+ ", which is equal to the given flow value and to all three min cut values after phase 1."
+ <<std::endl;
+ }
+
+
+
+
+
+ Graph::EdgeMap<int> flow4(G,0);
+ Preflow<Graph, int> preflow_test4(G, s, t, cap, flow4);
+ std::cout <<
+ "\n\nCalling preflow(PREFLOW) with the constant 0 flow, the result is f..."
+ <<std::endl;
+ preflow_test4.preflow(preflow_test4.PREFLOW);
+
+ std::cout << "Swapping the source and the target, "<<std::endl;
+ std::cout << "by calling resetSource(t) and resetTarget(s)..."
+ <<std::endl;
+ preflow_test4.resetSource(t);
+ preflow_test4.resetTarget(s);
+
+ std::cout <<
+ "Calling preflow(PREFLOW) to find a maximum t-s flow starting with flow f..."
+ <<std::endl;
+ preflow_test4.preflow(preflow_test4.PREFLOW);
+
+ Graph::NodeMap<bool> mincut4(G);
+ preflow_test4.minMinCut(mincut4);
+ int min_min_cut4_value=0;
+ Graph::NodeMap<bool> cut4(G);
+ preflow_test4.minCut(cut4);
+ int min_cut4_value=0;
+ Graph::NodeMap<bool> maxcut4(G);
+ preflow_test4.maxMinCut(maxcut4);
+ int max_min_cut4_value=0;
+ for(G.first(e); G.valid(e); G.next(e)) {
+ int c=cap[e];
+ if (mincut4[G.tail(e)] && !mincut4[G.head(e)]) min_min_cut4_value+=c;
+ if (cut4[G.tail(e)] && !cut4[G.head(e)]) min_cut4_value+=c;
+ if (maxcut4[G.tail(e)] && !maxcut4[G.head(e)]) max_min_cut4_value+=c;
+ }
+
+ std::cout << "\nThe given flow value is "
+ << preflow_test4.flowValue();
+
+ if ( preflow_test4.flowValue() == min_cut4_value &&
+ min_cut4_value == min_min_cut4_value &&
+ min_min_cut4_value == max_min_cut4_value )
+ std::cout <<", which is equal to all three min cut values."
+ <<std::endl;
+
+
+
+
+ Graph::EdgeMap<int> flow5(G,0);
+ std::cout << "Resetting the stored flow to constant zero, by calling resetFlow..."
+ <<std::endl;
+ preflow_test4.resetFlow(flow5);
+ std::cout <<
+ "Calling preflow(GEN_FLOW) to find a maximum t-s flow "<<std::endl;
+ std::cout <<
+ "starting with this constant zero flow..." <<std::endl;
+ preflow_test4.preflow(preflow_test4.GEN_FLOW);
+
+ Graph::NodeMap<bool> mincut5(G);
+ preflow_test4.minMinCut(mincut5);
+ int min_min_cut5_value=0;
+ Graph::NodeMap<bool> cut5(G);
+ preflow_test4.minCut(cut5);
+ int min_cut5_value=0;
+ Graph::NodeMap<bool> maxcut5(G);
+ preflow_test4.maxMinCut(maxcut5);
+ int max_min_cut5_value=0;
+ for(G.first(e); G.valid(e); G.next(e)) {
+ int c=cap[e];
+ if (mincut5[G.tail(e)] && !mincut5[G.head(e)]) min_min_cut5_value+=c;
+ if (cut5[G.tail(e)] && !cut5[G.head(e)]) min_cut5_value+=c;
+ if (maxcut5[G.tail(e)] && !maxcut5[G.head(e)]) max_min_cut5_value+=c;
+ }
+
+ std::cout << "\nThe given flow value is "
+ << preflow_test4.flowValue();
+
+ if ( preflow_test4.flowValue() == min_cut5_value &&
+ min_cut5_value == min_min_cut5_value &&
+ min_min_cut5_value == max_min_cut5_value )
+ std::cout <<", which is equal to all three min cut values."
+ <<std::endl<<std::endl;
+
+
+ return 0;
+}
Modified: hugo/trunk/src/work/jacint/preflow.h
==============================================================================
--- hugo/trunk/src/work/jacint/preflow.h (original)
+++ hugo/trunk/src/work/jacint/preflow.h Wed Apr 28 00:59:15 2004
@@ -1,20 +1,15 @@
// -*- C++ -*-
-//run gyorsan tudna adni a minmincutot a 2 fazis elejen , ne vegyuk be konstruktorba egy cutmapet?
-//constzero jo igy?
-
-//majd marci megmondja betegyem-e bfs-t meg resgraphot
-
/*
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 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 10.
+Parameters H0 and H1 are initialized to 20 and 1.
Constructors:
@@ -28,7 +23,7 @@
T flowValue() : returns the value of a maximum flow
void minMinCut(CutMap& M) : sets M to the characteristic vector of the
- minimum min cut. M should be a map of bools initialized to false.
+ minimum min cut. M should be a map of bools initialized to false. ??Is it OK?
void maxMinCut(CutMap& M) : sets M to the characteristic vector of the
maximum min cut. M should be a map of bools initialized to false.
@@ -36,8 +31,6 @@
void minCut(CutMap& M) : sets M to the characteristic vector of
a min cut. M should be a map of bools initialized to false.
-FIXME reset
-
*/
#ifndef HUGO_PREFLOW_H
@@ -48,6 +41,7 @@
#include <vector>
#include <queue>
+#include <stack>
namespace hugo {
@@ -57,494 +51,223 @@
class Preflow {
typedef typename Graph::Node Node;
- typedef typename Graph::Edge Edge;
typedef typename Graph::NodeIt NodeIt;
typedef typename Graph::OutEdgeIt OutEdgeIt;
typedef typename Graph::InEdgeIt InEdgeIt;
-
+
+ typedef typename std::vector<std::stack<Node> > VecStack;
+ typedef typename Graph::template NodeMap<Node> NNMap;
+ typedef typename std::vector<Node> VecNode;
+
const Graph& G;
Node s;
Node t;
- const CapMap& capacity;
- FlowMap& flow;
- T value;
- bool constzero;
+ CapMap* capacity;
+ FlowMap* flow;
+ int n; //the number of nodes of G
+ typename Graph::template NodeMap<int> level;
+ typename Graph::template NodeMap<T> excess;
+
public:
+
+ enum flowEnum{
+ ZERO_FLOW=0,
+ GEN_FLOW=1,
+ PREFLOW=2
+ };
+
Preflow(Graph& _G, Node _s, Node _t, CapMap& _capacity,
- FlowMap& _flow, bool _constzero ) :
- G(_G), s(_s), t(_t), capacity(_capacity), flow(_flow), constzero(_constzero) {}
-
-
+ FlowMap& _flow) :
+ G(_G), s(_s), t(_t), capacity(&_capacity),
+ flow(&_flow), n(_G.nodeNum()), level(_G), excess(_G,0) {}
+
void run() {
-
- value=0; //for the subsequent runs
+ preflow( ZERO_FLOW );
+ }
+
+ void preflow( flowEnum fe ) {
+ preflowPhase0(fe);
+ preflowPhase1();
+ }
- bool phase=0; //phase 0 is the 1st phase, phase 1 is the 2nd
- int n=G.nodeNum();
+ void preflowPhase0( flowEnum fe ) {
+
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)
+ int numrelabel=0;
+
bool what_heur=1;
- /*
- what_heur is 0 in case 'bound decrease'
- and 1 in case 'highest label'
- */
+ //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.
- */
- int relabel=0;
+ //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
- typename Graph::template NodeMap<int> level(G,n);
- typename Graph::template NodeMap<T> excess(G);
-
- std::vector<Node> active(n-1,INVALID);
- typename Graph::template NodeMap<Node> next(G,INVALID);
- //Stack of the active nodes in level i < n.
- //We use it in both phases.
-
- typename Graph::template NodeMap<Node> left(G,INVALID);
- typename Graph::template NodeMap<Node> right(G,INVALID);
- std::vector<Node> level_list(n,INVALID);
- /*
- List of the nodes in level i<n.
- */
-
-
- if ( constzero ) {
-
- /*Reverse_bfs from t, to find the starting level.*/
- level.set(t,0);
- std::queue<Node> bfs_queue;
- bfs_queue.push(t);
-
- while (!bfs_queue.empty()) {
-
- Node v=bfs_queue.front();
- bfs_queue.pop();
- int l=level[v]+1;
-
- InEdgeIt e;
- for(G.first(e,v); G.valid(e); G.next(e)) {
- Node w=G.tail(e);
- if ( level[w] == n && w != s ) {
- bfs_queue.push(w);
- Node first=level_list[l];
- if ( G.valid(first) ) left.set(first,w);
- right.set(w,first);
- level_list[l]=w;
- level.set(w, l);
- }
- }
- }
+ VecStack active(n);
+
+ NNMap left(G,INVALID);
+ NNMap right(G,INVALID);
+ VecNode level_list(n,INVALID);
+ //List of the nodes in level i<n, set to n.
- //the starting flow
- OutEdgeIt e;
- for(G.first(e,s); G.valid(e); G.next(e))
+ NodeIt v;
+ for(G.first(v); G.valid(v); G.next(v)) level.set(v,n);
+ //setting each node to level n
+
+ switch ( fe ) {
+ case PREFLOW:
{
- T c=capacity[e];
- if ( c == 0 ) continue;
- Node w=G.head(e);
- if ( level[w] < n ) {
- if ( excess[w] == 0 && w!=t ) {
- next.set(w,active[level[w]]);
- active[level[w]]=w;
- }
- flow.set(e, c);
- excess.set(w, excess[w]+c);
- }
- }
- }
- else
- {
-
- /*
- Reverse_bfs from t in the residual graph,
- to find the starting level.
- */
- level.set(t,0);
- std::queue<Node> bfs_queue;
- bfs_queue.push(t);
-
- while (!bfs_queue.empty()) {
-
- Node v=bfs_queue.front();
- bfs_queue.pop();
- int l=level[v]+1;
-
- InEdgeIt e;
- for(G.first(e,v); G.valid(e); G.next(e)) {
- if ( capacity[e] == flow[e] ) continue;
- Node w=G.tail(e);
- if ( level[w] == n && w != s ) {
- bfs_queue.push(w);
- Node first=level_list[l];
- if ( G.valid(first) ) left.set(first,w);
- right.set(w,first);
- level_list[l]=w;
- level.set(w, l);
- }
- }
+ //counting the excess
+ NodeIt v;
+ for(G.first(v); G.valid(v); G.next(v)) {
+ T exc=0;
+
+ InEdgeIt e;
+ for(G.first(e,v); G.valid(e); G.next(e)) exc+=(*flow)[e];
+ OutEdgeIt f;
+ for(G.first(f,v); G.valid(f); G.next(f)) exc-=(*flow)[f];
- OutEdgeIt f;
- for(G.first(f,v); G.valid(f); G.next(f)) {
- if ( 0 == flow[f] ) continue;
- Node w=G.head(f);
- if ( level[w] == n && w != s ) {
- bfs_queue.push(w);
- Node first=level_list[l];
- if ( G.valid(first) ) left.set(first,w);
- right.set(w,first);
- level_list[l]=w;
- level.set(w, l);
- }
+ excess.set(v,exc);
+
+ //putting the active nodes into the stack
+ int lev=level[v];
+ if ( exc > 0 && lev < n && v != t ) active[lev].push(v);
}
+ break;
}
-
-
- /*
- Counting the excess
- */
- NodeIt v;
- for(G.first(v); G.valid(v); G.next(v)) {
+ case GEN_FLOW:
+ {
+ //Counting the excess of t
T exc=0;
-
+
InEdgeIt e;
- for(G.first(e,v); G.valid(e); G.next(e)) exc+=flow[e];
+ for(G.first(e,t); G.valid(e); G.next(e)) exc+=(*flow)[e];
OutEdgeIt f;
- for(G.first(f,v); G.valid(f); G.next(f)) exc-=flow[e];
-
- excess.set(v,exc);
-
- //putting the active nodes into the stack
- int lev=level[v];
- if ( exc > 0 && lev < n ) {
- next.set(v,active[lev]);
- active[lev]=v;
- }
- }
-
-
- //the starting flow
- OutEdgeIt e;
- for(G.first(e,s); G.valid(e); G.next(e))
- {
- T rem=capacity[e]-flow[e];
- if ( rem == 0 ) continue;
- Node w=G.head(e);
- if ( level[w] < n ) {
- if ( excess[w] == 0 && w!=t ) {
- next.set(w,active[level[w]]);
- active[level[w]]=w;
- }
- flow.set(e, capacity[e]);
- excess.set(w, excess[w]+rem);
- }
- }
-
- InEdgeIt f;
- for(G.first(f,s); G.valid(f); G.next(f))
- {
- if ( flow[f] == 0 ) continue;
- Node w=G.head(f);
- if ( level[w] < n ) {
- if ( excess[w] == 0 && w!=t ) {
- next.set(w,active[level[w]]);
- active[level[w]]=w;
- }
- excess.set(w, excess[w]+flow[f]);
- flow.set(f, 0);
- }
+ for(G.first(f,t); G.valid(f); G.next(f)) exc-=(*flow)[f];
+
+ excess.set(t,exc);
+
+ break;
}
}
-
-
-
-
- /*
- End of preprocessing
- */
-
-
-
- /*
- Push/relabel on the highest level active nodes.
- */
+
+ preflowPreproc( fe, active, level_list, left, right );
+ //End of preprocessing
+
+
+ //Push/relabel on the highest level active nodes.
while ( true ) {
-
if ( b == 0 ) {
- if ( phase ) break;
-
if ( !what_heur && !end && k > 0 ) {
b=k;
end=true;
- } else {
- phase=1;
- level.set(s,0);
- std::queue<Node> bfs_queue;
- bfs_queue.push(s);
-
- while (!bfs_queue.empty()) {
-
- Node v=bfs_queue.front();
- bfs_queue.pop();
- int l=level[v]+1;
-
- InEdgeIt e;
- for(G.first(e,v); G.valid(e); G.next(e)) {
- if ( capacity[e] == flow[e] ) continue;
- Node u=G.tail(e);
- if ( level[u] >= n ) {
- bfs_queue.push(u);
- level.set(u, l);
- if ( excess[u] > 0 ) {
- next.set(u,active[l]);
- active[l]=u;
- }
- }
- }
-
- OutEdgeIt f;
- for(G.first(f,v); G.valid(f); G.next(f)) {
- if ( 0 == flow[f] ) continue;
- Node u=G.head(f);
- if ( level[u] >= n ) {
- bfs_queue.push(u);
- level.set(u, l);
- if ( excess[u] > 0 ) {
- next.set(u,active[l]);
- active[l]=u;
- }
- }
- }
- }
- b=n-2;
- }
-
+ } else break;
}
-
-
- if ( !G.valid(active[b]) ) --b;
+
+ if ( active[b].empty() ) --b;
else {
end=false;
+ Node w=active[b].top();
+ active[b].pop();
+ int newlevel=push(w,active);
+ if ( excess[w] > 0 ) relabel(w, newlevel, active, level_list,
+ left, right, b, k, what_heur);
+
+ ++numrelabel;
+ if ( numrelabel >= heur ) {
+ numrelabel=0;
+ if ( what_heur ) {
+ what_heur=0;
+ heur=heur0;
+ end=false;
+ } else {
+ what_heur=1;
+ heur=heur1;
+ b=k;
+ }
+ }
+ }
+ }
+ }
- Node w=active[b];
- active[b]=next[w];
- int lev=level[w];
- T exc=excess[w];
- int newlevel=n; //bound on the next level of w
-
- OutEdgeIt e;
- for(G.first(e,w); G.valid(e); G.next(e)) {
-
- if ( flow[e] == capacity[e] ) continue;
- Node v=G.head(e);
- //e=wv
-
- if( lev > level[v] ) {
- /*Push is allowed now*/
-
- if ( excess[v]==0 && v!=t && v!=s ) {
- int lev_v=level[v];
- next.set(v,active[lev_v]);
- active[lev_v]=v;
- }
-
- T cap=capacity[e];
- T flo=flow[e];
- T remcap=cap-flo;
-
- if ( remcap >= exc ) {
- /*A nonsaturating push.*/
-
- flow.set(e, flo+exc);
- excess.set(v, excess[v]+exc);
- exc=0;
- break;
-
- } else {
- /*A saturating push.*/
-
- flow.set(e, cap);
- excess.set(v, excess[v]+remcap);
- exc-=remcap;
- }
- } else if ( newlevel > level[v] ){
- newlevel = level[v];
- }
+
+ void preflowPhase1() {
+
+ 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
+
+ VecStack active(n);
+ level.set(s,0);
+ std::queue<Node> bfs_queue;
+ bfs_queue.push(s);
- } //for out edges wv
+ while (!bfs_queue.empty()) {
-
- if ( exc > 0 ) {
- InEdgeIt e;
- for(G.first(e,w); G.valid(e); G.next(e)) {
-
- if( flow[e] == 0 ) continue;
- Node v=G.tail(e);
- //e=vw
-
- if( lev > level[v] ) {
- /*Push is allowed now*/
-
- if ( excess[v]==0 && v!=t && v!=s ) {
- int lev_v=level[v];
- next.set(v,active[lev_v]);
- active[lev_v]=v;
- }
+ Node v=bfs_queue.front();
+ bfs_queue.pop();
+ int l=level[v]+1;
- T flo=flow[e];
-
- if ( flo >= exc ) {
- /*A nonsaturating push.*/
-
- flow.set(e, flo-exc);
- excess.set(v, excess[v]+exc);
- exc=0;
- break;
- } else {
- /*A saturating push.*/
-
- excess.set(v, excess[v]+flo);
- exc-=flo;
- flow.set(e,0);
- }
- } else if ( newlevel > level[v] ) {
- newlevel = level[v];
- }
- } //for in edges vw
-
- } // if w still has excess after the out edge for cycle
-
- excess.set(w, exc);
-
- /*
- Relabel
- */
+ InEdgeIt e;
+ for(G.first(e,v); G.valid(e); G.next(e)) {
+ if ( (*capacity)[e] == (*flow)[e] ) continue;
+ Node u=G.tail(e);
+ if ( level[u] >= n ) {
+ bfs_queue.push(u);
+ level.set(u, l);
+ if ( excess[u] > 0 ) active[l].push(u);
+ }
+ }
+ OutEdgeIt f;
+ for(G.first(f,v); G.valid(f); G.next(f)) {
+ if ( 0 == (*flow)[f] ) continue;
+ Node u=G.head(f);
+ if ( level[u] >= n ) {
+ bfs_queue.push(u);
+ level.set(u, l);
+ if ( excess[u] > 0 ) active[l].push(u);
+ }
+ }
+ }
+ b=n-2;
- if ( exc > 0 ) {
- //now 'lev' is the old level of w
+ while ( true ) {
- if ( phase ) {
- level.set(w,++newlevel);
- next.set(w,active[newlevel]);
- active[newlevel]=w;
- b=newlevel;
- } else {
- //unlacing starts
- Node right_n=right[w];
- Node left_n=left[w];
-
- if ( G.valid(right_n) ) {
- if ( G.valid(left_n) ) {
- right.set(left_n, right_n);
- left.set(right_n, left_n);
- } else {
- level_list[lev]=right_n;
- left.set(right_n, INVALID);
- }
- } else {
- if ( G.valid(left_n) ) {
- right.set(left_n, INVALID);
- } else {
- level_list[lev]=INVALID;
- }
- }
- //unlacing ends
-
- if ( !G.valid(level_list[lev]) ) {
-
- //gapping starts
- for (int i=lev; i!=k ; ) {
- Node v=level_list[++i];
- while ( G.valid(v) ) {
- level.set(v,n);
- v=right[v];
- }
- level_list[i]=INVALID;
- if ( !what_heur ) active[i]=INVALID;
- }
-
- level.set(w,n);
- b=lev-1;
- k=b;
- //gapping ends
-
- } else {
-
- if ( newlevel == n ) level.set(w,n);
- else {
- level.set(w,++newlevel);
- next.set(w,active[newlevel]);
- active[newlevel]=w;
- if ( what_heur ) b=newlevel;
- if ( k < newlevel ) ++k; //now k=newlevel
- Node first=level_list[newlevel];
- if ( G.valid(first) ) left.set(first,w);
- right.set(w,first);
- left.set(w,INVALID);
- level_list[newlevel]=w;
- }
- }
+ if ( b == 0 ) break;
+ if ( active[b].empty() ) --b;
+ else {
+ Node w=active[b].top();
+ active[b].pop();
+ int newlevel=push(w,active);
- ++relabel;
- if ( relabel >= heur ) {
- relabel=0;
- if ( what_heur ) {
- what_heur=0;
- heur=heur0;
- end=false;
- } else {
- what_heur=1;
- heur=heur1;
- b=k;
- }
- }
- } //phase 0
-
-
- } // if ( exc > 0 )
-
-
+ //relabel
+ if ( excess[w] > 0 ) {
+ level.set(w,++newlevel);
+ active[newlevel].push(w);
+ b=newlevel;
+ }
} // if stack[b] is nonempty
-
} // while(true)
+ }
- value = excess[t];
- /*Max flow value.*/
-
- } //void run()
-
-
-
-
-
- /*
- Returns the maximum value of a flow.
- */
-
+ //Returns the maximum value of a flow.
T flowValue() {
- return value;
+ return excess[t];
}
-
- FlowMap Flow() {
- return flow;
- }
-
-
-
- void Flow(FlowMap& _flow ) {
+ //should be used only between preflowPhase0 and preflowPhase1
+ template<typename _CutMap>
+ void actMinCut(_CutMap& M) {
NodeIt v;
- for(G.first(v) ; G.valid(v); G.next(v))
- _flow.set(v,flow[v]);
+ for(G.first(v); G.valid(v); G.next(v))
+ if ( level[v] < n ) M.set(v,false);
+ else M.set(v,true);
}
@@ -552,7 +275,6 @@
/*
Returns the minimum min cut, by a bfs from s in the residual graph.
*/
-
template<typename _CutMap>
void minMinCut(_CutMap& M) {
@@ -568,7 +290,7 @@
OutEdgeIt e;
for(G.first(e,w) ; G.valid(e); G.next(e)) {
Node v=G.head(e);
- if (!M[v] && flow[e] < capacity[e] ) {
+ if (!M[v] && (*flow)[e] < (*capacity)[e] ) {
queue.push(v);
M.set(v, true);
}
@@ -577,7 +299,7 @@
InEdgeIt f;
for(G.first(f,w) ; G.valid(f); G.next(f)) {
Node v=G.tail(f);
- if (!M[v] && flow[f] > 0 ) {
+ if (!M[v] && (*flow)[f] > 0 ) {
queue.push(v);
M.set(v, true);
}
@@ -594,10 +316,15 @@
template<typename _CutMap>
void maxMinCut(_CutMap& M) {
-
+
+ NodeIt v;
+ for(G.first(v) ; G.valid(v); G.next(v)) {
+ M.set(v, true);
+ }
+
std::queue<Node> queue;
- M.set(t,true);
+ M.set(t,false);
queue.push(t);
while (!queue.empty()) {
@@ -608,56 +335,319 @@
InEdgeIt e;
for(G.first(e,w) ; G.valid(e); G.next(e)) {
Node v=G.tail(e);
- if (!M[v] && flow[e] < capacity[e] ) {
+ if (M[v] && (*flow)[e] < (*capacity)[e] ) {
queue.push(v);
- M.set(v, true);
+ M.set(v, false);
}
}
OutEdgeIt f;
for(G.first(f,w) ; G.valid(f); G.next(f)) {
Node v=G.head(f);
- if (!M[v] && flow[f] > 0 ) {
+ if (M[v] && (*flow)[f] > 0 ) {
queue.push(v);
- M.set(v, true);
+ M.set(v, false);
}
}
}
-
- NodeIt v;
- for(G.first(v) ; G.valid(v); G.next(v)) {
- M.set(v, !M[v]);
- }
-
}
-
template<typename CutMap>
void minCut(CutMap& M) {
minMinCut(M);
}
- void reset_target (Node _t) {t=_t;}
- void reset_source (Node _s) {s=_s;}
-
- template<typename _CapMap>
- void reset_cap (_CapMap _cap) {capacity=_cap;}
+ void resetTarget (const Node _t) {t=_t;}
- template<typename _FlowMap>
- void reset_cap (_FlowMap _flow, bool _constzero) {
- flow=_flow;
- constzero=_constzero;
+ void resetSource (const Node _s) {s=_s;}
+
+ void resetCap (const CapMap& _cap) {
+ capacity=&_cap;
+ }
+
+ void resetFlow (FlowMap& _flow) {
+ flow=&_flow;
}
+ private:
+
+ int push(const Node w, VecStack& active) {
+
+ int lev=level[w];
+ T exc=excess[w];
+ int newlevel=n; //bound on the next level of w
+
+ OutEdgeIt e;
+ for(G.first(e,w); G.valid(e); G.next(e)) {
+
+ if ( (*flow)[e] == (*capacity)[e] ) continue;
+ Node v=G.head(e);
+
+ if( lev > level[v] ) { //Push is allowed now
+
+ if ( excess[v]==0 && v!=t && v!=s ) {
+ int lev_v=level[v];
+ active[lev_v].push(v);
+ }
+
+ T cap=(*capacity)[e];
+ T flo=(*flow)[e];
+ T remcap=cap-flo;
+
+ if ( remcap >= exc ) { //A nonsaturating push.
+
+ flow->set(e, flo+exc);
+ excess.set(v, excess[v]+exc);
+ exc=0;
+ break;
+
+ } else { //A saturating push.
+ flow->set(e, cap);
+ excess.set(v, excess[v]+remcap);
+ exc-=remcap;
+ }
+ } else if ( newlevel > level[v] ) newlevel = level[v];
+ } //for out edges wv
+
+ if ( exc > 0 ) {
+ InEdgeIt e;
+ for(G.first(e,w); G.valid(e); G.next(e)) {
+
+ if( (*flow)[e] == 0 ) continue;
+ Node v=G.tail(e);
+
+ if( lev > level[v] ) { //Push is allowed now
+
+ if ( excess[v]==0 && v!=t && v!=s ) {
+ int lev_v=level[v];
+ active[lev_v].push(v);
+ }
+
+ T flo=(*flow)[e];
+
+ if ( flo >= exc ) { //A nonsaturating push.
+
+ flow->set(e, flo-exc);
+ excess.set(v, excess[v]+exc);
+ exc=0;
+ break;
+ } else { //A saturating push.
+
+ excess.set(v, excess[v]+flo);
+ exc-=flo;
+ flow->set(e,0);
+ }
+ } else if ( newlevel > level[v] ) newlevel = level[v];
+ } //for in edges vw
+
+ } // if w still has excess after the out edge for cycle
+
+ excess.set(w, exc);
+
+ return newlevel;
+ }
+
+
+ void preflowPreproc ( flowEnum fe, VecStack& active,
+ VecNode& level_list, NNMap& left, NNMap& right ) {
+
+ std::queue<Node> bfs_queue;
+
+ switch ( fe ) {
+ 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;
+
+ InEdgeIt e;
+ for(G.first(e,v); G.valid(e); G.next(e)) {
+ Node w=G.tail(e);
+ if ( level[w] == n && w != s ) {
+ bfs_queue.push(w);
+ Node first=level_list[l];
+ if ( G.valid(first) ) left.set(first,w);
+ right.set(w,first);
+ level_list[l]=w;
+ level.set(w, l);
+ }
+ }
+ }
+
+ //the starting flow
+ OutEdgeIt e;
+ for(G.first(e,s); G.valid(e); G.next(e))
+ {
+ T c=(*capacity)[e];
+ if ( c == 0 ) continue;
+ Node w=G.head(e);
+ if ( level[w] < n ) {
+ if ( excess[w] == 0 && w!=t ) active[level[w]].push(w);
+ flow->set(e, c);
+ excess.set(w, excess[w]+c);
+ }
+ }
+ break;
+ }
+
+ case GEN_FLOW:
+ case PREFLOW:
+ {
+ //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()) {
+
+ Node v=bfs_queue.front();
+ bfs_queue.pop();
+ int l=level[v]+1;
+
+ InEdgeIt e;
+ for(G.first(e,v); G.valid(e); G.next(e)) {
+ if ( (*capacity)[e] == (*flow)[e] ) continue;
+ Node w=G.tail(e);
+ if ( level[w] == n && w != s ) {
+ bfs_queue.push(w);
+ Node first=level_list[l];
+ if ( G.valid(first) ) left.set(first,w);
+ right.set(w,first);
+ level_list[l]=w;
+ level.set(w, l);
+ }
+ }
+
+ OutEdgeIt f;
+ for(G.first(f,v); G.valid(f); G.next(f)) {
+ if ( 0 == (*flow)[f] ) continue;
+ Node w=G.head(f);
+ if ( level[w] == n && w != s ) {
+ bfs_queue.push(w);
+ Node first=level_list[l];
+ if ( G.valid(first) ) left.set(first,w);
+ right.set(w,first);
+ level_list[l]=w;
+ level.set(w, l);
+ }
+ }
+ }
+
+
+ //the starting flow
+ OutEdgeIt e;
+ for(G.first(e,s); G.valid(e); G.next(e))
+ {
+ T rem=(*capacity)[e]-(*flow)[e];
+ if ( rem == 0 ) continue;
+ Node w=G.head(e);
+ if ( level[w] < n ) {
+ if ( excess[w] == 0 && w!=t ) active[level[w]].push(w);
+ flow->set(e, (*capacity)[e]);
+ excess.set(w, excess[w]+rem);
+ }
+ }
+
+ InEdgeIt f;
+ for(G.first(f,s); G.valid(f); G.next(f))
+ {
+ if ( (*flow)[f] == 0 ) continue;
+ Node w=G.tail(f);
+ if ( level[w] < n ) {
+ if ( excess[w] == 0 && w!=t ) active[level[w]].push(w);
+ excess.set(w, excess[w]+(*flow)[f]);
+ flow->set(f, 0);
+ }
+ }
+ break;
+ } //case PREFLOW
+ }
+ } //preflowPreproc
+
+
+
+ void relabel( const Node w, int newlevel, VecStack& active,
+ VecNode& level_list, NNMap& left,
+ NNMap& right, int& b, int& k, const bool what_heur ) {
+
+ T lev=level[w];
+
+ Node right_n=right[w];
+ Node left_n=left[w];
+
+ //unlacing starts
+ if ( G.valid(right_n) ) {
+ if ( G.valid(left_n) ) {
+ right.set(left_n, right_n);
+ left.set(right_n, left_n);
+ } else {
+ level_list[lev]=right_n;
+ left.set(right_n, INVALID);
+ }
+ } else {
+ if ( G.valid(left_n) ) {
+ right.set(left_n, INVALID);
+ } else {
+ level_list[lev]=INVALID;
+ }
+ }
+ //unlacing ends
+
+ if ( !G.valid(level_list[lev]) ) {
+
+ //gapping starts
+ for (int i=lev; i!=k ; ) {
+ Node v=level_list[++i];
+ while ( G.valid(v) ) {
+ level.set(v,n);
+ v=right[v];
+ }
+ level_list[i]=INVALID;
+ if ( !what_heur ) {
+ while ( !active[i].empty() ) {
+ active[i].pop(); //FIXME: ezt szebben kene
+ }
+ }
+ }
+
+ level.set(w,n);
+ b=lev-1;
+ k=b;
+ //gapping ends
+
+ } else {
+
+ if ( newlevel == n ) level.set(w,n);
+ else {
+ level.set(w,++newlevel);
+ active[newlevel].push(w);
+ if ( what_heur ) b=newlevel;
+ if ( k < newlevel ) ++k; //now k=newlevel
+ Node first=level_list[newlevel];
+ if ( G.valid(first) ) left.set(first,w);
+ right.set(w,first);
+ left.set(w,INVALID);
+ level_list[newlevel]=w;
+ }
+ }
+
+ } //relabel
+
};
} //namespace hugo
-#endif //PREFLOW_H
+#endif //HUGO_PREFLOW_H
More information about the Lemon-commits
mailing list