COIN-OR::LEMON - Graph Library

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

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

javitott valtozat

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