diff -r c76f1eea05d2 -r ca164520d31a src/work/jacint/preflow_aug.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/work/jacint/preflow_aug.h Mon Mar 01 14:43:07 2004 +0000 @@ -0,0 +1,588 @@ +// -*- C++ -*- + +//hogy kell azt megcsinalni hogy a konstruktorban a FlowMap-nek legyen default erteke (a 0 map) + +/* +preflow_aug.h +by jacint. + +The same as preflow.h, the only difference is that here +we start from a given flow. + + +The constructor runs the algorithm: + +template , + typename Graph_EdgeMap_T_2=typename Graph::EdgeMap > +PreflowAug(Graph G, G_NodeIt s, G_NodeIt t, G_EdgeMap_T_1 capacity, + G_EdgeMap_T_2 flow, bool flow_type) + +'capacity' must be non-negative, if flow_type=0 then +'flow' must be a flow, otherwise it must be a preflow. + + +Members: + +T maxFlow() : returns the value of a maximum flow + +T flow(G_EdgeIt e) : for a fixed maximum flow x it returns x(e) + +G_EdgeMap_T_2 flow() : returns the fixed maximum flow x + +void minMinCut(G_NodeMap_bool& M) : + sets M to the characteristic vector of the + minimum min cut. M must be initialized to false. + +void maxMinCut(G_NodeMap_bool& M) : + sets M to the characteristic vector of the + maximum min cut. M must be initialized to false. + +void minCut(G_NodeMap_bool& M) : + sets M to the characteristic vector of a + min cut. M must be initialized to false. +*/ + +#ifndef PREFLOW_H +#define PREFLOW_H + +#define H0 20 +#define H1 1 + +#include +#include + +#include //for error handling + +#include + +namespace hugo { + + template , + typename FlowMap=typename Graph::EdgeMap > + class PreflowAug { + + typedef typename Graph::NodeIt NodeIt; + typedef typename Graph::EdgeIt EdgeIt; + typedef typename Graph::EachNodeIt EachNodeIt; + typedef typename Graph::EachEdgeIt EachEdgeIt; + typedef typename Graph::OutEdgeIt OutEdgeIt; + typedef typename Graph::InEdgeIt InEdgeIt; + + Graph& G; + NodeIt s; + NodeIt t; + CapMap& capacity; + FlowMap& _flow; + bool flow_type; + T value; + + public: + double time; + PreflowAug(Graph& _G, NodeIt _s, NodeIt _t, + CapMap& _capacity, FlowMap& __flow, bool _flow_type ) : + G(_G), s(_s), t(_t), capacity(_capacity), _flow(__flow), + flow_type(_flow_type) + { + + + bool phase=0; //phase 0 is the 1st phase, phase 1 is the 2nd + int n=G.nodeNum(); + 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) + bool what_heur=1; + /* + what_heur 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; + 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::NodeMap level(G,n); + typename Graph::NodeMap excess(G); + + std::vector active(n); + typename Graph::NodeMap next(G); + //Stack of the active nodes in level i < n. + //We use it in both phases. + + typename Graph::NodeMap left(G); + typename Graph::NodeMap right(G); + std::vector level_list(n); + /* + List of the nodes in level i bfs_queue; + bfs_queue.push(t); + + + while (!bfs_queue.empty()) { + + NodeIt v=bfs_queue.front(); + bfs_queue.pop(); + int l=level.get(v)+1; + + for(InEdgeIt e=G.template first(v); e.valid(); ++e) { + if ( capacity.get(e) == _flow.get(e) ) continue; + NodeIt w=G.tail(e); + if ( level.get(w) == n && w != s ) { + bfs_queue.push(w); + NodeIt first=level_list[l]; + if ( first.valid() ) left.set(first,w); + right.set(w,first); + level_list[l]=w; + level.set(w, l); + } + } + + for(OutEdgeIt e=G.template first(v); e.valid(); ++e) { + if ( 0 == _flow.get(e) ) continue; + NodeIt w=G.head(e); + if ( level.get(w) == n && w != s ) { + bfs_queue.push(w); + NodeIt first=level_list[l]; + if ( first != 0 ) left.set(first,w); + right.set(w,first); + level_list[l]=w; + level.set(w, l); + } + } + } + + level.set(s,n); + + + + /*The starting excess.*/ + if ( flow_type ) { + for(EachEdgeIt e=G.template first(); e.valid(); ++e) { + if ( _flow.get(e) > 0 ) { + T flo=_flow.get(e); + NodeIt u=G.tail(e); + NodeIt v=G.head(e); + excess.set(u, excess.get(u)-flo); + excess.set(v, excess.get(v)+flo); + } + } + + for(EachNodeIt v=G.template first(); v.valid(); ++v) { + if ( excess.get(v) < 0 ) { + std::cerr<<"It is not a pre_flow."<(s); e.valid(); ++e) + { + T c=capacity.get(e)-_flow.get(e); + if ( c == 0 ) continue; + NodeIt w=G.head(e); + if ( level.get(w) < n ) { + if ( excess.get(w) == 0 && w!=t ) { + next.set(w,active[level.get(w)]); + active[level.get(w)]=w; + } + _flow.set(e, capacity.get(e)); + excess.set(w, excess.get(w)+c); + } + } + + /* + 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; + time=currTime(); + level.set(s,0); + std::queue bfs_queue; + bfs_queue.push(s); + + while (!bfs_queue.empty()) { + + NodeIt v=bfs_queue.front(); + bfs_queue.pop(); + int l=level.get(v)+1; + + for(InEdgeIt e=G.template first(v); e.valid(); ++e) { + if ( capacity.get(e) == _flow.get(e) ) continue; + NodeIt u=G.tail(e); + if ( level.get(u) >= n ) { + bfs_queue.push(u); + level.set(u, l); + if ( excess.get(u) > 0 ) { + next.set(u,active[l]); + active[l]=u; + } + } + } + + for(OutEdgeIt e=G.template first(v); e.valid(); ++e) { + if ( 0 == _flow.get(e) ) continue; + NodeIt u=G.head(e); + if ( level.get(u) >= n ) { + bfs_queue.push(u); + level.set(u, l); + if ( excess.get(u) > 0 ) { + next.set(u,active[l]); + active[l]=u; + } + } + } + } + b=n-2; + } + + } + + + if ( active[b] == 0 ) --b; + else { + end=false; + + NodeIt w=active[b]; + active[b]=next.get(w); + int lev=level.get(w); + T exc=excess.get(w); + int newlevel=n; //bound on the next level of w + + for(OutEdgeIt e=G.template first(w); e.valid(); ++e) { + + if ( _flow.get(e) == capacity.get(e) ) continue; + NodeIt v=G.head(e); + //e=wv + + if( lev > level.get(v) ) { + /*Push is allowed now*/ + + if ( excess.get(v)==0 && v!=t && v!=s ) { + int lev_v=level.get(v); + next.set(v,active[lev_v]); + active[lev_v]=v; + } + + T cap=capacity.get(e); + T flo=_flow.get(e); + T remcap=cap-flo; + + if ( remcap >= exc ) { + /*A nonsaturating push.*/ + + _flow.set(e, flo+exc); + excess.set(v, excess.get(v)+exc); + exc=0; + break; + + } else { + /*A saturating push.*/ + + _flow.set(e, cap); + excess.set(v, excess.get(v)+remcap); + exc-=remcap; + } + } else if ( newlevel > level.get(v) ){ + newlevel = level.get(v); + } + + } //for out edges wv + + + if ( exc > 0 ) { + for( InEdgeIt e=G.template first(w); e.valid(); ++e) { + + if( _flow.get(e) == 0 ) continue; + NodeIt v=G.tail(e); + //e=vw + + if( lev > level.get(v) ) { + /*Push is allowed now*/ + + if ( excess.get(v)==0 && v!=t && v!=s ) { + int lev_v=level.get(v); + next.set(v,active[lev_v]); + active[lev_v]=v; + } + + T flo=_flow.get(e); + + if ( flo >= exc ) { + /*A nonsaturating push.*/ + + _flow.set(e, flo-exc); + excess.set(v, excess.get(v)+exc); + exc=0; + break; + } else { + /*A saturating push.*/ + + excess.set(v, excess.get(v)+flo); + exc-=flo; + _flow.set(e,0); + } + } else if ( newlevel > level.get(v) ) { + newlevel = level.get(v); + } + } //for in edges vw + + } // if w still has excess after the out edge for cycle + + excess.set(w, exc); + + /* + Relabel + */ + + + if ( exc > 0 ) { + //now 'lev' is the old level of w + + if ( phase ) { + level.set(w,++newlevel); + next.set(w,active[newlevel]); + active[newlevel]=w; + b=newlevel; + } else { + //unlacing starts + NodeIt right_n=right.get(w); + NodeIt left_n=left.get(w); + + if ( right_n != 0 ) { + if ( left_n != 0 ) { + right.set(left_n, right_n); + left.set(right_n, left_n); + } else { + level_list[lev]=right_n; + left.set(right_n, 0); + } + } else { + if ( left_n != 0 ) { + right.set(left_n, 0); + } else { + level_list[lev]=0; + + } + } + //unlacing ends + + //gapping starts + if ( level_list[lev]==0 ) { + + for (int i=lev; i!=k ; ) { + NodeIt v=level_list[++i]; + while ( v != 0 ) { + level.set(v,n); + v=right.get(v); + } + level_list[i]=0; + if ( !what_heur ) active[i]=0; + } + + 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; + NodeIt first=level_list[newlevel]; + if ( first != 0 ) left.set(first,w); + right.set(w,first); + left.set(w,0); + level_list[newlevel]=w; + } + } + + + ++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 ) + + + } // if stack[b] is nonempty + + } // while(true) + + + value = excess.get(t); + /*Max flow value.*/ + + } //void run() + + + + + + /* + Returns the maximum value of a flow. + */ + + T maxFlow() { + return value; + } + + + + /* + For the maximum flow x found by the algorithm, + it returns the flow value on edge e, i.e. x(e). + */ + + T flow(EdgeIt e) { + return _flow.get(e); + } + + + + FlowMap flow() { + return _flow; + } + + + + void flow(FlowMap& __flow ) { + for(EachNodeIt v=G.template first(); v.valid(); ++v) + __flow.set(v,_flow.get(v)); + } + + + + /* + Returns the minimum min cut, by a bfs from s in the residual graph. + */ + + template + void minMinCut(_CutMap& M) { + + std::queue queue; + + M.set(s,true); + queue.push(s); + + while (!queue.empty()) { + NodeIt w=queue.front(); + queue.pop(); + + for(OutEdgeIt e=G.template first(w) ; e.valid(); ++e) { + NodeIt v=G.head(e); + if (!M.get(v) && _flow.get(e) < capacity.get(e) ) { + queue.push(v); + M.set(v, true); + } + } + + for(InEdgeIt e=G.template first(w) ; e.valid(); ++e) { + NodeIt v=G.tail(e); + if (!M.get(v) && _flow.get(e) > 0 ) { + queue.push(v); + M.set(v, true); + } + } + } + } + + + + /* + Returns the maximum min cut, by a reverse bfs + from t in the residual graph. + */ + + template + void maxMinCut(_CutMap& M) { + + std::queue queue; + + M.set(t,true); + queue.push(t); + + while (!queue.empty()) { + NodeIt w=queue.front(); + queue.pop(); + + for(InEdgeIt e=G.template first(w) ; e.valid(); ++e) { + NodeIt v=G.tail(e); + if (!M.get(v) && _flow.get(e) < capacity.get(e) ) { + queue.push(v); + M.set(v, true); + } + } + + for(OutEdgeIt e=G.template first(w) ; e.valid(); ++e) { + NodeIt v=G.head(e); + if (!M.get(v) && _flow.get(e) > 0 ) { + queue.push(v); + M.set(v, true); + } + } + } + + for(EachNodeIt v=G.template first() ; v.valid(); ++v) { + M.set(v, !M.get(v)); + } + + } + + + + template + void minCut(CutMap& M) { + minMinCut(M); + } + + + }; +}//namespace marci +#endif + + + +