[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