lemon/hao_orlin.h
author athos
Mon, 02 Oct 2006 14:41:53 +0000
changeset 2228 f71b0f9a7c3a
parent 2225 bb3d5e6f9fcb
child 2273 507232469f5e
permissions -rw-r--r--
Improved documentation.
deba@2211
     1
/* -*- C++ -*-
deba@2211
     2
 *
deba@2225
     3
 * This file is a part of LEMON, a generic C++ optimization library
deba@2225
     4
 *
deba@2225
     5
 * Copyright (C) 2003-2006
deba@2225
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@2211
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@2211
     8
 *
deba@2211
     9
 * Permission to use, modify and distribute this software is granted
deba@2211
    10
 * provided that this copyright notice appears in all copies. For
deba@2211
    11
 * precise terms see the accompanying LICENSE file.
deba@2211
    12
 *
deba@2211
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@2211
    14
 * express or implied, and with no claim as to its suitability for any
deba@2211
    15
 * purpose.
deba@2211
    16
 *
deba@2211
    17
 */
deba@2211
    18
deba@2211
    19
#ifndef LEMON_HAO_ORLIN_H
deba@2211
    20
#define LEMON_HAO_ORLIN_H
deba@2211
    21
deba@2211
    22
#include <vector>
deba@2211
    23
#include <queue>
deba@2211
    24
#include <limits>
deba@2211
    25
deba@2211
    26
#include <lemon/maps.h>
deba@2211
    27
#include <lemon/graph_utils.h>
deba@2211
    28
#include <lemon/graph_adaptor.h>
deba@2211
    29
#include <lemon/iterable_maps.h>
deba@2211
    30
 
deba@2211
    31
deba@2211
    32
/// \file
deba@2211
    33
/// \ingroup flowalgs
deba@2225
    34
/// \brief Implementation of the Hao-Orlin algorithm.
deba@2225
    35
///
deba@2225
    36
/// Implementation of the HaoOrlin algorithms class for testing network 
deba@2211
    37
/// reliability.
deba@2211
    38
deba@2211
    39
namespace lemon {
deba@2211
    40
deba@2225
    41
  /// \ingroup flowalgs
deba@2225
    42
  ///
athos@2228
    43
  /// \brief %Hao-Orlin algorithm to find a minimum cut in directed graphs.
deba@2211
    44
  ///
athos@2228
    45
  /// Hao-Orlin calculates a minimum cut in a directed graph \f$
athos@2228
    46
  /// D=(V,A) \f$. It takes a fixed node \f$ source \in V \f$ and consists
athos@2228
    47
  /// of two phases: in the first phase it determines a minimum cut
athos@2228
    48
  /// with \f$ source \f$ on the source-side (i.e. a set \f$ X\subsetneq V
athos@2228
    49
  /// \f$ with \f$ source \in X \f$ and minimal out-degree) and in the
athos@2228
    50
  /// second phase it determines a minimum cut with \f$ source \f$ on the
athos@2228
    51
  /// sink-side (i.e. a set \f$ X\subsetneq V \f$ with \f$ source \notin X \f$
athos@2228
    52
  /// and minimal out-degree). Obviously, the smaller of these two
athos@2228
    53
  /// cuts will be a minimum cut of \f$ D \f$. The algorithm is a
athos@2228
    54
  /// modified push-relabel preflow algorithm and our implementation
athos@2228
    55
  /// calculates the minimum cut in \f$ O(n^3) \f$ time (we use the
athos@2228
    56
  /// highest-label rule). The purpose of such an algorithm is testing
athos@2228
    57
  /// network reliability. For an undirected graph with \f$ n \f$
athos@2228
    58
  /// nodes and \f$ e \f$ edges you can use the algorithm of Nagamochi
athos@2228
    59
  /// and Ibaraki which solves the undirected problem in \f$ O(ne +
athos@2228
    60
  /// n^2 \log(n)) \f$ time: it is implemented in the MinCut algorithm
athos@2228
    61
  /// class.
deba@2225
    62
  ///
deba@2225
    63
  /// \param _Graph is the graph type of the algorithm.
deba@2225
    64
  /// \param _CapacityMap is an edge map of capacities which should
deba@2225
    65
  /// be any numreric type. The default type is _Graph::EdgeMap<int>.
deba@2225
    66
  /// \param _Tolerance is the handler of the inexact computation. The
athos@2228
    67
  /// default type for this is Tolerance<typename CapacityMap::Value>.
deba@2211
    68
  ///
deba@2211
    69
  /// \author Attila Bernath and Balazs Dezso
deba@2225
    70
#ifdef DOXYGEN
deba@2225
    71
  template <typename _Graph, typename _CapacityMap, typename _Tolerance>
deba@2225
    72
#else
deba@2211
    73
  template <typename _Graph,
deba@2211
    74
	    typename _CapacityMap = typename _Graph::template EdgeMap<int>,
deba@2211
    75
            typename _Tolerance = Tolerance<typename _CapacityMap::Value> >
deba@2225
    76
#endif
deba@2211
    77
  class HaoOrlin {
deba@2211
    78
  protected:
deba@2211
    79
deba@2211
    80
    typedef _Graph Graph;
deba@2211
    81
    typedef _CapacityMap CapacityMap;
deba@2211
    82
    typedef _Tolerance Tolerance;
deba@2211
    83
deba@2211
    84
    typedef typename CapacityMap::Value Value;
deba@2211
    85
deba@2211
    86
    
deba@2211
    87
    typedef typename Graph::Node Node;
deba@2211
    88
    typedef typename Graph::NodeIt NodeIt;
deba@2211
    89
    typedef typename Graph::EdgeIt EdgeIt;
deba@2211
    90
    typedef typename Graph::OutEdgeIt OutEdgeIt;
deba@2211
    91
    typedef typename Graph::InEdgeIt InEdgeIt;
deba@2211
    92
deba@2211
    93
    const Graph* _graph;
deba@2225
    94
deba@2211
    95
    const CapacityMap* _capacity;
deba@2211
    96
deba@2211
    97
    typedef typename Graph::template EdgeMap<Value> FlowMap;
deba@2211
    98
deba@2211
    99
    FlowMap* _preflow;
deba@2211
   100
deba@2211
   101
    Node _source, _target;
deba@2211
   102
    int _node_num;
deba@2211
   103
deba@2211
   104
    typedef ResGraphAdaptor<const Graph, Value, CapacityMap, 
deba@2225
   105
                            FlowMap, Tolerance> OutResGraph;
deba@2225
   106
    typedef typename OutResGraph::Edge OutResEdge;
deba@2225
   107
    
deba@2225
   108
    OutResGraph* _out_res_graph;
deba@2211
   109
deba@2225
   110
    typedef typename Graph::template NodeMap<OutResEdge> OutCurrentEdgeMap;
deba@2225
   111
    OutCurrentEdgeMap* _out_current_edge;  
deba@2211
   112
deba@2225
   113
    typedef RevGraphAdaptor<const Graph> RevGraph;
deba@2225
   114
    RevGraph* _rev_graph;
deba@2225
   115
deba@2225
   116
    typedef ResGraphAdaptor<const RevGraph, Value, CapacityMap, 
deba@2225
   117
                            FlowMap, Tolerance> InResGraph;
deba@2225
   118
    typedef typename InResGraph::Edge InResEdge;
deba@2225
   119
    
deba@2225
   120
    InResGraph* _in_res_graph;
deba@2225
   121
deba@2225
   122
    typedef typename Graph::template NodeMap<InResEdge> InCurrentEdgeMap;
deba@2225
   123
    InCurrentEdgeMap* _in_current_edge;  
deba@2211
   124
deba@2211
   125
deba@2211
   126
    typedef IterableBoolMap<Graph, Node> WakeMap;
deba@2211
   127
    WakeMap* _wake;
deba@2211
   128
deba@2211
   129
    typedef typename Graph::template NodeMap<int> DistMap;
deba@2211
   130
    DistMap* _dist;  
deba@2211
   131
    
deba@2211
   132
    typedef typename Graph::template NodeMap<Value> ExcessMap;
deba@2211
   133
    ExcessMap* _excess;
deba@2211
   134
deba@2211
   135
    typedef typename Graph::template NodeMap<bool> SourceSetMap;
deba@2211
   136
    SourceSetMap* _source_set;
deba@2211
   137
deba@2211
   138
    std::vector<int> _level_size;
deba@2211
   139
deba@2211
   140
    int _highest_active;
deba@2211
   141
    std::vector<std::list<Node> > _active_nodes;
deba@2211
   142
deba@2211
   143
    int _dormant_max;
deba@2211
   144
    std::vector<std::list<Node> > _dormant;
deba@2211
   145
deba@2211
   146
deba@2211
   147
    Value _min_cut;
deba@2211
   148
deba@2211
   149
    typedef typename Graph::template NodeMap<bool> MinCutMap;
deba@2211
   150
    MinCutMap* _min_cut_map;
deba@2211
   151
deba@2211
   152
    Tolerance _tolerance;
deba@2211
   153
deba@2211
   154
  public: 
deba@2211
   155
deba@2225
   156
    /// \brief Constructor
deba@2225
   157
    ///
deba@2225
   158
    /// Constructor of the algorithm class. 
deba@2211
   159
    HaoOrlin(const Graph& graph, const CapacityMap& capacity, 
deba@2211
   160
             const Tolerance& tolerance = Tolerance()) :
deba@2211
   161
      _graph(&graph), _capacity(&capacity), 
deba@2225
   162
      _preflow(0), _source(), _target(), 
deba@2225
   163
      _out_res_graph(0), _out_current_edge(0),
deba@2225
   164
      _rev_graph(0), _in_res_graph(0), _in_current_edge(0),
deba@2211
   165
      _wake(0),_dist(0), _excess(0), _source_set(0), 
deba@2211
   166
      _highest_active(), _active_nodes(), _dormant_max(), _dormant(), 
deba@2211
   167
      _min_cut(), _min_cut_map(0), _tolerance(tolerance) {}
deba@2211
   168
deba@2211
   169
    ~HaoOrlin() {
deba@2211
   170
      if (_min_cut_map) {
deba@2211
   171
        delete _min_cut_map;
deba@2211
   172
      } 
deba@2225
   173
      if (_in_current_edge) {
deba@2225
   174
        delete _in_current_edge;
deba@2225
   175
      }
deba@2225
   176
      if (_in_res_graph) {
deba@2225
   177
        delete _in_res_graph;
deba@2225
   178
      }
deba@2225
   179
      if (_rev_graph) {
deba@2225
   180
        delete _rev_graph;
deba@2225
   181
      }
deba@2225
   182
      if (_out_current_edge) {
deba@2225
   183
        delete _out_current_edge;
deba@2225
   184
      }
deba@2225
   185
      if (_out_res_graph) {
deba@2225
   186
        delete _out_res_graph;
deba@2211
   187
      }
deba@2211
   188
      if (_source_set) {
deba@2211
   189
        delete _source_set;
deba@2211
   190
      }
deba@2211
   191
      if (_excess) {
deba@2211
   192
        delete _excess;
deba@2211
   193
      }
deba@2211
   194
      if (_dist) {
deba@2211
   195
        delete _dist;
deba@2211
   196
      }
deba@2211
   197
      if (_wake) {
deba@2211
   198
        delete _wake;
deba@2211
   199
      }
deba@2211
   200
      if (_preflow) {
deba@2211
   201
        delete _preflow;
deba@2211
   202
      }
deba@2211
   203
    }
deba@2211
   204
    
deba@2211
   205
  private:
deba@2211
   206
    
deba@2225
   207
    template <typename ResGraph, typename EdgeMap>
deba@2225
   208
    void findMinCut(const Node& target, bool out, 
deba@2225
   209
                    ResGraph& res_graph, EdgeMap& current_edge) {
deba@2225
   210
      typedef typename ResGraph::Edge ResEdge;
deba@2225
   211
      typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
deba@2225
   212
deba@2225
   213
      for (typename Graph::EdgeIt it(*_graph); it != INVALID; ++it) {
deba@2225
   214
        (*_preflow)[it] = 0;      
deba@2225
   215
      }
deba@2225
   216
      for (NodeIt it(*_graph); it != INVALID; ++it) {
deba@2225
   217
        (*_wake)[it] = true;
deba@2225
   218
        (*_dist)[it] = 1;
deba@2225
   219
        (*_excess)[it] = 0;
deba@2225
   220
        (*_source_set)[it] = false;
deba@2225
   221
deba@2225
   222
        res_graph.firstOut(current_edge[it], it);
deba@2225
   223
      }
deba@2225
   224
deba@2225
   225
      _target = target;
deba@2225
   226
      (*_dist)[target] = 0;
deba@2225
   227
deba@2225
   228
      for (ResOutEdgeIt it(res_graph, _source); it != INVALID; ++it) {
deba@2225
   229
        Value delta = res_graph.rescap(it);
deba@2225
   230
        if (!_tolerance.positive(delta)) continue;
deba@2225
   231
        
deba@2225
   232
        (*_excess)[res_graph.source(it)] -= delta;
deba@2225
   233
        res_graph.augment(it, delta);
deba@2225
   234
        Node a = res_graph.target(it);
deba@2225
   235
        if (!_tolerance.positive((*_excess)[a]) && 
deba@2225
   236
            (*_wake)[a] && a != _target) {
deba@2225
   237
          _active_nodes[(*_dist)[a]].push_front(a);
deba@2225
   238
          if (_highest_active < (*_dist)[a]) {
deba@2225
   239
            _highest_active = (*_dist)[a];
deba@2225
   240
          }
deba@2225
   241
        }
deba@2225
   242
        (*_excess)[a] += delta;
deba@2225
   243
      }
deba@2225
   244
deba@2225
   245
      _dormant[0].push_front(_source);
deba@2225
   246
      (*_source_set)[_source] = true;
deba@2225
   247
      _dormant_max = 0;
deba@2225
   248
      (*_wake)[_source] = false;
deba@2225
   249
deba@2225
   250
      _level_size[0] = 1;
deba@2225
   251
      _level_size[1] = _node_num - 1;
deba@2225
   252
deba@2225
   253
      do {
deba@2225
   254
	Node n;
deba@2225
   255
	while ((n = findActiveNode()) != INVALID) {
deba@2225
   256
	  ResEdge e;
deba@2225
   257
	  while (_tolerance.positive((*_excess)[n]) && 
deba@2225
   258
                 (e = findAdmissibleEdge(n, res_graph, current_edge)) 
deba@2225
   259
                 != INVALID){
deba@2225
   260
	    Value delta;
deba@2225
   261
	    if ((*_excess)[n] < res_graph.rescap(e)) {
deba@2225
   262
	      delta = (*_excess)[n];
deba@2225
   263
	    } else {
deba@2225
   264
	      delta = res_graph.rescap(e);
deba@2225
   265
	      res_graph.nextOut(current_edge[n]);
deba@2225
   266
	    }
deba@2225
   267
            if (!_tolerance.positive(delta)) continue;
deba@2225
   268
	    res_graph.augment(e, delta);
deba@2225
   269
	    (*_excess)[res_graph.source(e)] -= delta;
deba@2225
   270
	    Node a = res_graph.target(e);
deba@2225
   271
	    if (!_tolerance.positive((*_excess)[a]) && a != _target) {
deba@2225
   272
	      _active_nodes[(*_dist)[a]].push_front(a);
deba@2225
   273
	    }
deba@2225
   274
	    (*_excess)[a] += delta;
deba@2225
   275
	  }
deba@2225
   276
	  if (_tolerance.positive((*_excess)[n])) {
deba@2225
   277
	    relabel(n, res_graph, current_edge);
deba@2225
   278
          }
deba@2225
   279
	}
deba@2225
   280
deba@2225
   281
	Value current_value = cutValue(out);
deba@2225
   282
 	if (_min_cut > current_value){
deba@2225
   283
          if (out) {
deba@2225
   284
            for (NodeIt it(*_graph); it != INVALID; ++it) {
deba@2225
   285
              _min_cut_map->set(it, !(*_wake)[it]);
deba@2225
   286
            } 
deba@2225
   287
          } else {
deba@2225
   288
            for (NodeIt it(*_graph); it != INVALID; ++it) {
deba@2225
   289
              _min_cut_map->set(it, (*_wake)[it]);
deba@2225
   290
            } 
deba@2225
   291
          }
deba@2225
   292
deba@2225
   293
	  _min_cut = current_value;
deba@2225
   294
 	}
deba@2225
   295
deba@2225
   296
      } while (selectNewSink(res_graph));
deba@2225
   297
    }
deba@2225
   298
deba@2225
   299
    template <typename ResGraph, typename EdgeMap>
deba@2225
   300
    void relabel(const Node& n, ResGraph& res_graph, EdgeMap& current_edge) {
deba@2225
   301
      typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
deba@2225
   302
deba@2225
   303
      int k = (*_dist)[n];
deba@2211
   304
      if (_level_size[k] == 1) {
deba@2211
   305
	++_dormant_max;
deba@2211
   306
	for (NodeIt it(*_graph); it != INVALID; ++it) {
deba@2211
   307
	  if ((*_wake)[it] && (*_dist)[it] >= k) {
deba@2211
   308
	    (*_wake)[it] = false;
deba@2211
   309
	    _dormant[_dormant_max].push_front(it);
deba@2211
   310
	    --_level_size[(*_dist)[it]];
deba@2211
   311
	  }
deba@2211
   312
	}
deba@2211
   313
	--_highest_active;
deba@2225
   314
      } else {	
deba@2225
   315
        int new_dist = _node_num;
deba@2225
   316
        for (ResOutEdgeIt e(res_graph, n); e != INVALID; ++e) {
deba@2225
   317
          Node t = res_graph.target(e);
deba@2225
   318
          if ((*_wake)[t] && new_dist > (*_dist)[t]) {
deba@2225
   319
            new_dist = (*_dist)[t];
deba@2225
   320
          }
deba@2225
   321
        }
deba@2225
   322
        if (new_dist == _node_num) {
deba@2211
   323
	  ++_dormant_max;
deba@2225
   324
	  (*_wake)[n] = false;
deba@2225
   325
	  _dormant[_dormant_max].push_front(n);
deba@2225
   326
	  --_level_size[(*_dist)[n]];
deba@2225
   327
	} else {	    
deba@2225
   328
	  --_level_size[(*_dist)[n]];
deba@2225
   329
	  (*_dist)[n] = new_dist + 1;
deba@2225
   330
	  _highest_active = (*_dist)[n];
deba@2225
   331
	  _active_nodes[_highest_active].push_front(n);
deba@2225
   332
	  ++_level_size[(*_dist)[n]];
deba@2225
   333
	  res_graph.firstOut(current_edge[n], n);
deba@2211
   334
	}
deba@2211
   335
      }
deba@2211
   336
    }
deba@2211
   337
deba@2225
   338
    template <typename ResGraph>
deba@2225
   339
    bool selectNewSink(ResGraph& res_graph) {
deba@2225
   340
      typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
deba@2225
   341
deba@2211
   342
      Node old_target = _target;
deba@2211
   343
      (*_wake)[_target] = false;
deba@2211
   344
      --_level_size[(*_dist)[_target]];
deba@2211
   345
      _dormant[0].push_front(_target);
deba@2211
   346
      (*_source_set)[_target] = true;
deba@2211
   347
      if ((int)_dormant[0].size() == _node_num){
deba@2211
   348
        _dormant[0].clear();
deba@2211
   349
	return false;
deba@2211
   350
      }
deba@2211
   351
deba@2211
   352
      bool wake_was_empty = false;
deba@2211
   353
deba@2211
   354
      if(_wake->trueNum() == 0) {
deba@2211
   355
	while (!_dormant[_dormant_max].empty()){
deba@2211
   356
	  (*_wake)[_dormant[_dormant_max].front()] = true;
deba@2211
   357
	  ++_level_size[(*_dist)[_dormant[_dormant_max].front()]];
deba@2211
   358
	  _dormant[_dormant_max].pop_front();
deba@2211
   359
	}
deba@2211
   360
	--_dormant_max;
deba@2211
   361
	wake_was_empty = true;
deba@2211
   362
      }
deba@2211
   363
deba@2211
   364
      int min_dist = std::numeric_limits<int>::max();
deba@2211
   365
      for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
deba@2211
   366
	if (min_dist > (*_dist)[it]){
deba@2211
   367
	  _target = it;
deba@2211
   368
	  min_dist = (*_dist)[it];
deba@2211
   369
	}
deba@2211
   370
      }
deba@2211
   371
deba@2211
   372
      if (wake_was_empty){
deba@2211
   373
	for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
deba@2211
   374
          if (_tolerance.positive((*_excess)[it])) {
deba@2211
   375
	    if ((*_wake)[it] && it != _target) {
deba@2211
   376
	      _active_nodes[(*_dist)[it]].push_front(it);
deba@2211
   377
            }
deba@2211
   378
	    if (_highest_active < (*_dist)[it]) {
deba@2211
   379
	      _highest_active = (*_dist)[it];		    
deba@2211
   380
            }
deba@2211
   381
	  }
deba@2211
   382
	}
deba@2211
   383
      }
deba@2211
   384
deba@2225
   385
      for (ResOutEdgeIt e(res_graph, old_target); e!=INVALID; ++e){
deba@2225
   386
	if (!(*_source_set)[res_graph.target(e)]) {
deba@2225
   387
          Value delta = res_graph.rescap(e);
deba@2225
   388
          if (!_tolerance.positive(delta)) continue;
deba@2225
   389
          res_graph.augment(e, delta);
deba@2225
   390
          (*_excess)[res_graph.source(e)] -= delta;
deba@2225
   391
          Node a = res_graph.target(e);
deba@2225
   392
          if (!_tolerance.positive((*_excess)[a]) && 
deba@2225
   393
              (*_wake)[a] && a != _target) {
deba@2225
   394
            _active_nodes[(*_dist)[a]].push_front(a);
deba@2225
   395
            if (_highest_active < (*_dist)[a]) {
deba@2225
   396
              _highest_active = (*_dist)[a];
deba@2225
   397
            }
deba@2225
   398
          }
deba@2225
   399
          (*_excess)[a] += delta;
deba@2211
   400
	}
deba@2211
   401
      }
deba@2211
   402
      
deba@2211
   403
      return true;
deba@2211
   404
    }
deba@2211
   405
    
deba@2211
   406
    Node findActiveNode() {
deba@2211
   407
      while (_highest_active > 0 && _active_nodes[_highest_active].empty()){ 
deba@2211
   408
	--_highest_active;
deba@2211
   409
      }
deba@2211
   410
      if( _highest_active > 0) {
deba@2211
   411
       	Node n = _active_nodes[_highest_active].front();
deba@2211
   412
	_active_nodes[_highest_active].pop_front();
deba@2211
   413
	return n;
deba@2211
   414
      } else {
deba@2211
   415
	return INVALID;
deba@2211
   416
      }
deba@2211
   417
    }
deba@2211
   418
deba@2225
   419
    template <typename ResGraph, typename EdgeMap>
deba@2225
   420
    typename ResGraph::Edge findAdmissibleEdge(const Node& n, 
deba@2225
   421
                                               ResGraph& res_graph, 
deba@2225
   422
                                               EdgeMap& current_edge) {
deba@2225
   423
      typedef typename ResGraph::Edge ResEdge;
deba@2225
   424
      ResEdge e = current_edge[n];
deba@2211
   425
      while (e != INVALID && 
deba@2225
   426
             ((*_dist)[n] <= (*_dist)[res_graph.target(e)] || 
deba@2225
   427
              !(*_wake)[res_graph.target(e)])) {
deba@2225
   428
	res_graph.nextOut(e);
deba@2211
   429
      }
deba@2211
   430
      if (e != INVALID) {
deba@2225
   431
	current_edge[n] = e;	
deba@2211
   432
	return e;
deba@2211
   433
      } else {
deba@2211
   434
	return INVALID;
deba@2211
   435
      }
deba@2211
   436
    }
deba@2211
   437
deba@2225
   438
    Value cutValue(bool out) {
deba@2225
   439
      Value value = 0;
deba@2225
   440
      if (out) {
deba@2225
   441
        for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
deba@2225
   442
          for (InEdgeIt e(*_graph, it); e != INVALID; ++e) {
deba@2225
   443
            if (!(*_wake)[_graph->source(e)]){
deba@2225
   444
              value += (*_capacity)[e];
deba@2225
   445
            }	
deba@2225
   446
          }
deba@2225
   447
        }
deba@2225
   448
      } else {
deba@2225
   449
        for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
deba@2225
   450
          for (OutEdgeIt e(*_graph, it); e != INVALID; ++e) {
deba@2225
   451
            if (!(*_wake)[_graph->target(e)]){
deba@2225
   452
              value += (*_capacity)[e];
deba@2225
   453
            }	
deba@2225
   454
          }
deba@2211
   455
        }
deba@2211
   456
      }
deba@2225
   457
      return value;
deba@2211
   458
    }
deba@2225
   459
deba@2211
   460
deba@2211
   461
  public:
deba@2211
   462
deba@2225
   463
    /// \name Execution control
deba@2225
   464
    /// The simplest way to execute the algorithm is to use
deba@2225
   465
    /// one of the member functions called \c run(...).
deba@2225
   466
    /// \n
deba@2225
   467
    /// If you need more control on the execution,
deba@2225
   468
    /// first you must call \ref init(), then the \ref calculateIn() or
deba@2225
   469
    /// \ref calculateIn() functions.
deba@2225
   470
deba@2225
   471
    /// @{
deba@2225
   472
deba@2211
   473
    /// \brief Initializes the internal data structures.
deba@2211
   474
    ///
deba@2211
   475
    /// Initializes the internal data structures. It creates
deba@2225
   476
    /// the maps, residual graph adaptors and some bucket structures
deba@2211
   477
    /// for the algorithm. 
deba@2211
   478
    void init() {
deba@2211
   479
      init(NodeIt(*_graph));
deba@2211
   480
    }
deba@2211
   481
deba@2211
   482
    /// \brief Initializes the internal data structures.
deba@2211
   483
    ///
deba@2211
   484
    /// Initializes the internal data structures. It creates
deba@2211
   485
    /// the maps, residual graph adaptor and some bucket structures
athos@2228
   486
    /// for the algorithm. Node \c source  is used as the push-relabel
deba@2211
   487
    /// algorithm's source.
deba@2211
   488
    void init(const Node& source) {
deba@2211
   489
      _source = source;
deba@2211
   490
      _node_num = countNodes(*_graph);
deba@2211
   491
deba@2211
   492
      _dormant.resize(_node_num);
deba@2211
   493
      _level_size.resize(_node_num, 0);
deba@2211
   494
      _active_nodes.resize(_node_num);
deba@2211
   495
deba@2211
   496
      if (!_preflow) {
deba@2211
   497
        _preflow = new FlowMap(*_graph);
deba@2211
   498
      }
deba@2211
   499
      if (!_wake) {
deba@2211
   500
        _wake = new WakeMap(*_graph);
deba@2211
   501
      }
deba@2211
   502
      if (!_dist) {
deba@2211
   503
        _dist = new DistMap(*_graph);
deba@2211
   504
      }
deba@2211
   505
      if (!_excess) {
deba@2211
   506
        _excess = new ExcessMap(*_graph);
deba@2211
   507
      }
deba@2211
   508
      if (!_source_set) {
deba@2211
   509
        _source_set = new SourceSetMap(*_graph);
deba@2211
   510
      }
deba@2225
   511
      if (!_out_res_graph) {
deba@2225
   512
        _out_res_graph = new OutResGraph(*_graph, *_capacity, *_preflow);
deba@2225
   513
      }
deba@2225
   514
      if (!_out_current_edge) {
deba@2225
   515
        _out_current_edge = new OutCurrentEdgeMap(*_graph);
deba@2225
   516
      }
deba@2225
   517
      if (!_rev_graph) {
deba@2225
   518
        _rev_graph = new RevGraph(*_graph);
deba@2225
   519
      }
deba@2225
   520
      if (!_in_res_graph) {
deba@2225
   521
        _in_res_graph = new InResGraph(*_rev_graph, *_capacity, *_preflow);
deba@2225
   522
      }
deba@2225
   523
      if (!_in_current_edge) {
deba@2225
   524
        _in_current_edge = new InCurrentEdgeMap(*_graph);
deba@2211
   525
      }
deba@2211
   526
      if (!_min_cut_map) {
deba@2211
   527
        _min_cut_map = new MinCutMap(*_graph);
deba@2211
   528
      }
deba@2211
   529
deba@2211
   530
      _min_cut = std::numeric_limits<Value>::max();
deba@2211
   531
    }
deba@2211
   532
deba@2211
   533
athos@2228
   534
    /// \brief Calculates a minimum cut with \f$ source \f$ on the
athos@2228
   535
    /// source-side.
deba@2211
   536
    ///
athos@2228
   537
    /// \brief Calculates a minimum cut with \f$ source \f$ on the
athos@2228
   538
    /// source-side (i.e. a set \f$ X\subsetneq V \f$ with \f$ source \in X
athos@2228
   539
    /// \f$ and minimal out-degree).
deba@2211
   540
    void calculateOut() {
deba@2211
   541
      for (NodeIt it(*_graph); it != INVALID; ++it) {
deba@2211
   542
        if (it != _source) {
deba@2211
   543
          calculateOut(it);
deba@2211
   544
          return;
deba@2211
   545
        }
deba@2211
   546
      }
deba@2211
   547
    }
deba@2211
   548
athos@2228
   549
    /// \brief Calculates a minimum cut with \f$ source \f$ on the
athos@2228
   550
    /// source-side.
deba@2211
   551
    ///
athos@2228
   552
    /// \brief Calculates a minimum cut with \f$ source \f$ on the
athos@2228
   553
    /// source-side (i.e. a set \f$ X\subsetneq V \f$ with \f$ source \in X
athos@2228
   554
    /// \f$ and minimal out-degree). The \c target is the initial target
deba@2211
   555
    /// for the push-relabel algorithm.
deba@2211
   556
    void calculateOut(const Node& target) {
deba@2225
   557
      findMinCut(target, true, *_out_res_graph, *_out_current_edge);
deba@2211
   558
    }
deba@2211
   559
athos@2228
   560
    /// \brief Calculates a minimum cut with \f$ source \f$ on the
athos@2228
   561
    /// sink-side.
deba@2225
   562
    ///
athos@2228
   563
    /// \brief Calculates a minimum cut with \f$ source \f$ on the
athos@2228
   564
    /// sink-side (i.e. a set \f$ X\subsetneq V \f$ with \f$ source \notin X
athos@2228
   565
    /// \f$ and minimal out-degree).
deba@2211
   566
    void calculateIn() {
deba@2211
   567
      for (NodeIt it(*_graph); it != INVALID; ++it) {
deba@2211
   568
        if (it != _source) {
deba@2211
   569
          calculateIn(it);
deba@2211
   570
          return;
deba@2211
   571
        }
deba@2211
   572
      }
deba@2211
   573
    }
deba@2211
   574
athos@2228
   575
    /// \brief Calculates a minimum cut with \f$ source \f$ on the
athos@2228
   576
    /// sink-side.
deba@2225
   577
    ///
athos@2228
   578
    /// \brief Calculates a minimum cut with \f$ source \f$ on the
athos@2228
   579
    /// sink-side (i.e. a set \f$ X\subsetneq V \f$ with \f$ source \notin
athos@2228
   580
    /// X \f$ and minimal out-degree).  The \c target is the initial
athos@2228
   581
    /// target for the push-relabel algorithm.
deba@2225
   582
    void calculateIn(const Node& target) {
deba@2225
   583
      findMinCut(target, false, *_in_res_graph, *_in_current_edge);
deba@2225
   584
    }
deba@2225
   585
deba@2225
   586
    /// \brief Runs the algorithm.
deba@2225
   587
    ///
athos@2228
   588
    /// Runs the algorithm. It finds nodes \c source and \c target
athos@2228
   589
    /// arbitrarily and then calls \ref init(), \ref calculateOut()
athos@2228
   590
    /// and \ref calculateIn().
deba@2211
   591
    void run() {
deba@2211
   592
      init();
deba@2211
   593
      for (NodeIt it(*_graph); it != INVALID; ++it) {
deba@2211
   594
        if (it != _source) {
deba@2225
   595
          calculateOut(it);
deba@2225
   596
          calculateIn(it);
deba@2211
   597
          return;
deba@2211
   598
        }
deba@2211
   599
      }
deba@2211
   600
    }
deba@2211
   601
deba@2225
   602
    /// \brief Runs the algorithm.
deba@2225
   603
    ///
athos@2228
   604
    /// Runs the algorithm. It uses the given \c source node, finds a
athos@2228
   605
    /// proper \c target and then calls the \ref init(), \ref
athos@2228
   606
    /// calculateOut() and \ref calculateIn().
deba@2211
   607
    void run(const Node& s) {
deba@2211
   608
      init(s);
deba@2211
   609
      for (NodeIt it(*_graph); it != INVALID; ++it) {
deba@2211
   610
        if (it != _source) {
deba@2225
   611
          calculateOut(it);
deba@2225
   612
          calculateIn(it);
deba@2211
   613
          return;
deba@2211
   614
        }
deba@2211
   615
      }
deba@2211
   616
    }
deba@2211
   617
deba@2225
   618
    /// \brief Runs the algorithm.
deba@2225
   619
    ///
deba@2225
   620
    /// Runs the algorithm. It just calls the \ref init() and then
deba@2225
   621
    /// \ref calculateOut() and \ref calculateIn().
deba@2211
   622
    void run(const Node& s, const Node& t) {
deba@2225
   623
      init(s); 
deba@2225
   624
      calculateOut(t);
deba@2225
   625
      calculateIn(t);
deba@2211
   626
    }
deba@2225
   627
deba@2225
   628
    /// @}
deba@2211
   629
    
deba@2225
   630
    /// \name Query Functions The result of the %HaoOrlin algorithm
deba@2225
   631
    /// can be obtained using these functions.
deba@2225
   632
    /// \n
deba@2225
   633
    /// Before the use of these functions, either \ref run(), \ref
deba@2225
   634
    /// calculateOut() or \ref calculateIn() must be called.
deba@2225
   635
    
deba@2225
   636
    /// @{
deba@2225
   637
deba@2225
   638
    /// \brief Returns the value of the minimum value cut.
deba@2211
   639
    /// 
deba@2225
   640
    /// Returns the value of the minimum value cut.
deba@2211
   641
    Value minCut() const {
deba@2211
   642
      return _min_cut;
deba@2211
   643
    }
deba@2211
   644
deba@2211
   645
athos@2228
   646
    /// \brief Returns a minimum cut.
deba@2211
   647
    ///
deba@2211
   648
    /// Sets \c nodeMap to the characteristic vector of a minimum
athos@2228
   649
    /// value cut: it will give a nonempty set \f$ X\subsetneq V \f$
athos@2228
   650
    /// with minimal out-degree (i.e. \c nodeMap will be true exactly
athos@2228
   651
    /// for the nodes of \f$ X \f$.  \pre nodeMap should be a
athos@2228
   652
    /// bool-valued node-map.
deba@2211
   653
    template <typename NodeMap>
deba@2211
   654
    Value minCut(NodeMap& nodeMap) const {
deba@2211
   655
      for (NodeIt it(*_graph); it != INVALID; ++it) {
deba@2211
   656
	nodeMap.set(it, (*_min_cut_map)[it]);
deba@2211
   657
      }
deba@2211
   658
      return minCut();
deba@2211
   659
    }
deba@2225
   660
deba@2225
   661
    /// @}
deba@2211
   662
    
deba@2211
   663
  }; //class HaoOrlin 
deba@2211
   664
deba@2211
   665
deba@2211
   666
} //namespace lemon
deba@2211
   667
deba@2211
   668
#endif //LEMON_HAO_ORLIN_H