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