lemon/hao_orlin.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 2225 bb3d5e6f9fcb
child 2273 507232469f5e
permissions -rw-r--r--
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

The tests have been modified to the current implementation
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