COIN-OR::LEMON - Graph Library

source: lemon/lemon/hao_orlin.h @ 643:293551ad254f

Last change on this file since 643:293551ad254f was 643:293551ad254f, checked in by Peter Kovacs <kpeter@…>, 11 years ago

Improvements and fixes for the minimum cut algorithms (#264)

File size: 30.0 KB
Line 
1/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 *
3 * This file is a part of LEMON, a generic C++ optimization library.
4 *
5 * Copyright (C) 2003-2009
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 *
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
12 *
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
15 * purpose.
16 *
17 */
18
19#ifndef LEMON_HAO_ORLIN_H
20#define LEMON_HAO_ORLIN_H
21
22#include <vector>
23#include <list>
24#include <limits>
25
26#include <lemon/maps.h>
27#include <lemon/core.h>
28#include <lemon/tolerance.h>
29
30/// \file
31/// \ingroup min_cut
32/// \brief Implementation of the Hao-Orlin algorithm.
33///
34/// Implementation of the Hao-Orlin algorithm for finding a minimum cut
35/// in a digraph.
36
37namespace lemon {
38
39  /// \ingroup min_cut
40  ///
41  /// \brief Hao-Orlin algorithm for finding a minimum cut in a digraph.
42  ///
43  /// This class implements the Hao-Orlin algorithm for finding a minimum
44  /// value cut in a directed graph \f$D=(V,A)\f$.
45  /// It takes a fixed node \f$ source \in V \f$ and
46  /// consists of two phases: in the first phase it determines a
47  /// minimum cut with \f$ source \f$ on the source-side (i.e. a set
48  /// \f$ X\subsetneq V \f$ with \f$ source \in X \f$ and minimal outgoing
49  /// capacity) and in the second phase it determines a minimum cut
50  /// with \f$ source \f$ on the sink-side (i.e. a set
51  /// \f$ X\subsetneq V \f$ with \f$ source \notin X \f$ and minimal outgoing
52  /// capacity). Obviously, the smaller of these two cuts will be a
53  /// minimum cut of \f$ D \f$. The algorithm is a modified
54  /// preflow push-relabel algorithm. Our implementation calculates
55  /// the minimum cut in \f$ O(n^2\sqrt{m}) \f$ time (we use the
56  /// highest-label rule), or in \f$O(nm)\f$ for unit capacities. The
57  /// purpose of such algorithm is e.g. testing network reliability.
58  ///
59  /// For an undirected graph you can run just the first phase of the
60  /// algorithm or you can use the algorithm of Nagamochi and Ibaraki,
61  /// which solves the undirected problem in \f$ O(nm + n^2 \log n) \f$
62  /// time. It is implemented in the NagamochiIbaraki algorithm class.
63  ///
64  /// \tparam GR The type of the digraph the algorithm runs on.
65  /// \tparam CAP The type of the arc map containing the capacities,
66  /// which can be any numreric type. The default map type is
67  /// \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
68  /// \tparam TOL Tolerance class for handling inexact computations. The
69  /// default tolerance type is \ref Tolerance "Tolerance<CAP::Value>".
70#ifdef DOXYGEN
71  template <typename GR, typename CAP, typename TOL>
72#else
73  template <typename GR,
74            typename CAP = typename GR::template ArcMap<int>,
75            typename TOL = Tolerance<typename CAP::Value> >
76#endif
77  class HaoOrlin {
78  public:
79   
80    /// The digraph type of the algorithm
81    typedef GR Digraph;
82    /// The capacity map type of the algorithm
83    typedef CAP CapacityMap;
84    /// The tolerance type of the algorithm
85    typedef TOL Tolerance;
86
87  private:
88
89    typedef typename CapacityMap::Value Value;
90
91    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
92
93    const Digraph& _graph;
94    const CapacityMap* _capacity;
95
96    typedef typename Digraph::template ArcMap<Value> FlowMap;
97    FlowMap* _flow;
98
99    Node _source;
100
101    int _node_num;
102
103    // Bucketing structure
104    std::vector<Node> _first, _last;
105    typename Digraph::template NodeMap<Node>* _next;
106    typename Digraph::template NodeMap<Node>* _prev;
107    typename Digraph::template NodeMap<bool>* _active;
108    typename Digraph::template NodeMap<int>* _bucket;
109
110    std::vector<bool> _dormant;
111
112    std::list<std::list<int> > _sets;
113    std::list<int>::iterator _highest;
114
115    typedef typename Digraph::template NodeMap<Value> ExcessMap;
116    ExcessMap* _excess;
117
118    typedef typename Digraph::template NodeMap<bool> SourceSetMap;
119    SourceSetMap* _source_set;
120
121    Value _min_cut;
122
123    typedef typename Digraph::template NodeMap<bool> MinCutMap;
124    MinCutMap* _min_cut_map;
125
126    Tolerance _tolerance;
127
128  public:
129
130    /// \brief Constructor
131    ///
132    /// Constructor of the algorithm class.
133    HaoOrlin(const Digraph& graph, const CapacityMap& capacity,
134             const Tolerance& tolerance = Tolerance()) :
135      _graph(graph), _capacity(&capacity), _flow(0), _source(),
136      _node_num(), _first(), _last(), _next(0), _prev(0),
137      _active(0), _bucket(0), _dormant(), _sets(), _highest(),
138      _excess(0), _source_set(0), _min_cut(), _min_cut_map(0),
139      _tolerance(tolerance) {}
140
141    ~HaoOrlin() {
142      if (_min_cut_map) {
143        delete _min_cut_map;
144      }
145      if (_source_set) {
146        delete _source_set;
147      }
148      if (_excess) {
149        delete _excess;
150      }
151      if (_next) {
152        delete _next;
153      }
154      if (_prev) {
155        delete _prev;
156      }
157      if (_active) {
158        delete _active;
159      }
160      if (_bucket) {
161        delete _bucket;
162      }
163      if (_flow) {
164        delete _flow;
165      }
166    }
167
168  private:
169
170    void activate(const Node& i) {
171      (*_active)[i] = true;
172
173      int bucket = (*_bucket)[i];
174
175      if ((*_prev)[i] == INVALID || (*_active)[(*_prev)[i]]) return;
176      //unlace
177      (*_next)[(*_prev)[i]] = (*_next)[i];
178      if ((*_next)[i] != INVALID) {
179        (*_prev)[(*_next)[i]] = (*_prev)[i];
180      } else {
181        _last[bucket] = (*_prev)[i];
182      }
183      //lace
184      (*_next)[i] = _first[bucket];
185      (*_prev)[_first[bucket]] = i;
186      (*_prev)[i] = INVALID;
187      _first[bucket] = i;
188    }
189
190    void deactivate(const Node& i) {
191      (*_active)[i] = false;
192      int bucket = (*_bucket)[i];
193
194      if ((*_next)[i] == INVALID || !(*_active)[(*_next)[i]]) return;
195
196      //unlace
197      (*_prev)[(*_next)[i]] = (*_prev)[i];
198      if ((*_prev)[i] != INVALID) {
199        (*_next)[(*_prev)[i]] = (*_next)[i];
200      } else {
201        _first[bucket] = (*_next)[i];
202      }
203      //lace
204      (*_prev)[i] = _last[bucket];
205      (*_next)[_last[bucket]] = i;
206      (*_next)[i] = INVALID;
207      _last[bucket] = i;
208    }
209
210    void addItem(const Node& i, int bucket) {
211      (*_bucket)[i] = bucket;
212      if (_last[bucket] != INVALID) {
213        (*_prev)[i] = _last[bucket];
214        (*_next)[_last[bucket]] = i;
215        (*_next)[i] = INVALID;
216        _last[bucket] = i;
217      } else {
218        (*_prev)[i] = INVALID;
219        _first[bucket] = i;
220        (*_next)[i] = INVALID;
221        _last[bucket] = i;
222      }
223    }
224
225    void findMinCutOut() {
226
227      for (NodeIt n(_graph); n != INVALID; ++n) {
228        (*_excess)[n] = 0;
229      }
230
231      for (ArcIt a(_graph); a != INVALID; ++a) {
232        (*_flow)[a] = 0;
233      }
234
235      int bucket_num = 0;
236      std::vector<Node> queue(_node_num);
237      int qfirst = 0, qlast = 0, qsep = 0;
238
239      {
240        typename Digraph::template NodeMap<bool> reached(_graph, false);
241
242        reached[_source] = true;
243        bool first_set = true;
244
245        for (NodeIt t(_graph); t != INVALID; ++t) {
246          if (reached[t]) continue;
247          _sets.push_front(std::list<int>());
248
249          queue[qlast++] = t;
250          reached[t] = true;
251
252          while (qfirst != qlast) {
253            if (qsep == qfirst) {
254              ++bucket_num;
255              _sets.front().push_front(bucket_num);
256              _dormant[bucket_num] = !first_set;
257              _first[bucket_num] = _last[bucket_num] = INVALID;
258              qsep = qlast;
259            }
260
261            Node n = queue[qfirst++];
262            addItem(n, bucket_num);
263
264            for (InArcIt a(_graph, n); a != INVALID; ++a) {
265              Node u = _graph.source(a);
266              if (!reached[u] && _tolerance.positive((*_capacity)[a])) {
267                reached[u] = true;
268                queue[qlast++] = u;
269              }
270            }
271          }
272          first_set = false;
273        }
274
275        ++bucket_num;
276        (*_bucket)[_source] = 0;
277        _dormant[0] = true;
278      }
279      (*_source_set)[_source] = true;
280
281      Node target = _last[_sets.back().back()];
282      {
283        for (OutArcIt a(_graph, _source); a != INVALID; ++a) {
284          if (_tolerance.positive((*_capacity)[a])) {
285            Node u = _graph.target(a);
286            (*_flow)[a] = (*_capacity)[a];
287            (*_excess)[u] += (*_capacity)[a];
288            if (!(*_active)[u] && u != _source) {
289              activate(u);
290            }
291          }
292        }
293
294        if ((*_active)[target]) {
295          deactivate(target);
296        }
297
298        _highest = _sets.back().begin();
299        while (_highest != _sets.back().end() &&
300               !(*_active)[_first[*_highest]]) {
301          ++_highest;
302        }
303      }
304
305      while (true) {
306        while (_highest != _sets.back().end()) {
307          Node n = _first[*_highest];
308          Value excess = (*_excess)[n];
309          int next_bucket = _node_num;
310
311          int under_bucket;
312          if (++std::list<int>::iterator(_highest) == _sets.back().end()) {
313            under_bucket = -1;
314          } else {
315            under_bucket = *(++std::list<int>::iterator(_highest));
316          }
317
318          for (OutArcIt a(_graph, n); a != INVALID; ++a) {
319            Node v = _graph.target(a);
320            if (_dormant[(*_bucket)[v]]) continue;
321            Value rem = (*_capacity)[a] - (*_flow)[a];
322            if (!_tolerance.positive(rem)) continue;
323            if ((*_bucket)[v] == under_bucket) {
324              if (!(*_active)[v] && v != target) {
325                activate(v);
326              }
327              if (!_tolerance.less(rem, excess)) {
328                (*_flow)[a] += excess;
329                (*_excess)[v] += excess;
330                excess = 0;
331                goto no_more_push;
332              } else {
333                excess -= rem;
334                (*_excess)[v] += rem;
335                (*_flow)[a] = (*_capacity)[a];
336              }
337            } else if (next_bucket > (*_bucket)[v]) {
338              next_bucket = (*_bucket)[v];
339            }
340          }
341
342          for (InArcIt a(_graph, n); a != INVALID; ++a) {
343            Node v = _graph.source(a);
344            if (_dormant[(*_bucket)[v]]) continue;
345            Value rem = (*_flow)[a];
346            if (!_tolerance.positive(rem)) continue;
347            if ((*_bucket)[v] == under_bucket) {
348              if (!(*_active)[v] && v != target) {
349                activate(v);
350              }
351              if (!_tolerance.less(rem, excess)) {
352                (*_flow)[a] -= excess;
353                (*_excess)[v] += excess;
354                excess = 0;
355                goto no_more_push;
356              } else {
357                excess -= rem;
358                (*_excess)[v] += rem;
359                (*_flow)[a] = 0;
360              }
361            } else if (next_bucket > (*_bucket)[v]) {
362              next_bucket = (*_bucket)[v];
363            }
364          }
365
366        no_more_push:
367
368          (*_excess)[n] = excess;
369
370          if (excess != 0) {
371            if ((*_next)[n] == INVALID) {
372              typename std::list<std::list<int> >::iterator new_set =
373                _sets.insert(--_sets.end(), std::list<int>());
374              new_set->splice(new_set->end(), _sets.back(),
375                              _sets.back().begin(), ++_highest);
376              for (std::list<int>::iterator it = new_set->begin();
377                   it != new_set->end(); ++it) {
378                _dormant[*it] = true;
379              }
380              while (_highest != _sets.back().end() &&
381                     !(*_active)[_first[*_highest]]) {
382                ++_highest;
383              }
384            } else if (next_bucket == _node_num) {
385              _first[(*_bucket)[n]] = (*_next)[n];
386              (*_prev)[(*_next)[n]] = INVALID;
387
388              std::list<std::list<int> >::iterator new_set =
389                _sets.insert(--_sets.end(), std::list<int>());
390
391              new_set->push_front(bucket_num);
392              (*_bucket)[n] = bucket_num;
393              _first[bucket_num] = _last[bucket_num] = n;
394              (*_next)[n] = INVALID;
395              (*_prev)[n] = INVALID;
396              _dormant[bucket_num] = true;
397              ++bucket_num;
398
399              while (_highest != _sets.back().end() &&
400                     !(*_active)[_first[*_highest]]) {
401                ++_highest;
402              }
403            } else {
404              _first[*_highest] = (*_next)[n];
405              (*_prev)[(*_next)[n]] = INVALID;
406
407              while (next_bucket != *_highest) {
408                --_highest;
409              }
410
411              if (_highest == _sets.back().begin()) {
412                _sets.back().push_front(bucket_num);
413                _dormant[bucket_num] = false;
414                _first[bucket_num] = _last[bucket_num] = INVALID;
415                ++bucket_num;
416              }
417              --_highest;
418
419              (*_bucket)[n] = *_highest;
420              (*_next)[n] = _first[*_highest];
421              if (_first[*_highest] != INVALID) {
422                (*_prev)[_first[*_highest]] = n;
423              } else {
424                _last[*_highest] = n;
425              }
426              _first[*_highest] = n;
427            }
428          } else {
429
430            deactivate(n);
431            if (!(*_active)[_first[*_highest]]) {
432              ++_highest;
433              if (_highest != _sets.back().end() &&
434                  !(*_active)[_first[*_highest]]) {
435                _highest = _sets.back().end();
436              }
437            }
438          }
439        }
440
441        if ((*_excess)[target] < _min_cut) {
442          _min_cut = (*_excess)[target];
443          for (NodeIt i(_graph); i != INVALID; ++i) {
444            (*_min_cut_map)[i] = true;
445          }
446          for (std::list<int>::iterator it = _sets.back().begin();
447               it != _sets.back().end(); ++it) {
448            Node n = _first[*it];
449            while (n != INVALID) {
450              (*_min_cut_map)[n] = false;
451              n = (*_next)[n];
452            }
453          }
454        }
455
456        {
457          Node new_target;
458          if ((*_prev)[target] != INVALID || (*_next)[target] != INVALID) {
459            if ((*_next)[target] == INVALID) {
460              _last[(*_bucket)[target]] = (*_prev)[target];
461              new_target = (*_prev)[target];
462            } else {
463              (*_prev)[(*_next)[target]] = (*_prev)[target];
464              new_target = (*_next)[target];
465            }
466            if ((*_prev)[target] == INVALID) {
467              _first[(*_bucket)[target]] = (*_next)[target];
468            } else {
469              (*_next)[(*_prev)[target]] = (*_next)[target];
470            }
471          } else {
472            _sets.back().pop_back();
473            if (_sets.back().empty()) {
474              _sets.pop_back();
475              if (_sets.empty())
476                break;
477              for (std::list<int>::iterator it = _sets.back().begin();
478                   it != _sets.back().end(); ++it) {
479                _dormant[*it] = false;
480              }
481            }
482            new_target = _last[_sets.back().back()];
483          }
484
485          (*_bucket)[target] = 0;
486
487          (*_source_set)[target] = true;
488          for (OutArcIt a(_graph, target); a != INVALID; ++a) {
489            Value rem = (*_capacity)[a] - (*_flow)[a];
490            if (!_tolerance.positive(rem)) continue;
491            Node v = _graph.target(a);
492            if (!(*_active)[v] && !(*_source_set)[v]) {
493              activate(v);
494            }
495            (*_excess)[v] += rem;
496            (*_flow)[a] = (*_capacity)[a];
497          }
498
499          for (InArcIt a(_graph, target); a != INVALID; ++a) {
500            Value rem = (*_flow)[a];
501            if (!_tolerance.positive(rem)) continue;
502            Node v = _graph.source(a);
503            if (!(*_active)[v] && !(*_source_set)[v]) {
504              activate(v);
505            }
506            (*_excess)[v] += rem;
507            (*_flow)[a] = 0;
508          }
509
510          target = new_target;
511          if ((*_active)[target]) {
512            deactivate(target);
513          }
514
515          _highest = _sets.back().begin();
516          while (_highest != _sets.back().end() &&
517                 !(*_active)[_first[*_highest]]) {
518            ++_highest;
519          }
520        }
521      }
522    }
523
524    void findMinCutIn() {
525
526      for (NodeIt n(_graph); n != INVALID; ++n) {
527        (*_excess)[n] = 0;
528      }
529
530      for (ArcIt a(_graph); a != INVALID; ++a) {
531        (*_flow)[a] = 0;
532      }
533
534      int bucket_num = 0;
535      std::vector<Node> queue(_node_num);
536      int qfirst = 0, qlast = 0, qsep = 0;
537
538      {
539        typename Digraph::template NodeMap<bool> reached(_graph, false);
540
541        reached[_source] = true;
542
543        bool first_set = true;
544
545        for (NodeIt t(_graph); t != INVALID; ++t) {
546          if (reached[t]) continue;
547          _sets.push_front(std::list<int>());
548
549          queue[qlast++] = t;
550          reached[t] = true;
551
552          while (qfirst != qlast) {
553            if (qsep == qfirst) {
554              ++bucket_num;
555              _sets.front().push_front(bucket_num);
556              _dormant[bucket_num] = !first_set;
557              _first[bucket_num] = _last[bucket_num] = INVALID;
558              qsep = qlast;
559            }
560
561            Node n = queue[qfirst++];
562            addItem(n, bucket_num);
563
564            for (OutArcIt a(_graph, n); a != INVALID; ++a) {
565              Node u = _graph.target(a);
566              if (!reached[u] && _tolerance.positive((*_capacity)[a])) {
567                reached[u] = true;
568                queue[qlast++] = u;
569              }
570            }
571          }
572          first_set = false;
573        }
574
575        ++bucket_num;
576        (*_bucket)[_source] = 0;
577        _dormant[0] = true;
578      }
579      (*_source_set)[_source] = true;
580
581      Node target = _last[_sets.back().back()];
582      {
583        for (InArcIt a(_graph, _source); a != INVALID; ++a) {
584          if (_tolerance.positive((*_capacity)[a])) {
585            Node u = _graph.source(a);
586            (*_flow)[a] = (*_capacity)[a];
587            (*_excess)[u] += (*_capacity)[a];
588            if (!(*_active)[u] && u != _source) {
589              activate(u);
590            }
591          }
592        }
593        if ((*_active)[target]) {
594          deactivate(target);
595        }
596
597        _highest = _sets.back().begin();
598        while (_highest != _sets.back().end() &&
599               !(*_active)[_first[*_highest]]) {
600          ++_highest;
601        }
602      }
603
604
605      while (true) {
606        while (_highest != _sets.back().end()) {
607          Node n = _first[*_highest];
608          Value excess = (*_excess)[n];
609          int next_bucket = _node_num;
610
611          int under_bucket;
612          if (++std::list<int>::iterator(_highest) == _sets.back().end()) {
613            under_bucket = -1;
614          } else {
615            under_bucket = *(++std::list<int>::iterator(_highest));
616          }
617
618          for (InArcIt a(_graph, n); a != INVALID; ++a) {
619            Node v = _graph.source(a);
620            if (_dormant[(*_bucket)[v]]) continue;
621            Value rem = (*_capacity)[a] - (*_flow)[a];
622            if (!_tolerance.positive(rem)) continue;
623            if ((*_bucket)[v] == under_bucket) {
624              if (!(*_active)[v] && v != target) {
625                activate(v);
626              }
627              if (!_tolerance.less(rem, excess)) {
628                (*_flow)[a] += excess;
629                (*_excess)[v] += excess;
630                excess = 0;
631                goto no_more_push;
632              } else {
633                excess -= rem;
634                (*_excess)[v] += rem;
635                (*_flow)[a] = (*_capacity)[a];
636              }
637            } else if (next_bucket > (*_bucket)[v]) {
638              next_bucket = (*_bucket)[v];
639            }
640          }
641
642          for (OutArcIt a(_graph, n); a != INVALID; ++a) {
643            Node v = _graph.target(a);
644            if (_dormant[(*_bucket)[v]]) continue;
645            Value rem = (*_flow)[a];
646            if (!_tolerance.positive(rem)) continue;
647            if ((*_bucket)[v] == under_bucket) {
648              if (!(*_active)[v] && v != target) {
649                activate(v);
650              }
651              if (!_tolerance.less(rem, excess)) {
652                (*_flow)[a] -= excess;
653                (*_excess)[v] += excess;
654                excess = 0;
655                goto no_more_push;
656              } else {
657                excess -= rem;
658                (*_excess)[v] += rem;
659                (*_flow)[a] = 0;
660              }
661            } else if (next_bucket > (*_bucket)[v]) {
662              next_bucket = (*_bucket)[v];
663            }
664          }
665
666        no_more_push:
667
668          (*_excess)[n] = excess;
669
670          if (excess != 0) {
671            if ((*_next)[n] == INVALID) {
672              typename std::list<std::list<int> >::iterator new_set =
673                _sets.insert(--_sets.end(), std::list<int>());
674              new_set->splice(new_set->end(), _sets.back(),
675                              _sets.back().begin(), ++_highest);
676              for (std::list<int>::iterator it = new_set->begin();
677                   it != new_set->end(); ++it) {
678                _dormant[*it] = true;
679              }
680              while (_highest != _sets.back().end() &&
681                     !(*_active)[_first[*_highest]]) {
682                ++_highest;
683              }
684            } else if (next_bucket == _node_num) {
685              _first[(*_bucket)[n]] = (*_next)[n];
686              (*_prev)[(*_next)[n]] = INVALID;
687
688              std::list<std::list<int> >::iterator new_set =
689                _sets.insert(--_sets.end(), std::list<int>());
690
691              new_set->push_front(bucket_num);
692              (*_bucket)[n] = bucket_num;
693              _first[bucket_num] = _last[bucket_num] = n;
694              (*_next)[n] = INVALID;
695              (*_prev)[n] = INVALID;
696              _dormant[bucket_num] = true;
697              ++bucket_num;
698
699              while (_highest != _sets.back().end() &&
700                     !(*_active)[_first[*_highest]]) {
701                ++_highest;
702              }
703            } else {
704              _first[*_highest] = (*_next)[n];
705              (*_prev)[(*_next)[n]] = INVALID;
706
707              while (next_bucket != *_highest) {
708                --_highest;
709              }
710              if (_highest == _sets.back().begin()) {
711                _sets.back().push_front(bucket_num);
712                _dormant[bucket_num] = false;
713                _first[bucket_num] = _last[bucket_num] = INVALID;
714                ++bucket_num;
715              }
716              --_highest;
717
718              (*_bucket)[n] = *_highest;
719              (*_next)[n] = _first[*_highest];
720              if (_first[*_highest] != INVALID) {
721                (*_prev)[_first[*_highest]] = n;
722              } else {
723                _last[*_highest] = n;
724              }
725              _first[*_highest] = n;
726            }
727          } else {
728
729            deactivate(n);
730            if (!(*_active)[_first[*_highest]]) {
731              ++_highest;
732              if (_highest != _sets.back().end() &&
733                  !(*_active)[_first[*_highest]]) {
734                _highest = _sets.back().end();
735              }
736            }
737          }
738        }
739
740        if ((*_excess)[target] < _min_cut) {
741          _min_cut = (*_excess)[target];
742          for (NodeIt i(_graph); i != INVALID; ++i) {
743            (*_min_cut_map)[i] = false;
744          }
745          for (std::list<int>::iterator it = _sets.back().begin();
746               it != _sets.back().end(); ++it) {
747            Node n = _first[*it];
748            while (n != INVALID) {
749              (*_min_cut_map)[n] = true;
750              n = (*_next)[n];
751            }
752          }
753        }
754
755        {
756          Node new_target;
757          if ((*_prev)[target] != INVALID || (*_next)[target] != INVALID) {
758            if ((*_next)[target] == INVALID) {
759              _last[(*_bucket)[target]] = (*_prev)[target];
760              new_target = (*_prev)[target];
761            } else {
762              (*_prev)[(*_next)[target]] = (*_prev)[target];
763              new_target = (*_next)[target];
764            }
765            if ((*_prev)[target] == INVALID) {
766              _first[(*_bucket)[target]] = (*_next)[target];
767            } else {
768              (*_next)[(*_prev)[target]] = (*_next)[target];
769            }
770          } else {
771            _sets.back().pop_back();
772            if (_sets.back().empty()) {
773              _sets.pop_back();
774              if (_sets.empty())
775                break;
776              for (std::list<int>::iterator it = _sets.back().begin();
777                   it != _sets.back().end(); ++it) {
778                _dormant[*it] = false;
779              }
780            }
781            new_target = _last[_sets.back().back()];
782          }
783
784          (*_bucket)[target] = 0;
785
786          (*_source_set)[target] = true;
787          for (InArcIt a(_graph, target); a != INVALID; ++a) {
788            Value rem = (*_capacity)[a] - (*_flow)[a];
789            if (!_tolerance.positive(rem)) continue;
790            Node v = _graph.source(a);
791            if (!(*_active)[v] && !(*_source_set)[v]) {
792              activate(v);
793            }
794            (*_excess)[v] += rem;
795            (*_flow)[a] = (*_capacity)[a];
796          }
797
798          for (OutArcIt a(_graph, target); a != INVALID; ++a) {
799            Value rem = (*_flow)[a];
800            if (!_tolerance.positive(rem)) continue;
801            Node v = _graph.target(a);
802            if (!(*_active)[v] && !(*_source_set)[v]) {
803              activate(v);
804            }
805            (*_excess)[v] += rem;
806            (*_flow)[a] = 0;
807          }
808
809          target = new_target;
810          if ((*_active)[target]) {
811            deactivate(target);
812          }
813
814          _highest = _sets.back().begin();
815          while (_highest != _sets.back().end() &&
816                 !(*_active)[_first[*_highest]]) {
817            ++_highest;
818          }
819        }
820      }
821    }
822
823  public:
824
825    /// \name Execution Control
826    /// The simplest way to execute the algorithm is to use
827    /// one of the member functions called \ref run().
828    /// \n
829    /// If you need better control on the execution,
830    /// you have to call one of the \ref init() functions first, then
831    /// \ref calculateOut() and/or \ref calculateIn().
832
833    /// @{
834
835    /// \brief Initialize the internal data structures.
836    ///
837    /// This function initializes the internal data structures. It creates
838    /// the maps and some bucket structures for the algorithm.
839    /// The first node is used as the source node for the push-relabel
840    /// algorithm.
841    void init() {
842      init(NodeIt(_graph));
843    }
844
845    /// \brief Initialize the internal data structures.
846    ///
847    /// This function initializes the internal data structures. It creates
848    /// the maps and some bucket structures for the algorithm.
849    /// The given node is used as the source node for the push-relabel
850    /// algorithm.
851    void init(const Node& source) {
852      _source = source;
853
854      _node_num = countNodes(_graph);
855
856      _first.resize(_node_num);
857      _last.resize(_node_num);
858
859      _dormant.resize(_node_num);
860
861      if (!_flow) {
862        _flow = new FlowMap(_graph);
863      }
864      if (!_next) {
865        _next = new typename Digraph::template NodeMap<Node>(_graph);
866      }
867      if (!_prev) {
868        _prev = new typename Digraph::template NodeMap<Node>(_graph);
869      }
870      if (!_active) {
871        _active = new typename Digraph::template NodeMap<bool>(_graph);
872      }
873      if (!_bucket) {
874        _bucket = new typename Digraph::template NodeMap<int>(_graph);
875      }
876      if (!_excess) {
877        _excess = new ExcessMap(_graph);
878      }
879      if (!_source_set) {
880        _source_set = new SourceSetMap(_graph);
881      }
882      if (!_min_cut_map) {
883        _min_cut_map = new MinCutMap(_graph);
884      }
885
886      _min_cut = std::numeric_limits<Value>::max();
887    }
888
889
890    /// \brief Calculate a minimum cut with \f$ source \f$ on the
891    /// source-side.
892    ///
893    /// This function calculates a minimum cut with \f$ source \f$ on the
894    /// source-side (i.e. a set \f$ X\subsetneq V \f$ with
895    /// \f$ source \in X \f$ and minimal outgoing capacity).
896    ///
897    /// \pre \ref init() must be called before using this function.
898    void calculateOut() {
899      findMinCutOut();
900    }
901
902    /// \brief Calculate a minimum cut with \f$ source \f$ on the
903    /// sink-side.
904    ///
905    /// This function calculates a minimum cut with \f$ source \f$ on the
906    /// sink-side (i.e. a set \f$ X\subsetneq V \f$ with
907    /// \f$ source \notin X \f$ and minimal outgoing capacity).
908    ///
909    /// \pre \ref init() must be called before using this function.
910    void calculateIn() {
911      findMinCutIn();
912    }
913
914
915    /// \brief Run the algorithm.
916    ///
917    /// This function runs the algorithm. It finds nodes \c source and
918    /// \c target arbitrarily and then calls \ref init(), \ref calculateOut()
919    /// and \ref calculateIn().
920    void run() {
921      init();
922      calculateOut();
923      calculateIn();
924    }
925
926    /// \brief Run the algorithm.
927    ///
928    /// This function runs the algorithm. It uses the given \c source node,
929    /// finds a proper \c target node and then calls the \ref init(),
930    /// \ref calculateOut() and \ref calculateIn().
931    void run(const Node& s) {
932      init(s);
933      calculateOut();
934      calculateIn();
935    }
936
937    /// @}
938
939    /// \name Query Functions
940    /// The result of the %HaoOrlin algorithm
941    /// can be obtained using these functions.\n
942    /// \ref run(), \ref calculateOut() or \ref calculateIn()
943    /// should be called before using them.
944
945    /// @{
946
947    /// \brief Return the value of the minimum cut.
948    ///
949    /// This function returns the value of the minimum cut.
950    ///
951    /// \pre \ref run(), \ref calculateOut() or \ref calculateIn()
952    /// must be called before using this function.
953    Value minCutValue() const {
954      return _min_cut;
955    }
956
957
958    /// \brief Return a minimum cut.
959    ///
960    /// This function sets \c cutMap to the characteristic vector of a
961    /// minimum value cut: it will give a non-empty set \f$ X\subsetneq V \f$
962    /// with minimal outgoing capacity (i.e. \c cutMap will be \c true exactly
963    /// for the nodes of \f$ X \f$).
964    ///
965    /// \param cutMap A \ref concepts::WriteMap "writable" node map with
966    /// \c bool (or convertible) value type.
967    ///
968    /// \return The value of the minimum cut.
969    ///
970    /// \pre \ref run(), \ref calculateOut() or \ref calculateIn()
971    /// must be called before using this function.
972    template <typename CutMap>
973    Value minCutMap(CutMap& cutMap) const {
974      for (NodeIt it(_graph); it != INVALID; ++it) {
975        cutMap.set(it, (*_min_cut_map)[it]);
976      }
977      return _min_cut;
978    }
979
980    /// @}
981
982  }; //class HaoOrlin
983
984} //namespace lemon
985
986#endif //LEMON_HAO_ORLIN_H
Note: See TracBrowser for help on using the repository browser.