[Lemon-commits] Peter Kovacs: Port MinMeanCycle from SVN -r3524 ...

Lemon HG hg at lemon.cs.elte.hu
Thu Nov 5 08:59:55 CET 2009


details:   http://lemon.cs.elte.hu/hg/lemon/rev/b31e130db13d
changeset: 818:b31e130db13d
user:      Peter Kovacs <kpeter [at] inf.elte.hu>
date:      Mon Aug 03 14:12:55 2009 +0200
description:
	Port MinMeanCycle from SVN -r3524 (#179) with some doc improvements

diffstat:

 lemon/Makefile.am      |    1 +
 lemon/min_mean_cycle.h |  462 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 463 insertions(+), 0 deletions(-)

diffs (truncated from 478 to 300 lines):

diff --git a/lemon/Makefile.am b/lemon/Makefile.am
--- a/lemon/Makefile.am
+++ b/lemon/Makefile.am
@@ -97,6 +97,7 @@
 	lemon/matching.h \
 	lemon/math.h \
 	lemon/min_cost_arborescence.h \
+	lemon/min_mean_cycle.h \
 	lemon/nauty_reader.h \
 	lemon/network_simplex.h \
 	lemon/path.h \
diff --git a/lemon/min_mean_cycle.h b/lemon/min_mean_cycle.h
new file mode 100644
--- /dev/null
+++ b/lemon/min_mean_cycle.h
@@ -0,0 +1,462 @@
+/* -*- C++ -*-
+ *
+ * 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_MIN_MEAN_CYCLE_H
+#define LEMON_MIN_MEAN_CYCLE_H
+
+/// \ingroup shortest_path
+///
+/// \file
+/// \brief Howard's algorithm for finding a minimum mean cycle.
+
+#include <vector>
+#include <lemon/core.h>
+#include <lemon/path.h>
+#include <lemon/tolerance.h>
+#include <lemon/connectivity.h>
+
+namespace lemon {
+
+  /// \addtogroup shortest_path
+  /// @{
+
+  /// \brief Implementation of Howard's algorithm for finding a minimum
+  /// mean cycle.
+  ///
+  /// \ref MinMeanCycle implements Howard's algorithm for finding a
+  /// directed cycle of minimum mean length (cost) in a digraph.
+  ///
+  /// \tparam GR The type of the digraph the algorithm runs on.
+  /// \tparam LEN The type of the length map. The default
+  /// map type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
+  ///
+  /// \warning \c LEN::Value must be convertible to \c double.
+#ifdef DOXYGEN
+  template <typename GR, typename LEN>
+#else
+  template < typename GR,
+             typename LEN = typename GR::template ArcMap<int> >
+#endif
+  class MinMeanCycle
+  {
+  public:
+  
+    /// The type of the digraph the algorithm runs on
+    typedef GR Digraph;
+    /// The type of the length map
+    typedef LEN LengthMap;
+    /// The type of the arc lengths
+    typedef typename LengthMap::Value Value;
+    /// The type of the paths
+    typedef lemon::Path<Digraph> Path;
+
+  private:
+
+    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
+  
+    // The digraph the algorithm runs on
+    const Digraph &_gr;
+    // The length of the arcs
+    const LengthMap &_length;
+
+    // The total length of the found cycle
+    Value _cycle_length;
+    // The number of arcs on the found cycle
+    int _cycle_size;
+    // The found cycle
+    Path *_cycle_path;
+
+    bool _local_path;
+    bool _cycle_found;
+    Node _cycle_node;
+
+    typename Digraph::template NodeMap<bool> _reached;
+    typename Digraph::template NodeMap<double> _dist;
+    typename Digraph::template NodeMap<Arc> _policy;
+
+    typename Digraph::template NodeMap<int> _comp;
+    int _comp_num;
+
+    std::vector<Node> _nodes;
+    std::vector<Arc> _arcs;
+    Tolerance<double> _tol;
+
+  public:
+
+    /// \brief Constructor.
+    ///
+    /// The constructor of the class.
+    ///
+    /// \param digraph The digraph the algorithm runs on.
+    /// \param length The lengths (costs) of the arcs.
+    MinMeanCycle( const Digraph &digraph,
+                  const LengthMap &length ) :
+      _gr(digraph), _length(length), _cycle_length(0), _cycle_size(-1),
+      _cycle_path(NULL), _local_path(false), _reached(digraph),
+      _dist(digraph), _policy(digraph), _comp(digraph)
+    {}
+
+    /// Destructor.
+    ~MinMeanCycle() {
+      if (_local_path) delete _cycle_path;
+    }
+
+    /// \brief Set the path structure for storing the found cycle.
+    ///
+    /// This function sets an external path structure for storing the
+    /// found cycle.
+    ///
+    /// If you don't call this function before calling \ref run() or
+    /// \ref init(), it will allocate a local \ref Path "path"
+    /// structure. The destuctor deallocates this automatically
+    /// allocated object, of course.
+    ///
+    /// \note The algorithm calls only the \ref lemon::Path::addBack()
+    /// "addBack()" function of the given path structure.
+    ///
+    /// \return <tt>(*this)</tt>
+    ///
+    /// \sa cycle()
+    MinMeanCycle& cyclePath(Path &path) {
+      if (_local_path) {
+        delete _cycle_path;
+        _local_path = false;
+      }
+      _cycle_path = &path;
+      return *this;
+    }
+
+    /// \name Execution control
+    /// The simplest way to execute the algorithm is to call the \ref run()
+    /// function.\n
+    /// If you only need the minimum mean length, you may call \ref init()
+    /// and \ref findMinMean().
+    /// If you would like to run the algorithm again (e.g. the underlying
+    /// digraph and/or the arc lengths has been modified), you may not
+    /// create a new instance of the class, rather call \ref reset(),
+    /// \ref findMinMean() and \ref findCycle() instead.
+
+    /// @{
+
+    /// \brief Run the algorithm.
+    ///
+    /// This function runs the algorithm.
+    ///
+    /// \return \c true if a directed cycle exists in the digraph.
+    ///
+    /// \note Apart from the return value, <tt>mmc.run()</tt> is just a
+    /// shortcut of the following code.
+    /// \code
+    ///   mmc.init();
+    ///   mmc.findMinMean();
+    ///   mmc.findCycle();
+    /// \endcode
+    bool run() {
+      init();
+      return findMinMean() && findCycle();
+    }
+
+    /// \brief Initialize the internal data structures.
+    ///
+    /// This function initializes the internal data structures.
+    ///
+    /// \sa reset()
+    void init() {
+      _tol.epsilon(1e-6);
+      if (!_cycle_path) {
+        _local_path = true;
+        _cycle_path = new Path;
+      }
+      _cycle_found = false;
+      _comp_num = stronglyConnectedComponents(_gr, _comp);
+    }
+
+    /// \brief Reset the internal data structures.
+    ///
+    /// This function resets the internal data structures so that
+    /// findMinMean() and findCycle() can be called again (e.g. when the
+    /// underlying digraph and/or the arc lengths has been modified).
+    ///
+    /// \sa init()
+    void reset() {
+      if (_cycle_path) _cycle_path->clear();
+      _cycle_found = false;
+      _comp_num = stronglyConnectedComponents(_gr, _comp);
+    }
+
+    /// \brief Find the minimum cycle mean.
+    ///
+    /// This function computes all the required data and finds the
+    /// minimum mean length of the directed cycles in the digraph.
+    ///
+    /// \return \c true if a directed cycle exists in the digraph.
+    ///
+    /// \pre \ref init() must be called before using this function.
+    bool findMinMean() {
+      // Find the minimum cycle mean in the components
+      for (int comp = 0; comp < _comp_num; ++comp) {
+        if (!initCurrentComponent(comp)) continue;
+        while (true) {
+          if (!findPolicyCycles()) break;
+          contractPolicyGraph(comp);
+          if (!computeNodeDistances()) break;
+        }
+      }
+      return _cycle_found;
+    }
+
+    /// \brief Find a minimum mean directed cycle.
+    ///
+    /// This function finds a directed cycle of minimum mean length
+    /// in the digraph using the data computed by findMinMean().
+    ///
+    /// \return \c true if a directed cycle exists in the digraph.
+    ///
+    /// \pre \ref init() and \ref findMinMean() must be called before
+    /// using this function.
+    bool findCycle() {
+      if (!_cycle_found) return false;
+      _cycle_path->addBack(_policy[_cycle_node]);
+      for ( Node v = _cycle_node;
+            (v = _gr.target(_policy[v])) != _cycle_node; ) {
+        _cycle_path->addBack(_policy[v]);
+      }
+      return true;
+    }
+
+    /// @}
+
+    /// \name Query Functions
+    /// The result of the algorithm can be obtained using these
+    /// functions.\n
+    /// The algorithm should be executed before using them.
+
+    /// @{
+
+    /// \brief Return the total length of the found cycle.
+    ///
+    /// This function returns the total length of the found cycle.
+    ///
+    /// \pre \ref run() or \ref findCycle() must be called before
+    /// using this function.
+    Value cycleLength() const {
+      return _cycle_length;
+    }
+
+    /// \brief Return the number of arcs on the found cycle.
+    ///
+    /// This function returns the number of arcs on the found cycle.
+    ///
+    /// \pre \ref run() or \ref findCycle() must be called before
+    /// using this function.
+    int cycleArcNum() const {
+      return _cycle_size;
+    }
+
+    /// \brief Return the mean length of the found cycle.
+    ///
+    /// This function returns the mean length of the found cycle.
+    ///
+    /// \note <tt>mmc.cycleMean()</tt> is just a shortcut of the
+    /// following code.
+    /// \code
+    ///   return double(mmc.cycleLength()) / mmc.cycleArcNum();
+    /// \endcode
+    ///
+    /// \pre \ref run() or \ref findMinMean() must be called before
+    /// using this function.
+    double cycleMean() const {
+      return double(_cycle_length) / _cycle_size;



More information about the Lemon-commits mailing list