// -*- C++ -*- /* preflow.h by jacint. 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 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. The best preflow I could ever write. The constructor runs the algorithm. Members: T maxFlow() : returns the value of a maximum flow T flowOnEdge(EdgeIt e) : for a fixed maximum flow x it returns x(e) FlowMap Flow() : returns the fixed maximum flow x 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. 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. void minCut(CutMap& M) : sets M to the characteristic vector of a min cut. M should be a map of bools initialized to false. */ #ifndef PREFLOW_H #define PREFLOW_H #define H0 20 #define H1 1 #include #include #include namespace hugo { template , typename CapMap=typename Graph::EdgeMap > class preflow { typedef typename Graph::NodeIt NodeIt; typedef typename Graph::EdgeIt EdgeIt; typedef typename Graph::EachNodeIt EachNodeIt; typedef typename Graph::OutEdgeIt OutEdgeIt; typedef typename Graph::InEdgeIt InEdgeIt; Graph& G; NodeIt s; NodeIt t; FlowMap flow; CapMap& capacity; T value; public: double time; preflow(Graph& _G, NodeIt _s, NodeIt _t, CapMap& _capacity ) : G(_G), s(_s), t(_t), flow(_G, 0), capacity(_capacity) { 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) { NodeIt w=G.tail(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); /* Starting flow. It is everywhere 0 at the moment. */ for(OutEdgeIt e=G.template first(s); e.valid(); ++e) { T c=capacity.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, c); 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 flowOnEdge(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