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