lemon/hao_orlin.h
author alpar
Fri, 20 Apr 2007 14:50:42 +0000
changeset 2430 c14aaef85d50
parent 2386 81b47fc5c444
child 2530 f86f7e4eb2ba
permissions -rw-r--r--
Test broken repository warning
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
 *
alpar@2391
     5
 * Copyright (C) 2003-2007
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@2376
    37
/// \ingroup min_cut
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@2376
    45
  /// \ingroup min_cut
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@2225
   200
      typedef typename ResGraph::Edge ResEdge;
deba@2225
   201
      typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
deba@2225
   202
deba@2225
   203
      for (typename Graph::EdgeIt it(*_graph); it != INVALID; ++it) {
deba@2225
   204
        (*_preflow)[it] = 0;      
deba@2225
   205
      }
deba@2225
   206
      for (NodeIt it(*_graph); it != INVALID; ++it) {
deba@2225
   207
        (*_wake)[it] = true;
deba@2225
   208
        (*_dist)[it] = 1;
deba@2225
   209
        (*_excess)[it] = 0;
deba@2225
   210
        (*_source_set)[it] = false;
deba@2225
   211
      }
deba@2225
   212
deba@2225
   213
      _dormant[0].push_front(_source);
deba@2225
   214
      (*_source_set)[_source] = true;
deba@2225
   215
      _dormant_max = 0;
deba@2225
   216
      (*_wake)[_source] = false;
deba@2225
   217
deba@2225
   218
      _level_size[0] = 1;
deba@2225
   219
      _level_size[1] = _node_num - 1;
deba@2225
   220
deba@2340
   221
      _target = target;
deba@2340
   222
      (*_dist)[target] = 0;
deba@2340
   223
deba@2340
   224
      for (ResOutEdgeIt it(res_graph, _source); it != INVALID; ++it) {
deba@2340
   225
        Value delta = res_graph.rescap(it);
deba@2340
   226
        (*_excess)[_source] -= delta;
deba@2340
   227
        res_graph.augment(it, delta);
deba@2340
   228
        Node a = res_graph.target(it);
deba@2340
   229
        if ((*_excess)[a] == 0 && (*_wake)[a] && a != _target) {
deba@2340
   230
          _active_nodes[(*_dist)[a]].push_front(a);
deba@2340
   231
          if (_highest_active < (*_dist)[a]) {
deba@2340
   232
            _highest_active = (*_dist)[a];
deba@2340
   233
          }
deba@2340
   234
        }
deba@2340
   235
        (*_excess)[a] += delta;
deba@2340
   236
      }
deba@2340
   237
deba@2340
   238
deba@2225
   239
      do {
deba@2225
   240
	Node n;
deba@2225
   241
	while ((n = findActiveNode()) != INVALID) {
deba@2340
   242
	  for (ResOutEdgeIt e(res_graph, n); e != INVALID; ++e) {
deba@2340
   243
            Node a = res_graph.target(e);
deba@2340
   244
            if ((*_dist)[a] >= (*_dist)[n] || !(*_wake)[a]) continue;
deba@2340
   245
	    Value delta = res_graph.rescap(e);
deba@2340
   246
	    if (_tolerance.positive((*_excess)[n] - delta)) {
deba@2340
   247
              (*_excess)[n] -= delta;
deba@2340
   248
	    } else {
deba@2225
   249
	      delta = (*_excess)[n];
deba@2340
   250
              (*_excess)[n] = 0;
deba@2225
   251
	    }
deba@2225
   252
	    res_graph.augment(e, delta);
deba@2340
   253
	    if ((*_excess)[a] == 0 && a != _target) {
deba@2225
   254
	      _active_nodes[(*_dist)[a]].push_front(a);
deba@2225
   255
	    }
deba@2225
   256
	    (*_excess)[a] += delta;
deba@2340
   257
            if ((*_excess)[n] == 0) break;
deba@2225
   258
	  }
deba@2340
   259
	  if ((*_excess)[n] != 0) {
deba@2340
   260
	    relabel(n, res_graph);
deba@2225
   261
          }
deba@2225
   262
	}
deba@2225
   263
deba@2225
   264
	Value current_value = cutValue(out);
deba@2225
   265
 	if (_min_cut > current_value){
deba@2225
   266
          if (out) {
deba@2225
   267
            for (NodeIt it(*_graph); it != INVALID; ++it) {
deba@2225
   268
              _min_cut_map->set(it, !(*_wake)[it]);
deba@2225
   269
            } 
deba@2225
   270
          } else {
deba@2225
   271
            for (NodeIt it(*_graph); it != INVALID; ++it) {
deba@2225
   272
              _min_cut_map->set(it, (*_wake)[it]);
deba@2225
   273
            } 
deba@2225
   274
          }
deba@2225
   275
deba@2225
   276
	  _min_cut = current_value;
deba@2225
   277
 	}
deba@2225
   278
deba@2225
   279
      } while (selectNewSink(res_graph));
deba@2225
   280
    }
deba@2225
   281
deba@2340
   282
    template <typename ResGraph>
deba@2340
   283
    void relabel(const Node& n, ResGraph& res_graph) {
deba@2225
   284
      typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
deba@2225
   285
deba@2225
   286
      int k = (*_dist)[n];
deba@2211
   287
      if (_level_size[k] == 1) {
deba@2211
   288
	++_dormant_max;
deba@2211
   289
	for (NodeIt it(*_graph); it != INVALID; ++it) {
deba@2211
   290
	  if ((*_wake)[it] && (*_dist)[it] >= k) {
deba@2211
   291
	    (*_wake)[it] = false;
deba@2211
   292
	    _dormant[_dormant_max].push_front(it);
deba@2211
   293
	    --_level_size[(*_dist)[it]];
deba@2211
   294
	  }
deba@2211
   295
	}
deba@2340
   296
        --_highest_active;
deba@2225
   297
      } else {	
deba@2225
   298
        int new_dist = _node_num;
deba@2225
   299
        for (ResOutEdgeIt e(res_graph, n); e != INVALID; ++e) {
deba@2225
   300
          Node t = res_graph.target(e);
deba@2225
   301
          if ((*_wake)[t] && new_dist > (*_dist)[t]) {
deba@2225
   302
            new_dist = (*_dist)[t];
deba@2225
   303
          }
deba@2225
   304
        }
deba@2225
   305
        if (new_dist == _node_num) {
deba@2211
   306
	  ++_dormant_max;
deba@2225
   307
	  (*_wake)[n] = false;
deba@2225
   308
	  _dormant[_dormant_max].push_front(n);
deba@2225
   309
	  --_level_size[(*_dist)[n]];
deba@2225
   310
	} else {	    
deba@2225
   311
	  --_level_size[(*_dist)[n]];
deba@2225
   312
	  (*_dist)[n] = new_dist + 1;
deba@2225
   313
	  _highest_active = (*_dist)[n];
deba@2225
   314
	  _active_nodes[_highest_active].push_front(n);
deba@2225
   315
	  ++_level_size[(*_dist)[n]];
deba@2211
   316
	}
deba@2211
   317
      }
deba@2211
   318
    }
deba@2211
   319
deba@2225
   320
    template <typename ResGraph>
deba@2225
   321
    bool selectNewSink(ResGraph& res_graph) {
deba@2225
   322
      typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
deba@2225
   323
deba@2211
   324
      Node old_target = _target;
deba@2211
   325
      (*_wake)[_target] = false;
deba@2211
   326
      --_level_size[(*_dist)[_target]];
deba@2211
   327
      _dormant[0].push_front(_target);
deba@2211
   328
      (*_source_set)[_target] = true;
deba@2386
   329
      if (int(_dormant[0].size()) == _node_num){
deba@2211
   330
        _dormant[0].clear();
deba@2211
   331
	return false;
deba@2211
   332
      }
deba@2211
   333
deba@2211
   334
      bool wake_was_empty = false;
deba@2211
   335
deba@2211
   336
      if(_wake->trueNum() == 0) {
deba@2211
   337
	while (!_dormant[_dormant_max].empty()){
deba@2211
   338
	  (*_wake)[_dormant[_dormant_max].front()] = true;
deba@2211
   339
	  ++_level_size[(*_dist)[_dormant[_dormant_max].front()]];
deba@2211
   340
	  _dormant[_dormant_max].pop_front();
deba@2211
   341
	}
deba@2211
   342
	--_dormant_max;
deba@2211
   343
	wake_was_empty = true;
deba@2211
   344
      }
deba@2211
   345
deba@2211
   346
      int min_dist = std::numeric_limits<int>::max();
deba@2211
   347
      for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
deba@2211
   348
	if (min_dist > (*_dist)[it]){
deba@2211
   349
	  _target = it;
deba@2211
   350
	  min_dist = (*_dist)[it];
deba@2211
   351
	}
deba@2211
   352
      }
deba@2211
   353
deba@2211
   354
      if (wake_was_empty){
deba@2211
   355
	for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
deba@2340
   356
          if ((*_excess)[it] != 0 && it != _target) {
deba@2340
   357
            _active_nodes[(*_dist)[it]].push_front(it);
deba@2340
   358
            if (_highest_active < (*_dist)[it]) {
deba@2340
   359
              _highest_active = (*_dist)[it];		    
deba@2211
   360
            }
deba@2211
   361
	  }
deba@2211
   362
	}
deba@2211
   363
      }
deba@2211
   364
deba@2340
   365
      Node n = old_target;
deba@2340
   366
      for (ResOutEdgeIt e(res_graph, n); e != INVALID; ++e){
deba@2340
   367
        Node a = res_graph.target(e);
deba@2340
   368
	if (!(*_wake)[a]) continue;
deba@2340
   369
        Value delta = res_graph.rescap(e);
deba@2340
   370
        res_graph.augment(e, delta);
deba@2340
   371
        (*_excess)[n] -= delta;
deba@2340
   372
        if ((*_excess)[a] == 0 && (*_wake)[a] && a != _target) {
deba@2340
   373
          _active_nodes[(*_dist)[a]].push_front(a);
deba@2340
   374
          if (_highest_active < (*_dist)[a]) {
deba@2340
   375
            _highest_active = (*_dist)[a];
deba@2225
   376
          }
deba@2340
   377
        }
deba@2340
   378
        (*_excess)[a] += delta;
deba@2211
   379
      }
deba@2211
   380
      
deba@2211
   381
      return true;
deba@2211
   382
    }
deba@2340
   383
deba@2211
   384
    Node findActiveNode() {
deba@2211
   385
      while (_highest_active > 0 && _active_nodes[_highest_active].empty()){ 
deba@2211
   386
	--_highest_active;
deba@2211
   387
      }
deba@2211
   388
      if( _highest_active > 0) {
deba@2211
   389
       	Node n = _active_nodes[_highest_active].front();
deba@2211
   390
	_active_nodes[_highest_active].pop_front();
deba@2211
   391
	return n;
deba@2211
   392
      } else {
deba@2211
   393
	return INVALID;
deba@2211
   394
      }
deba@2211
   395
    }
deba@2211
   396
deba@2225
   397
    Value cutValue(bool out) {
deba@2225
   398
      Value value = 0;
deba@2225
   399
      if (out) {
deba@2225
   400
        for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
deba@2225
   401
          for (InEdgeIt e(*_graph, it); e != INVALID; ++e) {
deba@2225
   402
            if (!(*_wake)[_graph->source(e)]){
deba@2225
   403
              value += (*_capacity)[e];
deba@2225
   404
            }	
deba@2225
   405
          }
deba@2225
   406
        }
deba@2225
   407
      } else {
deba@2225
   408
        for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
deba@2225
   409
          for (OutEdgeIt e(*_graph, it); e != INVALID; ++e) {
deba@2225
   410
            if (!(*_wake)[_graph->target(e)]){
deba@2225
   411
              value += (*_capacity)[e];
deba@2225
   412
            }	
deba@2225
   413
          }
deba@2211
   414
        }
deba@2211
   415
      }
deba@2225
   416
      return value;
deba@2211
   417
    }
deba@2225
   418
deba@2211
   419
deba@2211
   420
  public:
deba@2211
   421
deba@2225
   422
    /// \name Execution control
deba@2225
   423
    /// The simplest way to execute the algorithm is to use
deba@2225
   424
    /// one of the member functions called \c run(...).
deba@2225
   425
    /// \n
deba@2225
   426
    /// If you need more control on the execution,
deba@2225
   427
    /// first you must call \ref init(), then the \ref calculateIn() or
deba@2225
   428
    /// \ref calculateIn() functions.
deba@2225
   429
deba@2225
   430
    /// @{
deba@2225
   431
deba@2211
   432
    /// \brief Initializes the internal data structures.
deba@2211
   433
    ///
deba@2211
   434
    /// Initializes the internal data structures. It creates
deba@2225
   435
    /// the maps, residual graph adaptors and some bucket structures
deba@2211
   436
    /// for the algorithm. 
deba@2211
   437
    void init() {
deba@2211
   438
      init(NodeIt(*_graph));
deba@2211
   439
    }
deba@2211
   440
deba@2211
   441
    /// \brief Initializes the internal data structures.
deba@2211
   442
    ///
deba@2211
   443
    /// Initializes the internal data structures. It creates
deba@2211
   444
    /// the maps, residual graph adaptor and some bucket structures
athos@2228
   445
    /// for the algorithm. Node \c source  is used as the push-relabel
deba@2211
   446
    /// algorithm's source.
deba@2211
   447
    void init(const Node& source) {
deba@2211
   448
      _source = source;
deba@2211
   449
      _node_num = countNodes(*_graph);
deba@2211
   450
deba@2211
   451
      _dormant.resize(_node_num);
deba@2211
   452
      _level_size.resize(_node_num, 0);
deba@2211
   453
      _active_nodes.resize(_node_num);
deba@2211
   454
deba@2211
   455
      if (!_preflow) {
deba@2211
   456
        _preflow = new FlowMap(*_graph);
deba@2211
   457
      }
deba@2211
   458
      if (!_wake) {
deba@2211
   459
        _wake = new WakeMap(*_graph);
deba@2211
   460
      }
deba@2211
   461
      if (!_dist) {
deba@2211
   462
        _dist = new DistMap(*_graph);
deba@2211
   463
      }
deba@2211
   464
      if (!_excess) {
deba@2211
   465
        _excess = new ExcessMap(*_graph);
deba@2211
   466
      }
deba@2211
   467
      if (!_source_set) {
deba@2211
   468
        _source_set = new SourceSetMap(*_graph);
deba@2211
   469
      }
deba@2225
   470
      if (!_out_res_graph) {
deba@2225
   471
        _out_res_graph = new OutResGraph(*_graph, *_capacity, *_preflow);
deba@2225
   472
      }
deba@2225
   473
      if (!_rev_graph) {
deba@2225
   474
        _rev_graph = new RevGraph(*_graph);
deba@2225
   475
      }
deba@2225
   476
      if (!_in_res_graph) {
deba@2225
   477
        _in_res_graph = new InResGraph(*_rev_graph, *_capacity, *_preflow);
deba@2225
   478
      }
deba@2211
   479
      if (!_min_cut_map) {
deba@2211
   480
        _min_cut_map = new MinCutMap(*_graph);
deba@2211
   481
      }
deba@2211
   482
deba@2211
   483
      _min_cut = std::numeric_limits<Value>::max();
deba@2211
   484
    }
deba@2211
   485
deba@2211
   486
athos@2228
   487
    /// \brief Calculates a minimum cut with \f$ source \f$ on the
athos@2228
   488
    /// source-side.
deba@2211
   489
    ///
athos@2228
   490
    /// \brief Calculates a minimum cut with \f$ source \f$ on the
athos@2273
   491
    /// source-side (i.e. a set \f$ X\subsetneq V \f$ with \f$ source \in X \f$
athos@2273
   492
    ///  and minimal out-degree).
deba@2211
   493
    void calculateOut() {
deba@2211
   494
      for (NodeIt it(*_graph); it != INVALID; ++it) {
deba@2211
   495
        if (it != _source) {
deba@2211
   496
          calculateOut(it);
deba@2211
   497
          return;
deba@2211
   498
        }
deba@2211
   499
      }
deba@2211
   500
    }
deba@2211
   501
athos@2228
   502
    /// \brief Calculates a minimum cut with \f$ source \f$ on the
athos@2228
   503
    /// source-side.
deba@2211
   504
    ///
athos@2228
   505
    /// \brief Calculates a minimum cut with \f$ source \f$ on the
athos@2273
   506
    /// source-side (i.e. a set \f$ X\subsetneq V \f$ with \f$ source \in X \f$
athos@2273
   507
    ///  and minimal out-degree). The \c target is the initial target
deba@2211
   508
    /// for the push-relabel algorithm.
deba@2211
   509
    void calculateOut(const Node& target) {
deba@2340
   510
      findMinCut(target, true, *_out_res_graph);
deba@2211
   511
    }
deba@2211
   512
athos@2228
   513
    /// \brief Calculates a minimum cut with \f$ source \f$ on the
athos@2228
   514
    /// sink-side.
deba@2225
   515
    ///
athos@2228
   516
    /// \brief Calculates a minimum cut with \f$ source \f$ on the
athos@2273
   517
    /// sink-side (i.e. a set \f$ X\subsetneq V \f$ with 
athos@2273
   518
    /// \f$ source \notin X \f$
athos@2273
   519
    /// and minimal out-degree).
deba@2211
   520
    void calculateIn() {
deba@2211
   521
      for (NodeIt it(*_graph); it != INVALID; ++it) {
deba@2211
   522
        if (it != _source) {
deba@2211
   523
          calculateIn(it);
deba@2211
   524
          return;
deba@2211
   525
        }
deba@2211
   526
      }
deba@2211
   527
    }
deba@2211
   528
athos@2228
   529
    /// \brief Calculates a minimum cut with \f$ source \f$ on the
athos@2228
   530
    /// sink-side.
deba@2225
   531
    ///
athos@2228
   532
    /// \brief Calculates a minimum cut with \f$ source \f$ on the
athos@2273
   533
    /// sink-side (i.e. a set \f$ X\subsetneq V 
athos@2273
   534
    /// \f$ with \f$ source \notin X \f$ and minimal out-degree).  
athos@2273
   535
    /// The \c target is the initial
athos@2228
   536
    /// target for the push-relabel algorithm.
deba@2225
   537
    void calculateIn(const Node& target) {
deba@2340
   538
      findMinCut(target, false, *_in_res_graph);
deba@2225
   539
    }
deba@2225
   540
deba@2225
   541
    /// \brief Runs the algorithm.
deba@2225
   542
    ///
athos@2228
   543
    /// Runs the algorithm. It finds nodes \c source and \c target
athos@2228
   544
    /// arbitrarily and then calls \ref init(), \ref calculateOut()
athos@2228
   545
    /// and \ref calculateIn().
deba@2211
   546
    void run() {
deba@2211
   547
      init();
deba@2211
   548
      for (NodeIt it(*_graph); it != INVALID; ++it) {
deba@2211
   549
        if (it != _source) {
deba@2225
   550
          calculateOut(it);
deba@2225
   551
          calculateIn(it);
deba@2211
   552
          return;
deba@2211
   553
        }
deba@2211
   554
      }
deba@2211
   555
    }
deba@2211
   556
deba@2225
   557
    /// \brief Runs the algorithm.
deba@2225
   558
    ///
athos@2228
   559
    /// Runs the algorithm. It uses the given \c source node, finds a
athos@2228
   560
    /// proper \c target and then calls the \ref init(), \ref
athos@2228
   561
    /// calculateOut() and \ref calculateIn().
deba@2211
   562
    void run(const Node& s) {
deba@2211
   563
      init(s);
deba@2211
   564
      for (NodeIt it(*_graph); it != INVALID; ++it) {
deba@2211
   565
        if (it != _source) {
deba@2225
   566
          calculateOut(it);
deba@2225
   567
          calculateIn(it);
deba@2211
   568
          return;
deba@2211
   569
        }
deba@2211
   570
      }
deba@2211
   571
    }
deba@2211
   572
deba@2225
   573
    /// \brief Runs the algorithm.
deba@2225
   574
    ///
deba@2225
   575
    /// Runs the algorithm. It just calls the \ref init() and then
deba@2225
   576
    /// \ref calculateOut() and \ref calculateIn().
deba@2211
   577
    void run(const Node& s, const Node& t) {
deba@2225
   578
      init(s); 
deba@2225
   579
      calculateOut(t);
deba@2225
   580
      calculateIn(t);
deba@2211
   581
    }
deba@2225
   582
deba@2225
   583
    /// @}
deba@2211
   584
    
athos@2275
   585
    /// \name Query Functions 
athos@2275
   586
    /// The result of the %HaoOrlin algorithm
deba@2225
   587
    /// can be obtained using these functions.
deba@2225
   588
    /// \n
athos@2275
   589
    /// Before using these functions, either \ref run(), \ref
deba@2225
   590
    /// calculateOut() or \ref calculateIn() must be called.
deba@2225
   591
    
deba@2225
   592
    /// @{
deba@2225
   593
deba@2225
   594
    /// \brief Returns the value of the minimum value cut.
deba@2211
   595
    /// 
deba@2225
   596
    /// Returns the value of the minimum value cut.
deba@2211
   597
    Value minCut() const {
deba@2211
   598
      return _min_cut;
deba@2211
   599
    }
deba@2211
   600
deba@2211
   601
athos@2228
   602
    /// \brief Returns a minimum cut.
deba@2211
   603
    ///
deba@2211
   604
    /// Sets \c nodeMap to the characteristic vector of a minimum
athos@2228
   605
    /// value cut: it will give a nonempty set \f$ X\subsetneq V \f$
athos@2228
   606
    /// with minimal out-degree (i.e. \c nodeMap will be true exactly
athos@2275
   607
    /// for the nodes of \f$ X \f$).  \pre nodeMap should be a
athos@2228
   608
    /// bool-valued node-map.
deba@2211
   609
    template <typename NodeMap>
deba@2211
   610
    Value minCut(NodeMap& nodeMap) const {
deba@2211
   611
      for (NodeIt it(*_graph); it != INVALID; ++it) {
deba@2211
   612
	nodeMap.set(it, (*_min_cut_map)[it]);
deba@2211
   613
      }
deba@2211
   614
      return minCut();
deba@2211
   615
    }
deba@2225
   616
deba@2225
   617
    /// @}
deba@2211
   618
    
deba@2211
   619
  }; //class HaoOrlin 
deba@2211
   620
deba@2211
   621
deba@2211
   622
} //namespace lemon
deba@2211
   623
deba@2211
   624
#endif //LEMON_HAO_ORLIN_H