[Lemon-commits] [lemon_svn] deba: r2937 - hugo/trunk/lemon

Lemon SVN svn at lemon.cs.elte.hu
Mon Nov 6 21:51:21 CET 2006


Author: deba
Date: Thu Sep  7 16:16:47 2006
New Revision: 2937

Added:
   hugo/trunk/lemon/hao_orlin.h
      - copied, changed from r2932, /hugo_loc/work/deba/hao_orlin.h
Modified:
   hugo/trunk/lemon/Makefile.am

Log:
Hao-Orlin algorithm

It is based on Attila's work
It is tested on all dimacs files in data directory

It may need more execution control
 - possible interruption after each findNewSink



Modified: hugo/trunk/lemon/Makefile.am
==============================================================================
--- hugo/trunk/lemon/Makefile.am	(original)
+++ hugo/trunk/lemon/Makefile.am	Thu Sep  7 16:16:47 2006
@@ -57,6 +57,7 @@
 	lemon/graph_utils.h \
 	lemon/graph_writer.h \
 	lemon/grid_ugraph.h \
+	lemon/hao_orlin.h \
 	lemon/hypercube_graph.h \
 	lemon/iterable_maps.h \
 	lemon/johnson.h \

Copied: hugo/trunk/lemon/hao_orlin.h (from r2932, /hugo_loc/work/deba/hao_orlin.h)
==============================================================================
--- /hugo_loc/work/deba/hao_orlin.h	(original)
+++ hugo/trunk/lemon/hao_orlin.h	Thu Sep  7 16:16:47 2006
@@ -1,7 +1,9 @@
 /* -*- C++ -*-
- * lemon/hao_orlin.h - Part of LEMON, a generic C++ optimization library
  *
- * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * This file is a part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2003-2006
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
  * (Egervary Research Group on Combinatorial Optimization, EGRES).
  *
  * Permission to use, modify and distribute this software is granted
@@ -29,30 +31,44 @@
 
 /// \file
 /// \ingroup flowalgs
-/// Implementation of the Hao-Orlin algorithms class for testing network 
+/// \brief Implementation of the Hao-Orlin algorithm.
+///
+/// Implementation of the HaoOrlin algorithms class for testing network 
 /// reliability.
 
 namespace lemon {
 
-  /// \addtogroup flowalgs
-  /// @{                                                   
-
-  /// %Hao-Orlin algorithm for calculate minimum cut in directed graphs.
+  /// \ingroup flowalgs
+  ///
+  /// \brief %Hao-Orlin algorithm for calculate minimum cut in directed graphs.
   ///
   /// Hao-Orlin calculates the minimum cut in directed graphs. It
-  /// separates the nodes of the graph into two disjoint sets and the
-  /// summary of the edge capacities go from the first set to the
-  /// second set is the minimum.  The algorithm is a modified
-  /// push-relabel preflow algorithm and it calculates the minimum cat
-  /// in \f$ O(n^3) \f$ time. The purpose of such algorithm is testing
-  /// network reliability. For sparse undirected graph you can use the
+  /// separates the nodes of the graph into two disjoint sets, 
+  /// \f$ V_{out} \f$ and \f$ V_{in} \f$. This separation is the minimum
+  /// cut if the summary of the edge capacities which source is in
+  /// \f$ V_{out} \f$ and the target is in \f$ V_{in} \f$ is the
+  /// minimum.  The algorithm is a modified push-relabel preflow
+  /// algorithm and it calculates the minimum cut in \f$ O(n^3) \f$
+  /// time. The purpose of such algorithm is testing network
+  /// reliability. For sparse undirected graph you can use the
   /// algorithm of Nagamochi and Ibraki which solves the undirected
-  /// problem in \f$ O(n^3) \f$ time. 
+  /// problem in \f$ O(ne + n^2 \log(n)) \f$ time and it is implemented in the
+  /// MinCut algorithm class.
+  ///
+  /// \param _Graph is the graph type of the algorithm.
+  /// \param _CapacityMap is an edge map of capacities which should
+  /// be any numreric type. The default type is _Graph::EdgeMap<int>.
+  /// \param _Tolerance is the handler of the inexact computation. The
+  /// default type for it is Tolerance<typename CapacityMap::Value>.
   ///
   /// \author Attila Bernath and Balazs Dezso
+#ifdef DOXYGEN
+  template <typename _Graph, typename _CapacityMap, typename _Tolerance>
+#else
   template <typename _Graph,
 	    typename _CapacityMap = typename _Graph::template EdgeMap<int>,
             typename _Tolerance = Tolerance<typename _CapacityMap::Value> >
+#endif
   class HaoOrlin {
   protected:
 
@@ -70,6 +86,7 @@
     typedef typename Graph::InEdgeIt InEdgeIt;
 
     const Graph* _graph;
+
     const CapacityMap* _capacity;
 
     typedef typename Graph::template EdgeMap<Value> FlowMap;
@@ -80,18 +97,25 @@
     int _node_num;
 
     typedef ResGraphAdaptor<const Graph, Value, CapacityMap, 
-                            FlowMap, Tolerance> ResGraph;
-    typedef typename ResGraph::Node ResNode;
-    typedef typename ResGraph::NodeIt ResNodeIt;
-    typedef typename ResGraph::EdgeIt ResEdgeIt;
-    typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
-    typedef typename ResGraph::Edge ResEdge;
-    typedef typename ResGraph::InEdgeIt ResInEdgeIt;
+                            FlowMap, Tolerance> OutResGraph;
+    typedef typename OutResGraph::Edge OutResEdge;
+    
+    OutResGraph* _out_res_graph;
 
-    ResGraph* _res_graph;
+    typedef typename Graph::template NodeMap<OutResEdge> OutCurrentEdgeMap;
+    OutCurrentEdgeMap* _out_current_edge;  
 
-    typedef typename Graph::template NodeMap<ResEdge> CurrentArcMap;
-    CurrentArcMap* _current_arc;  
+    typedef RevGraphAdaptor<const Graph> RevGraph;
+    RevGraph* _rev_graph;
+
+    typedef ResGraphAdaptor<const RevGraph, Value, CapacityMap, 
+                            FlowMap, Tolerance> InResGraph;
+    typedef typename InResGraph::Edge InResEdge;
+    
+    InResGraph* _in_res_graph;
+
+    typedef typename Graph::template NodeMap<InResEdge> InCurrentEdgeMap;
+    InCurrentEdgeMap* _in_current_edge;  
 
 
     typedef IterableBoolMap<Graph, Node> WakeMap;
@@ -124,23 +148,37 @@
 
   public: 
 
+    /// \brief Constructor
+    ///
+    /// Constructor of the algorithm class. 
     HaoOrlin(const Graph& graph, const CapacityMap& capacity, 
              const Tolerance& tolerance = Tolerance()) :
       _graph(&graph), _capacity(&capacity), 
-      _preflow(0), _source(), _target(), _res_graph(0), _current_arc(0),
+      _preflow(0), _source(), _target(), 
+      _out_res_graph(0), _out_current_edge(0),
+      _rev_graph(0), _in_res_graph(0), _in_current_edge(0),
       _wake(0),_dist(0), _excess(0), _source_set(0), 
       _highest_active(), _active_nodes(), _dormant_max(), _dormant(), 
       _min_cut(), _min_cut_map(0), _tolerance(tolerance) {}
 
     ~HaoOrlin() {
-      if (_res_graph) {
-        delete _res_graph;
-      }
       if (_min_cut_map) {
         delete _min_cut_map;
       } 
-      if (_current_arc) {
-        delete _current_arc;
+      if (_in_current_edge) {
+        delete _in_current_edge;
+      }
+      if (_in_res_graph) {
+        delete _in_res_graph;
+      }
+      if (_rev_graph) {
+        delete _rev_graph;
+      }
+      if (_out_current_edge) {
+        delete _out_current_edge;
+      }
+      if (_out_res_graph) {
+        delete _out_res_graph;
       }
       if (_source_set) {
         delete _source_set;
@@ -161,8 +199,103 @@
     
   private:
     
-    void relabel(Node i) {
-      int k = (*_dist)[i];
+    template <typename ResGraph, typename EdgeMap>
+    void findMinCut(const Node& target, bool out, 
+                    ResGraph& res_graph, EdgeMap& current_edge) {
+      typedef typename ResGraph::Edge ResEdge;
+      typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
+
+      for (typename Graph::EdgeIt it(*_graph); it != INVALID; ++it) {
+        (*_preflow)[it] = 0;      
+      }
+      for (NodeIt it(*_graph); it != INVALID; ++it) {
+        (*_wake)[it] = true;
+        (*_dist)[it] = 1;
+        (*_excess)[it] = 0;
+        (*_source_set)[it] = false;
+
+        res_graph.firstOut(current_edge[it], it);
+      }
+
+      _target = target;
+      (*_dist)[target] = 0;
+
+      for (ResOutEdgeIt it(res_graph, _source); it != INVALID; ++it) {
+        Value delta = res_graph.rescap(it);
+        if (!_tolerance.positive(delta)) continue;
+        
+        (*_excess)[res_graph.source(it)] -= delta;
+        res_graph.augment(it, delta);
+        Node a = res_graph.target(it);
+        if (!_tolerance.positive((*_excess)[a]) && 
+            (*_wake)[a] && a != _target) {
+          _active_nodes[(*_dist)[a]].push_front(a);
+          if (_highest_active < (*_dist)[a]) {
+            _highest_active = (*_dist)[a];
+          }
+        }
+        (*_excess)[a] += delta;
+      }
+
+      _dormant[0].push_front(_source);
+      (*_source_set)[_source] = true;
+      _dormant_max = 0;
+      (*_wake)[_source] = false;
+
+      _level_size[0] = 1;
+      _level_size[1] = _node_num - 1;
+
+      do {
+	Node n;
+	while ((n = findActiveNode()) != INVALID) {
+	  ResEdge e;
+	  while (_tolerance.positive((*_excess)[n]) && 
+                 (e = findAdmissibleEdge(n, res_graph, current_edge)) 
+                 != INVALID){
+	    Value delta;
+	    if ((*_excess)[n] < res_graph.rescap(e)) {
+	      delta = (*_excess)[n];
+	    } else {
+	      delta = res_graph.rescap(e);
+	      res_graph.nextOut(current_edge[n]);
+	    }
+            if (!_tolerance.positive(delta)) continue;
+	    res_graph.augment(e, delta);
+	    (*_excess)[res_graph.source(e)] -= delta;
+	    Node a = res_graph.target(e);
+	    if (!_tolerance.positive((*_excess)[a]) && a != _target) {
+	      _active_nodes[(*_dist)[a]].push_front(a);
+	    }
+	    (*_excess)[a] += delta;
+	  }
+	  if (_tolerance.positive((*_excess)[n])) {
+	    relabel(n, res_graph, current_edge);
+          }
+	}
+
+	Value current_value = cutValue(out);
+ 	if (_min_cut > current_value){
+          if (out) {
+            for (NodeIt it(*_graph); it != INVALID; ++it) {
+              _min_cut_map->set(it, !(*_wake)[it]);
+            } 
+          } else {
+            for (NodeIt it(*_graph); it != INVALID; ++it) {
+              _min_cut_map->set(it, (*_wake)[it]);
+            } 
+          }
+
+	  _min_cut = current_value;
+ 	}
+
+      } while (selectNewSink(res_graph));
+    }
+
+    template <typename ResGraph, typename EdgeMap>
+    void relabel(const Node& n, ResGraph& res_graph, EdgeMap& current_edge) {
+      typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
+
+      int k = (*_dist)[n];
       if (_level_size[k] == 1) {
 	++_dormant_max;
 	for (NodeIt it(*_graph); it != INVALID; ++it) {
@@ -173,39 +306,34 @@
 	  }
 	}
 	--_highest_active;
-      } else {
-	ResOutEdgeIt e(*_res_graph, i);
-	while (e != INVALID && !(*_wake)[_res_graph->target(e)]) {
-	  ++e;
-	}
-
-	if (e == INVALID){
+      } else {	
+        int new_dist = _node_num;
+        for (ResOutEdgeIt e(res_graph, n); e != INVALID; ++e) {
+          Node t = res_graph.target(e);
+          if ((*_wake)[t] && new_dist > (*_dist)[t]) {
+            new_dist = (*_dist)[t];
+          }
+        }
+        if (new_dist == _node_num) {
 	  ++_dormant_max;
-	  (*_wake)[i] = false;
-	  _dormant[_dormant_max].push_front(i);
-	  --_level_size[(*_dist)[i]];
-	} else{	    
-	  Node j = _res_graph->target(e);
-	  int new_dist = (*_dist)[j];
-	  ++e;
-	  while (e != INVALID){
-	    Node j = _res_graph->target(e);
-	    if ((*_wake)[j] && new_dist > (*_dist)[j]) {
-	      new_dist = (*_dist)[j];
-            }
-	    ++e;
-	  }
-	  --_level_size[(*_dist)[i]];
-	  (*_dist)[i] = new_dist + 1;
-	  _highest_active = (*_dist)[i];
-	  _active_nodes[_highest_active].push_front(i);
-	  ++_level_size[(*_dist)[i]];
-	  _res_graph->firstOut((*_current_arc)[i], i);
+	  (*_wake)[n] = false;
+	  _dormant[_dormant_max].push_front(n);
+	  --_level_size[(*_dist)[n]];
+	} else {	    
+	  --_level_size[(*_dist)[n]];
+	  (*_dist)[n] = new_dist + 1;
+	  _highest_active = (*_dist)[n];
+	  _active_nodes[_highest_active].push_front(n);
+	  ++_level_size[(*_dist)[n]];
+	  res_graph.firstOut(current_edge[n], n);
 	}
       }
     }
 
-    bool selectNewSink(){
+    template <typename ResGraph>
+    bool selectNewSink(ResGraph& res_graph) {
+      typedef typename ResGraph::OutEdgeIt ResOutEdgeIt;
+
       Node old_target = _target;
       (*_wake)[_target] = false;
       --_level_size[(*_dist)[_target]];
@@ -249,9 +377,21 @@
 	}
       }
 
-      for (ResOutEdgeIt e(*_res_graph, old_target); e!=INVALID; ++e){
-	if (!(*_source_set)[_res_graph->target(e)]){
-	  push(e, _res_graph->rescap(e));
+      for (ResOutEdgeIt e(res_graph, old_target); e!=INVALID; ++e){
+	if (!(*_source_set)[res_graph.target(e)]) {
+          Value delta = res_graph.rescap(e);
+          if (!_tolerance.positive(delta)) continue;
+          res_graph.augment(e, delta);
+          (*_excess)[res_graph.source(e)] -= delta;
+          Node a = res_graph.target(e);
+          if (!_tolerance.positive((*_excess)[a]) && 
+              (*_wake)[a] && a != _target) {
+            _active_nodes[(*_dist)[a]].push_front(a);
+            if (_highest_active < (*_dist)[a]) {
+              _highest_active = (*_dist)[a];
+            }
+          }
+          (*_excess)[a] += delta;
 	}
       }
       
@@ -271,54 +411,64 @@
       }
     }
 
-    ResEdge findAdmissibleEdge(const Node& n){
-      ResEdge e = (*_current_arc)[n];
+    template <typename ResGraph, typename EdgeMap>
+    typename ResGraph::Edge findAdmissibleEdge(const Node& n, 
+                                               ResGraph& res_graph, 
+                                               EdgeMap& current_edge) {
+      typedef typename ResGraph::Edge ResEdge;
+      ResEdge e = current_edge[n];
       while (e != INVALID && 
-             ((*_dist)[n] <= (*_dist)[_res_graph->target(e)] || 
-              !(*_wake)[_res_graph->target(e)])) {
-	_res_graph->nextOut(e);
+             ((*_dist)[n] <= (*_dist)[res_graph.target(e)] || 
+              !(*_wake)[res_graph.target(e)])) {
+	res_graph.nextOut(e);
       }
       if (e != INVALID) {
-	(*_current_arc)[n] = e;	
+	current_edge[n] = e;	
 	return e;
       } else {
 	return INVALID;
       }
     }
 
-    void push(ResEdge& e,const Value& delta){
-      _res_graph->augment(e, delta);
-      if (!_tolerance.positive(delta)) return;
-      
-      (*_excess)[_res_graph->source(e)] -= delta;
-      Node a = _res_graph->target(e);
-      if (!_tolerance.positive((*_excess)[a]) && (*_wake)[a] && a != _target) {
-	_active_nodes[(*_dist)[a]].push_front(a);
-	if (_highest_active < (*_dist)[a]) {
-	  _highest_active = (*_dist)[a];
-        }
-      }
-      (*_excess)[a] += delta;
-    }
-    
-    Value cutValue() {
+    Value cutValue(bool out) {
       Value value = 0;
-      for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
-	for (InEdgeIt e(*_graph, it); e != INVALID; ++e) {
-	  if (!(*_wake)[_graph->source(e)]){
-	    value += (*_capacity)[e];
-	  }	
-	}
+      if (out) {
+        for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
+          for (InEdgeIt e(*_graph, it); e != INVALID; ++e) {
+            if (!(*_wake)[_graph->source(e)]){
+              value += (*_capacity)[e];
+            }	
+          }
+        }
+      } else {
+        for (typename WakeMap::TrueIt it(*_wake); it != INVALID; ++it) {
+          for (OutEdgeIt e(*_graph, it); e != INVALID; ++e) {
+            if (!(*_wake)[_graph->target(e)]){
+              value += (*_capacity)[e];
+            }	
+          }
+        }
       }
       return value;
-    }    
+    }
+
 
   public:
 
+    /// \name Execution control
+    /// The simplest way to execute the algorithm is to use
+    /// one of the member functions called \c run(...).
+    /// \n
+    /// If you need more control on the execution,
+    /// first you must call \ref init(), then the \ref calculateIn() or
+    /// \ref calculateIn() functions.
+
+    /// @{
+
     /// \brief Initializes the internal data structures.
     ///
     /// Initializes the internal data structures. It creates
-    /// the maps, residual graph adaptor and some bucket structures
+    /// the maps, residual graph adaptors and some bucket structures
     /// for the algorithm. 
     void init() {
       init(NodeIt(*_graph));
@@ -353,25 +503,34 @@
       if (!_source_set) {
         _source_set = new SourceSetMap(*_graph);
       }
-      if (!_current_arc) {
-        _current_arc = new CurrentArcMap(*_graph);
+      if (!_out_res_graph) {
+        _out_res_graph = new OutResGraph(*_graph, *_capacity, *_preflow);
+      }
+      if (!_out_current_edge) {
+        _out_current_edge = new OutCurrentEdgeMap(*_graph);
+      }
+      if (!_rev_graph) {
+        _rev_graph = new RevGraph(*_graph);
+      }
+      if (!_in_res_graph) {
+        _in_res_graph = new InResGraph(*_rev_graph, *_capacity, *_preflow);
+      }
+      if (!_in_current_edge) {
+        _in_current_edge = new InCurrentEdgeMap(*_graph);
       }
       if (!_min_cut_map) {
         _min_cut_map = new MinCutMap(*_graph);
       }
-      if (!_res_graph) {
-        _res_graph = new ResGraph(*_graph, *_capacity, *_preflow);
-      }
 
       _min_cut = std::numeric_limits<Value>::max();
     }
 
 
     /// \brief Calculates the minimum cut with the \c source node
-    /// in the first partition.
+    /// in the \f$ V_{out} \f$.
     ///
     /// Calculates the minimum cut with the \c source node
-    /// in the first partition.
+    /// in the \f$ V_{out} \f$.
     void calculateOut() {
       for (NodeIt it(*_graph); it != INVALID; ++it) {
         if (it != _source) {
@@ -382,75 +541,20 @@
     }
 
     /// \brief Calculates the minimum cut with the \c source node
-    /// in the first partition.
+    /// in the \f$ V_{out} \f$.
     ///
     /// Calculates the minimum cut with the \c source node
-    /// in the first partition. The \c target is the initial target
+    /// in the \f$ V_{out} \f$. The \c target is the initial target
     /// for the push-relabel algorithm.
     void calculateOut(const Node& target) {
-      for (NodeIt it(*_graph); it != INVALID; ++it) {
-        (*_wake)[it] = true;
-        (*_dist)[it] = 1;
-        (*_excess)[it] = 0;
-        (*_source_set)[it] = false;
-
-        _res_graph->firstOut((*_current_arc)[it], it);
-      }
-
-      _target = target;
-      (*_dist)[target] = 0;
-
-      for (ResOutEdgeIt it(*_res_graph, _source); it != INVALID; ++it) {
-	push(it, _res_graph->rescap(it));
-      }
-
-      _dormant[0].push_front(_source);
-      (*_source_set)[_source] = true;
-      _dormant_max = 0;
-      (*_wake)[_source]=false;
-
-      _level_size[0] = 1;
-      _level_size[1] = _node_num - 1;
-
-      do {
-	Node n;
-	while ((n = findActiveNode()) != INVALID) {
-	  ResEdge e;
-	  while (_tolerance.positive((*_excess)[n]) && 
-                 (e = findAdmissibleEdge(n)) != INVALID){
-	    Value delta;
-	    if ((*_excess)[n] < _res_graph->rescap(e)) {
-	      delta = (*_excess)[n];
-	    } else {
-	      delta = _res_graph->rescap(e);
-	      _res_graph->nextOut((*_current_arc)[n]);
-	    }
-            if (!_tolerance.positive(delta)) continue;
-	    _res_graph->augment(e, delta);
-	    (*_excess)[_res_graph->source(e)] -= delta;
-	    Node a = _res_graph->target(e);
-	    if (!_tolerance.positive((*_excess)[a]) && a != _target) {
-	      _active_nodes[(*_dist)[a]].push_front(a);
-	    }
-	    (*_excess)[a] += delta;
-	  }
-	  if (_tolerance.positive((*_excess)[n])) {
-	    relabel(n);
-          }
-	}
-
-	Value current_value = cutValue();
- 	if (_min_cut > current_value){
-	  for (NodeIt it(*_graph); it != INVALID; ++it) {
-            _min_cut_map->set(it, !(*_wake)[it]);
-	  }
-
-	  _min_cut = current_value;
- 	}
-
-      } while (selectNewSink());
+      findMinCut(target, true, *_out_res_graph, *_out_current_edge);
     }
 
+    /// \brief Calculates the minimum cut with the \c source node
+    /// in the \f$ V_{in} \f$.
+    ///
+    /// Calculates the minimum cut with the \c source node
+    /// in the \f$ V_{in} \f$.
     void calculateIn() {
       for (NodeIt it(*_graph); it != INVALID; ++it) {
         if (it != _source) {
@@ -460,40 +564,70 @@
       }
     }
 
+    /// \brief Calculates the minimum cut with the \c source node
+    /// in the \f$ V_{in} \f$.
+    ///
+    /// Calculates the minimum cut with the \c source node
+    /// in the \f$ V_{in} \f$. The \c target is the initial target
+    /// for the push-relabel algorithm.
+    void calculateIn(const Node& target) {
+      findMinCut(target, false, *_in_res_graph, *_in_current_edge);
+    }
+
+    /// \brief Runs the algorithm.
+    ///
+    /// Runs the algorithm. It finds a proper \c source and \c target
+    /// and then calls the \ref init(), \ref calculateOut() and \ref
+    /// calculateIn().
     void run() {
       init();
       for (NodeIt it(*_graph); it != INVALID; ++it) {
         if (it != _source) {
-          startOut(it);
-          //          startIn(it);
+          calculateOut(it);
+          calculateIn(it);
           return;
         }
       }
     }
 
+    /// \brief Runs the algorithm.
+    ///
+    /// Runs the algorithm. It finds a proper \c target and then calls
+    /// the \ref init(), \ref calculateOut() and \ref calculateIn().
     void run(const Node& s) {
       init(s);
       for (NodeIt it(*_graph); it != INVALID; ++it) {
         if (it != _source) {
-          startOut(it);
-          //          startIn(it);
+          calculateOut(it);
+          calculateIn(it);
           return;
         }
       }
     }
 
+    /// \brief Runs the algorithm.
+    ///
+    /// Runs the algorithm. It just calls the \ref init() and then
+    /// \ref calculateOut() and \ref calculateIn().
     void run(const Node& s, const Node& t) {
-      init(s);
-      startOut(t);
-      startIn(t);
+      init(s); 
+      calculateOut(t);
+      calculateIn(t);
     }
+
+    /// @}
+    
+    /// \name Query Functions The result of the %HaoOrlin algorithm
+    /// can be obtained using these functions.
+    /// \n
+    /// Before the use of these functions, either \ref run(), \ref
+    /// calculateOut() or \ref calculateIn() must be called.
     
-    /// \brief Returns the value of the minimum value cut with node \c
-    /// source on the source side.
+    /// @{
+
+    /// \brief Returns the value of the minimum value cut.
     /// 
-    /// Returns the value of the minimum value cut with node \c source
-    /// on the source side. This function can be called after running
-    /// \ref findMinCut.
+    /// Returns the value of the minimum value cut.
     Value minCut() const {
       return _min_cut;
     }
@@ -502,8 +636,8 @@
     /// \brief Returns a minimum value cut.
     ///
     /// Sets \c nodeMap to the characteristic vector of a minimum
-    /// value cut with node \c source on the source side. This
-    /// function can be called after running \ref findMinCut.  
+    /// value cut. The nodes in \f$ V_{out} \f$ will be set true and
+    /// the nodes in \f$ V_{in} \f$ will be set false. 
     /// \pre nodeMap should be a bool-valued node-map.
     template <typename NodeMap>
     Value minCut(NodeMap& nodeMap) const {
@@ -512,6 +646,8 @@
       }
       return minCut();
     }
+
+    /// @}
     
   }; //class HaoOrlin 
 



More information about the Lemon-commits mailing list