[Lemon-commits] Balazs Dezso: Port Hao-Orlin algorithm from SVN ...

Lemon HG hg at lemon.cs.elte.hu
Tue Dec 2 12:04:59 CET 2008


details:   http://lemon.cs.elte.hu/hg/lemon/rev/b8ce15103485
changeset: 425:b8ce15103485
user:      Balazs Dezso <deba [at] inf.elte.hu>
date:      Mon Dec 01 23:12:16 2008 +0100
description:
	Port Hao-Orlin algorithm from SVN -r3509 (#58)

diffstat:

2 files changed, 986 insertions(+)
lemon/Makefile.am |    1 
lemon/hao_orlin.h |  985 +++++++++++++++++++++++++++++++++++++++++++++++++++++

diffs (truncated from 1000 to 300 lines):

diff -r 59d3aa4f921f -r b8ce15103485 lemon/Makefile.am
--- a/lemon/Makefile.am	Mon Dec 01 14:18:40 2008 +0000
+++ b/lemon/Makefile.am	Mon Dec 01 23:12:16 2008 +0100
@@ -36,6 +36,7 @@
         lemon/grid_graph.h \
 	lemon/hypercube_graph.h \
 	lemon/kruskal.h \
+	lemon/hao_orlin.h \
 	lemon/lgf_reader.h \
 	lemon/lgf_writer.h \
 	lemon/list_graph.h \
diff -r 59d3aa4f921f -r b8ce15103485 lemon/hao_orlin.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lemon/hao_orlin.h	Mon Dec 01 23:12:16 2008 +0100
@@ -0,0 +1,985 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2008
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_HAO_ORLIN_H
+#define LEMON_HAO_ORLIN_H
+
+#include <vector>
+#include <list>
+#include <limits>
+
+#include <lemon/maps.h>
+#include <lemon/core.h>
+#include <lemon/tolerance.h>
+
+/// \file
+/// \ingroup min_cut
+/// \brief Implementation of the Hao-Orlin algorithm.
+///
+/// Implementation of the Hao-Orlin algorithm class for testing network
+/// reliability.
+
+namespace lemon {
+
+  /// \ingroup min_cut
+  ///
+  /// \brief %Hao-Orlin algorithm to find a minimum cut in directed graphs.
+  ///
+  /// Hao-Orlin calculates a minimum cut in a directed graph
+  /// \f$D=(V,A)\f$. It takes a fixed node \f$ source \in V \f$ and
+  /// consists of two phases: in the first phase it determines a
+  /// minimum cut with \f$ source \f$ on the source-side (i.e. a set
+  /// \f$ X\subsetneq V \f$ with \f$ source \in X \f$ and minimal
+  /// out-degree) and in the second phase it determines a minimum cut
+  /// with \f$ source \f$ on the sink-side (i.e. a set
+  /// \f$ X\subsetneq V \f$ with \f$ source \notin X \f$ and minimal
+  /// out-degree). Obviously, the smaller of these two cuts will be a
+  /// minimum cut of \f$ D \f$. The algorithm is a modified
+  /// push-relabel preflow algorithm and our implementation calculates
+  /// the minimum cut in \f$ O(n^2\sqrt{m}) \f$ time (we use the
+  /// highest-label rule), or in \f$O(nm)\f$ for unit capacities. The
+  /// purpose of such algorithm is testing network reliability. For an
+  /// undirected graph you can run just the first phase of the
+  /// algorithm or you can use the algorithm of Nagamochi and Ibaraki
+  /// which solves the undirected problem in
+  /// \f$ O(nm + n^2 \log(n)) \f$ time: it is implemented in the
+  /// NagamochiIbaraki algorithm class.
+  ///
+  /// \param _Digraph 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 _Digraph::ArcMap<int>.
+  /// \param _Tolerance is the handler of the inexact computation. The
+  /// default type for this is Tolerance<CapacityMap::Value>.
+#ifdef DOXYGEN
+  template <typename _Digraph, typename _CapacityMap, typename _Tolerance>
+#else
+  template <typename _Digraph,
+            typename _CapacityMap = typename _Digraph::template ArcMap<int>,
+            typename _Tolerance = Tolerance<typename _CapacityMap::Value> >
+#endif
+  class HaoOrlin {
+  private:
+
+    typedef _Digraph Digraph;
+    typedef _CapacityMap CapacityMap;
+    typedef _Tolerance Tolerance;
+
+    typedef typename CapacityMap::Value Value;
+
+    TEMPLATE_GRAPH_TYPEDEFS(Digraph);
+
+    const Digraph& _graph;
+    const CapacityMap* _capacity;
+
+    typedef typename Digraph::template ArcMap<Value> FlowMap;
+    FlowMap* _flow;
+
+    Node _source;
+
+    int _node_num;
+
+    // Bucketing structure
+    std::vector<Node> _first, _last;
+    typename Digraph::template NodeMap<Node>* _next;
+    typename Digraph::template NodeMap<Node>* _prev;
+    typename Digraph::template NodeMap<bool>* _active;
+    typename Digraph::template NodeMap<int>* _bucket;
+
+    std::vector<bool> _dormant;
+
+    std::list<std::list<int> > _sets;
+    std::list<int>::iterator _highest;
+
+    typedef typename Digraph::template NodeMap<Value> ExcessMap;
+    ExcessMap* _excess;
+
+    typedef typename Digraph::template NodeMap<bool> SourceSetMap;
+    SourceSetMap* _source_set;
+
+    Value _min_cut;
+
+    typedef typename Digraph::template NodeMap<bool> MinCutMap;
+    MinCutMap* _min_cut_map;
+
+    Tolerance _tolerance;
+
+  public:
+
+    /// \brief Constructor
+    ///
+    /// Constructor of the algorithm class.
+    HaoOrlin(const Digraph& graph, const CapacityMap& capacity,
+             const Tolerance& tolerance = Tolerance()) :
+      _graph(graph), _capacity(&capacity), _flow(0), _source(),
+      _node_num(), _first(), _last(), _next(0), _prev(0),
+      _active(0), _bucket(0), _dormant(), _sets(), _highest(),
+      _excess(0), _source_set(0), _min_cut(), _min_cut_map(0),
+      _tolerance(tolerance) {}
+
+    ~HaoOrlin() {
+      if (_min_cut_map) {
+        delete _min_cut_map;
+      }
+      if (_source_set) {
+        delete _source_set;
+      }
+      if (_excess) {
+        delete _excess;
+      }
+      if (_next) {
+        delete _next;
+      }
+      if (_prev) {
+        delete _prev;
+      }
+      if (_active) {
+        delete _active;
+      }
+      if (_bucket) {
+        delete _bucket;
+      }
+      if (_flow) {
+        delete _flow;
+      }
+    }
+
+  private:
+
+    void activate(const Node& i) {
+      _active->set(i, true);
+
+      int bucket = (*_bucket)[i];
+
+      if ((*_prev)[i] == INVALID || (*_active)[(*_prev)[i]]) return;
+      //unlace
+      _next->set((*_prev)[i], (*_next)[i]);
+      if ((*_next)[i] != INVALID) {
+        _prev->set((*_next)[i], (*_prev)[i]);
+      } else {
+        _last[bucket] = (*_prev)[i];
+      }
+      //lace
+      _next->set(i, _first[bucket]);
+      _prev->set(_first[bucket], i);
+      _prev->set(i, INVALID);
+      _first[bucket] = i;
+    }
+
+    void deactivate(const Node& i) {
+      _active->set(i, false);
+      int bucket = (*_bucket)[i];
+
+      if ((*_next)[i] == INVALID || !(*_active)[(*_next)[i]]) return;
+
+      //unlace
+      _prev->set((*_next)[i], (*_prev)[i]);
+      if ((*_prev)[i] != INVALID) {
+        _next->set((*_prev)[i], (*_next)[i]);
+      } else {
+        _first[bucket] = (*_next)[i];
+      }
+      //lace
+      _prev->set(i, _last[bucket]);
+      _next->set(_last[bucket], i);
+      _next->set(i, INVALID);
+      _last[bucket] = i;
+    }
+
+    void addItem(const Node& i, int bucket) {
+      (*_bucket)[i] = bucket;
+      if (_last[bucket] != INVALID) {
+        _prev->set(i, _last[bucket]);
+        _next->set(_last[bucket], i);
+        _next->set(i, INVALID);
+        _last[bucket] = i;
+      } else {
+        _prev->set(i, INVALID);
+        _first[bucket] = i;
+        _next->set(i, INVALID);
+        _last[bucket] = i;
+      }
+    }
+
+    void findMinCutOut() {
+
+      for (NodeIt n(_graph); n != INVALID; ++n) {
+        _excess->set(n, 0);
+      }
+
+      for (ArcIt a(_graph); a != INVALID; ++a) {
+        _flow->set(a, 0);
+      }
+
+      int bucket_num = 1;
+
+      {
+        typename Digraph::template NodeMap<bool> reached(_graph, false);
+
+        reached.set(_source, true);
+
+        bool first_set = true;
+
+        for (NodeIt t(_graph); t != INVALID; ++t) {
+          if (reached[t]) continue;
+          _sets.push_front(std::list<int>());
+          _sets.front().push_front(bucket_num);
+          _dormant[bucket_num] = !first_set;
+
+          _bucket->set(t, bucket_num);
+          _first[bucket_num] = _last[bucket_num] = t;
+          _next->set(t, INVALID);
+          _prev->set(t, INVALID);
+
+          ++bucket_num;
+
+          std::vector<Node> queue;
+          queue.push_back(t);
+          reached.set(t, true);
+
+          while (!queue.empty()) {
+            _sets.front().push_front(bucket_num);
+            _dormant[bucket_num] = !first_set;
+            _first[bucket_num] = _last[bucket_num] = INVALID;
+
+            std::vector<Node> nqueue;
+            for (int i = 0; i < int(queue.size()); ++i) {
+              Node n = queue[i];
+              for (InArcIt a(_graph, n); a != INVALID; ++a) {
+                Node u = _graph.source(a);
+                if (!reached[u] && _tolerance.positive((*_capacity)[a])) {
+                  reached.set(u, true);
+                  addItem(u, bucket_num);
+                  nqueue.push_back(u);
+                }
+              }
+            }
+            queue.swap(nqueue);
+            ++bucket_num;
+          }
+          _sets.front().pop_front();
+          --bucket_num;
+          first_set = false;
+        }
+
+        _bucket->set(_source, 0);
+        _dormant[0] = true;
+      }
+      _source_set->set(_source, true);
+
+      Node target = _last[_sets.back().back()];
+      {



More information about the Lemon-commits mailing list