COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/work/jacint/preflow_hl2.h @ 98:ba20e7ab1baa

Last change on this file since 98:ba20e7ab1baa was 98:ba20e7ab1baa, checked in by jacint, 20 years ago

egyfajta preflow

File size: 8.3 KB
Line 
1// -*- C++ -*-
2/*
3preflow_hl2.h
4by jacint.
5Runs the highest label variant of the preflow push algorithm with
6running time O(n^2\sqrt(m)), with the 'empty level' and with the
7heuristic that the bound b on the active nodes is not increased
8only when b=0, when we put b=2*n-2.
9
10'A' is a parameter for the empty_level heuristic
11
12Member functions:
13
14void run() : runs the algorithm
15
16 The following functions should be used after run() was already run.
17
18T maxflow() : returns the value of a maximum flow
19
20T flowonedge(EdgeIt e) : for a fixed maximum flow x it returns x(e)
21
22FlowMap allflow() : returns the fixed maximum flow x
23
24void mincut(CutMap& M) : sets M to the characteristic vector of a
25     minimum cut. M should be a map of bools initialized to false.
26
27void min_mincut(CutMap& M) : sets M to the characteristic vector of the
28     minimum min cut. M should be a map of bools initialized to false.
29
30void max_mincut(CutMap& M) : sets M to the characteristic vector of the
31     maximum min cut. M should be a map of bools initialized to false.
32
33*/
34
35#ifndef PREFLOW_HL2_H
36#define PREFLOW_HL2_H
37
38#define A 1
39
40#include <vector>
41#include <stack>
42#include <queue>
43
44namespace marci {
45
46  template <typename Graph, typename T,
47    typename FlowMap=typename Graph::EdgeMap<T>, typename CapMap=typename Graph::EdgeMap<T>,
48    typename IntMap=typename Graph::NodeMap<int>, typename TMap=typename Graph::NodeMap<T> >
49  class preflow_hl2 {
50   
51    typedef typename Graph::NodeIt NodeIt;
52    typedef typename Graph::EdgeIt EdgeIt;
53    typedef typename Graph::EachNodeIt EachNodeIt;
54    typedef typename Graph::OutEdgeIt OutEdgeIt;
55    typedef typename Graph::InEdgeIt InEdgeIt;
56   
57    Graph& G;
58    NodeIt s;
59    NodeIt t;
60    FlowMap flow;
61    CapMap& capacity; 
62    T value;
63   
64  public:
65
66    preflow_hl2(Graph& _G, NodeIt _s, NodeIt _t, CapMap& _capacity) :
67      G(_G), s(_s), t(_t), flow(_G, 0), capacity(_capacity) { }
68
69
70    void run() {
71 
72      bool no_end=true;
73      int n=G.nodeNum();
74      int b=n-2;
75      /*
76        b is a bound on the highest level of an active node.
77        In the beginning it is at most n-2.
78      */
79
80      IntMap level(G,n);     
81      TMap excess(G);
82     
83      std::vector<int> numb(n+1);   
84      /*
85        The number of nodes on level i < n. It is
86        initialized to n+1, because of the reverse_bfs-part.
87      */
88
89      std::vector<std::stack<NodeIt> > stack(2*n-1);   
90      //Stack of the active nodes in level i.
91
92
93      /*Reverse_bfs from t, to find the starting level.*/
94      level.set(t,0);
95      std::queue<NodeIt> bfs_queue;
96      bfs_queue.push(t);
97
98      while (!bfs_queue.empty()) {
99
100        NodeIt v=bfs_queue.front();     
101        bfs_queue.pop();
102        int l=level.get(v)+1;
103
104        for(InEdgeIt e=G.template first<InEdgeIt>(v); e.valid(); ++e) {
105          NodeIt w=G.tail(e);
106          if ( level.get(w) == n ) {
107            bfs_queue.push(w);
108            ++numb[l];
109            level.set(w, l);
110          }
111        }
112      }
113     
114      level.set(s,n);
115
116
117
118      /* Starting flow. It is everywhere 0 at the moment. */     
119      for(OutEdgeIt e=G.template first<OutEdgeIt>(s); e.valid(); ++e)
120        {
121          if ( capacity.get(e) == 0 ) continue;
122          NodeIt w=G.head(e);
123          if ( w!=s ) {   
124            if ( excess.get(w) == 0 && w!=t ) stack[level.get(w)].push(w);
125            flow.set(e, capacity.get(e));
126            excess.set(w, excess.get(w)+capacity.get(e));
127          }
128        }
129
130      /*
131         End of preprocessing
132      */
133
134
135
136      /*
137        Push/relabel on the highest level active nodes.
138      */       
139      /*While there exists an active node.*/
140      while (b) {
141        if ( stack[b].empty() ) {
142          if ( b==1 ) {
143            if ( !no_end ) break;
144            else {
145              b=2*n-2;
146              no_end=false;
147            }
148          }
149          --b;
150        } else {
151         
152          no_end=true;
153         
154          NodeIt w=stack[b].top();        //w is a highest label active node.
155          stack[b].pop();           
156          int lev=level.get(w);
157          int exc=excess.get(w);
158          int newlevel=2*n-2;      //In newlevel we bound the next level of w.
159         
160          //  if ( level.get(w) < n ) { //Nem tudom ez mukodik-e
161          for(OutEdgeIt e=G.template first<OutEdgeIt>(w); e.valid(); ++e) {
162           
163            if ( flow.get(e) == capacity.get(e) ) continue;
164            NodeIt v=G.head(e);           
165            //e=wv         
166           
167            if( lev > level.get(v) ) {     
168              /*Push is allowed now*/
169             
170              if ( excess.get(v)==0 && v != s && v !=t )
171                stack[level.get(v)].push(v);
172              /*v becomes active.*/
173             
174              int cap=capacity.get(e);
175              int flo=flow.get(e);
176              int remcap=cap-flo;
177             
178              if ( remcap >= exc ) {       
179                /*A nonsaturating push.*/
180               
181                flow.set(e, flo+exc);
182                excess.set(v, excess.get(v)+exc);
183                exc=0;
184                break;
185               
186              } else {
187                /*A saturating push.*/
188               
189                flow.set(e, cap );
190                excess.set(v, excess.get(v)+remcap);
191                exc-=remcap;
192              }
193            } else if ( newlevel > level.get(v) ) newlevel = level.get(v);
194           
195          } //for out edges wv
196       
197       
198        if ( exc > 0 ) {       
199          for( InEdgeIt e=G.template first<InEdgeIt>(w); e.valid(); ++e) {
200           
201            if( flow.get(e) == 0 ) continue;
202            NodeIt v=G.tail(e); 
203            //e=vw
204           
205            if( lev > level.get(v) ) { 
206              /*Push is allowed now*/
207             
208              if ( excess.get(v)==0 && v != s && v !=t)
209                stack[level.get(v)].push(v);
210              /*v becomes active.*/
211             
212              int flo=flow.get(e);
213             
214              if ( flo >= exc ) {
215                /*A nonsaturating push.*/
216               
217                flow.set(e, flo-exc);
218                excess.set(v, excess.get(v)+exc);
219                exc=0;
220                break;
221              } else {                                               
222                /*A saturating push.*/
223               
224                excess.set(v, excess.get(v)+flo);
225                exc-=flo;
226                flow.set(e,0);
227              } 
228            } else if ( newlevel > level.get(v) ) newlevel = level.get(v);
229           
230          } //for in edges vw
231         
232        } // if w still has excess after the out edge for cycle
233         
234          excess.set(w, exc);
235         
236
237          /*
238            Relabel
239          */
240         
241          if ( exc > 0 ) {
242            //now 'lev' is the old level of w
243            level.set(w,++newlevel);
244           
245            if ( lev < n ) {
246              --numb[lev];
247
248              if ( !numb[lev] && lev < A*n ) {  //If the level of w gets empty.
249               
250                for (EachNodeIt v=G.template first<EachNodeIt>(); v.valid() ; ++v) {
251                  if (level.get(v) > lev && level.get(v) < n ) level.set(v,n); 
252                }
253                for (int i=lev+1 ; i!=n ; ++i) numb[i]=0;
254                if ( newlevel < n ) newlevel=n;
255              } else {
256                if ( newlevel < n ) ++numb[newlevel];
257              }
258            }
259           
260            stack[newlevel].push(w);
261
262          }
263
264        } // if stack[b] is nonempty
265
266      } // while(b)
267
268
269      value = excess.get(t);
270      /*Max flow value.*/
271
272
273    } //void run()
274
275
276
277
278
279    /*
280      Returns the maximum value of a flow.
281     */
282
283    T maxflow() {
284      return value;
285    }
286
287
288
289    /*
290      For the maximum flow x found by the algorithm, it returns the flow value on Edge e, i.e. x(e).
291    */
292
293    T flowonedge(EdgeIt e) {
294      return flow.get(e);
295    }
296
297
298
299    /*
300      Returns the maximum flow x found by the algorithm.
301    */
302
303    FlowMap allflow() {
304      return flow;
305    }
306
307
308
309
310    /*
311      Returns the minimum min cut, by a bfs from s in the residual graph.
312    */
313   
314    template<typename CutMap>
315    void mincut(CutMap& M) {
316   
317      std::queue<NodeIt> queue;
318     
319      M.set(s,true);     
320      queue.push(s);
321
322      while (!queue.empty()) {
323        NodeIt w=queue.front();
324        queue.pop();
325
326        for(OutEdgeIt e=G.template first<OutEdgeIt>(w) ; e.valid(); ++e) {
327          NodeIt v=G.head(e);
328          if (!M.get(v) && flow.get(e) < capacity.get(e) ) {
329            queue.push(v);
330            M.set(v, true);
331          }
332        }
333
334        for(InEdgeIt e=G.template first<InEdgeIt>(w) ; e.valid(); ++e) {
335          NodeIt v=G.tail(e);
336          if (!M.get(v) && flow.get(e) > 0 ) {
337            queue.push(v);
338            M.set(v, true);
339          }
340        }
341
342      }
343
344    }
345
346
347
348    /*
349      Returns the maximum min cut, by a reverse bfs
350      from t in the residual graph.
351    */
352   
353    template<typename CutMap>
354    void max_mincut(CutMap& M) {
355   
356      std::queue<NodeIt> queue;
357     
358      M.set(t,true);       
359      queue.push(t);
360
361      while (!queue.empty()) {
362        NodeIt w=queue.front();
363        queue.pop();
364
365        for(InEdgeIt e=G.template first<InEdgeIt>(w) ; e.valid(); ++e) {
366          NodeIt v=G.tail(e);
367          if (!M.get(v) && flow.get(e) < capacity.get(e) ) {
368            queue.push(v);
369            M.set(v, true);
370          }
371        }
372
373        for(OutEdgeIt e=G.template first<OutEdgeIt>(w) ; e.valid(); ++e) {
374          NodeIt v=G.head(e);
375          if (!M.get(v) && flow.get(e) > 0 ) {
376            queue.push(v);
377            M.set(v, true);
378          }
379        }
380      }
381
382      for(EachNodeIt v=G.template first<EachNodeIt>() ; v.valid(); ++v) {
383        M.set(v, !M.get(v));
384      }
385
386    }
387
388
389
390    template<typename CutMap>
391    void min_mincut(CutMap& M) {
392      mincut(M);
393    }
394
395
396
397  };
398}//namespace marci
399#endif
400
401
402
403
Note: See TracBrowser for help on using the repository browser.