| alpar@956 |      1 | /* -*- mode: C++; indent-tabs-mode: nil; -*-
 | 
| kpeter@813 |      2 |  *
 | 
| alpar@956 |      3 |  * This file is a part of LEMON, a generic C++ optimization library.
 | 
| kpeter@813 |      4 |  *
 | 
| alpar@1270 |      5 |  * Copyright (C) 2003-2013
 | 
| kpeter@813 |      6 |  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
 | 
| kpeter@813 |      7 |  * (Egervary Research Group on Combinatorial Optimization, EGRES).
 | 
| kpeter@813 |      8 |  *
 | 
| kpeter@813 |      9 |  * Permission to use, modify and distribute this software is granted
 | 
| kpeter@813 |     10 |  * provided that this copyright notice appears in all copies. For
 | 
| kpeter@813 |     11 |  * precise terms see the accompanying LICENSE file.
 | 
| kpeter@813 |     12 |  *
 | 
| kpeter@813 |     13 |  * This software is provided "AS IS" with no warranty of any kind,
 | 
| kpeter@813 |     14 |  * express or implied, and with no claim as to its suitability for any
 | 
| kpeter@813 |     15 |  * purpose.
 | 
| kpeter@813 |     16 |  *
 | 
| kpeter@813 |     17 |  */
 | 
| kpeter@813 |     18 | 
 | 
| kpeter@942 |     19 | #ifndef LEMON_HARTMANN_ORLIN_MMC_H
 | 
| kpeter@942 |     20 | #define LEMON_HARTMANN_ORLIN_MMC_H
 | 
| kpeter@813 |     21 | 
 | 
| kpeter@815 |     22 | /// \ingroup min_mean_cycle
 | 
| kpeter@813 |     23 | ///
 | 
| kpeter@813 |     24 | /// \file
 | 
| kpeter@813 |     25 | /// \brief Hartmann-Orlin's algorithm for finding a minimum mean cycle.
 | 
| kpeter@813 |     26 | 
 | 
| kpeter@813 |     27 | #include <vector>
 | 
| kpeter@813 |     28 | #include <limits>
 | 
| kpeter@813 |     29 | #include <lemon/core.h>
 | 
| kpeter@813 |     30 | #include <lemon/path.h>
 | 
| kpeter@813 |     31 | #include <lemon/tolerance.h>
 | 
| kpeter@813 |     32 | #include <lemon/connectivity.h>
 | 
| kpeter@813 |     33 | 
 | 
| kpeter@813 |     34 | namespace lemon {
 | 
| kpeter@813 |     35 | 
 | 
| kpeter@942 |     36 |   /// \brief Default traits class of HartmannOrlinMmc class.
 | 
| kpeter@813 |     37 |   ///
 | 
| kpeter@942 |     38 |   /// Default traits class of HartmannOrlinMmc class.
 | 
| kpeter@813 |     39 |   /// \tparam GR The type of the digraph.
 | 
| kpeter@942 |     40 |   /// \tparam CM The type of the cost map.
 | 
| kpeter@959 |     41 |   /// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
 | 
| kpeter@813 |     42 | #ifdef DOXYGEN
 | 
| kpeter@942 |     43 |   template <typename GR, typename CM>
 | 
| kpeter@813 |     44 | #else
 | 
| kpeter@942 |     45 |   template <typename GR, typename CM,
 | 
| kpeter@942 |     46 |     bool integer = std::numeric_limits<typename CM::Value>::is_integer>
 | 
| kpeter@813 |     47 | #endif
 | 
| kpeter@942 |     48 |   struct HartmannOrlinMmcDefaultTraits
 | 
| kpeter@813 |     49 |   {
 | 
| kpeter@813 |     50 |     /// The type of the digraph
 | 
| kpeter@813 |     51 |     typedef GR Digraph;
 | 
| kpeter@942 |     52 |     /// The type of the cost map
 | 
| kpeter@942 |     53 |     typedef CM CostMap;
 | 
| kpeter@942 |     54 |     /// The type of the arc costs
 | 
| kpeter@942 |     55 |     typedef typename CostMap::Value Cost;
 | 
| kpeter@813 |     56 | 
 | 
| kpeter@942 |     57 |     /// \brief The large cost type used for internal computations
 | 
| kpeter@813 |     58 |     ///
 | 
| kpeter@942 |     59 |     /// The large cost type used for internal computations.
 | 
| kpeter@942 |     60 |     /// It is \c long \c long if the \c Cost type is integer,
 | 
| kpeter@813 |     61 |     /// otherwise it is \c double.
 | 
| kpeter@942 |     62 |     /// \c Cost must be convertible to \c LargeCost.
 | 
| kpeter@942 |     63 |     typedef double LargeCost;
 | 
| kpeter@813 |     64 | 
 | 
| kpeter@813 |     65 |     /// The tolerance type used for internal computations
 | 
| kpeter@942 |     66 |     typedef lemon::Tolerance<LargeCost> Tolerance;
 | 
| kpeter@813 |     67 | 
 | 
| kpeter@813 |     68 |     /// \brief The path type of the found cycles
 | 
| kpeter@813 |     69 |     ///
 | 
| kpeter@813 |     70 |     /// The path type of the found cycles.
 | 
| kpeter@813 |     71 |     /// It must conform to the \ref lemon::concepts::Path "Path" concept
 | 
| kpeter@819 |     72 |     /// and it must have an \c addFront() function.
 | 
| kpeter@813 |     73 |     typedef lemon::Path<Digraph> Path;
 | 
| kpeter@813 |     74 |   };
 | 
| kpeter@813 |     75 | 
 | 
| kpeter@942 |     76 |   // Default traits class for integer cost types
 | 
| kpeter@942 |     77 |   template <typename GR, typename CM>
 | 
| kpeter@942 |     78 |   struct HartmannOrlinMmcDefaultTraits<GR, CM, true>
 | 
| kpeter@813 |     79 |   {
 | 
| kpeter@813 |     80 |     typedef GR Digraph;
 | 
| kpeter@942 |     81 |     typedef CM CostMap;
 | 
| kpeter@942 |     82 |     typedef typename CostMap::Value Cost;
 | 
| kpeter@813 |     83 | #ifdef LEMON_HAVE_LONG_LONG
 | 
| kpeter@942 |     84 |     typedef long long LargeCost;
 | 
| kpeter@813 |     85 | #else
 | 
| kpeter@942 |     86 |     typedef long LargeCost;
 | 
| kpeter@813 |     87 | #endif
 | 
| kpeter@942 |     88 |     typedef lemon::Tolerance<LargeCost> Tolerance;
 | 
| kpeter@813 |     89 |     typedef lemon::Path<Digraph> Path;
 | 
| kpeter@813 |     90 |   };
 | 
| kpeter@813 |     91 | 
 | 
| kpeter@813 |     92 | 
 | 
| kpeter@815 |     93 |   /// \addtogroup min_mean_cycle
 | 
| kpeter@813 |     94 |   /// @{
 | 
| kpeter@813 |     95 | 
 | 
| kpeter@813 |     96 |   /// \brief Implementation of the Hartmann-Orlin algorithm for finding
 | 
| kpeter@813 |     97 |   /// a minimum mean cycle.
 | 
| kpeter@813 |     98 |   ///
 | 
| kpeter@813 |     99 |   /// This class implements the Hartmann-Orlin algorithm for finding
 | 
| kpeter@942 |    100 |   /// a directed cycle of minimum mean cost in a digraph
 | 
| alpar@1221 |    101 |   /// \cite hartmann93finding, \cite dasdan98minmeancycle.
 | 
| kpeter@1217 |    102 |   /// This method is based on \ref KarpMmc "Karp"'s original algorithm, but
 | 
| kpeter@1217 |    103 |   /// applies an early termination scheme. It makes the algorithm
 | 
| kpeter@1217 |    104 |   /// significantly faster for some problem instances, but slower for others.
 | 
| kpeter@1254 |    105 |   /// The algorithm runs in time O(nm) and uses space O(n<sup>2</sup>+m).
 | 
| kpeter@813 |    106 |   ///
 | 
| kpeter@813 |    107 |   /// \tparam GR The type of the digraph the algorithm runs on.
 | 
| kpeter@942 |    108 |   /// \tparam CM The type of the cost map. The default
 | 
| kpeter@813 |    109 |   /// map type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
 | 
| kpeter@891 |    110 |   /// \tparam TR The traits class that defines various types used by the
 | 
| kpeter@942 |    111 |   /// algorithm. By default, it is \ref HartmannOrlinMmcDefaultTraits
 | 
| kpeter@942 |    112 |   /// "HartmannOrlinMmcDefaultTraits<GR, CM>".
 | 
| kpeter@891 |    113 |   /// In most cases, this parameter should not be set directly,
 | 
| kpeter@891 |    114 |   /// consider to use the named template parameters instead.
 | 
| kpeter@813 |    115 | #ifdef DOXYGEN
 | 
| kpeter@942 |    116 |   template <typename GR, typename CM, typename TR>
 | 
| kpeter@813 |    117 | #else
 | 
| kpeter@813 |    118 |   template < typename GR,
 | 
| kpeter@942 |    119 |              typename CM = typename GR::template ArcMap<int>,
 | 
| kpeter@942 |    120 |              typename TR = HartmannOrlinMmcDefaultTraits<GR, CM> >
 | 
| kpeter@813 |    121 | #endif
 | 
| kpeter@942 |    122 |   class HartmannOrlinMmc
 | 
| kpeter@813 |    123 |   {
 | 
| kpeter@813 |    124 |   public:
 | 
| kpeter@813 |    125 | 
 | 
| kpeter@813 |    126 |     /// The type of the digraph
 | 
| kpeter@813 |    127 |     typedef typename TR::Digraph Digraph;
 | 
| kpeter@942 |    128 |     /// The type of the cost map
 | 
| kpeter@942 |    129 |     typedef typename TR::CostMap CostMap;
 | 
| kpeter@942 |    130 |     /// The type of the arc costs
 | 
| kpeter@942 |    131 |     typedef typename TR::Cost Cost;
 | 
| kpeter@813 |    132 | 
 | 
| kpeter@942 |    133 |     /// \brief The large cost type
 | 
| kpeter@813 |    134 |     ///
 | 
| kpeter@942 |    135 |     /// The large cost type used for internal computations.
 | 
| kpeter@942 |    136 |     /// By default, it is \c long \c long if the \c Cost type is integer,
 | 
| kpeter@813 |    137 |     /// otherwise it is \c double.
 | 
| kpeter@942 |    138 |     typedef typename TR::LargeCost LargeCost;
 | 
| kpeter@813 |    139 | 
 | 
| kpeter@813 |    140 |     /// The tolerance type
 | 
| kpeter@813 |    141 |     typedef typename TR::Tolerance Tolerance;
 | 
| kpeter@813 |    142 | 
 | 
| kpeter@813 |    143 |     /// \brief The path type of the found cycles
 | 
| kpeter@813 |    144 |     ///
 | 
| kpeter@813 |    145 |     /// The path type of the found cycles.
 | 
| alpar@1250 |    146 |     /// Using the \ref lemon::HartmannOrlinMmcDefaultTraits
 | 
| alpar@1250 |    147 |     /// "default traits class",
 | 
| kpeter@813 |    148 |     /// it is \ref lemon::Path "Path<Digraph>".
 | 
| kpeter@813 |    149 |     typedef typename TR::Path Path;
 | 
| kpeter@813 |    150 | 
 | 
| alpar@1250 |    151 |     /// \brief The
 | 
| alpar@1250 |    152 |     /// \ref lemon::HartmannOrlinMmcDefaultTraits "traits class"
 | 
| alpar@1250 |    153 |     /// of the algorithm
 | 
| kpeter@813 |    154 |     typedef TR Traits;
 | 
| kpeter@813 |    155 | 
 | 
| kpeter@813 |    156 |   private:
 | 
| kpeter@813 |    157 | 
 | 
| kpeter@813 |    158 |     TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
 | 
| kpeter@813 |    159 | 
 | 
| kpeter@813 |    160 |     // Data sturcture for path data
 | 
| kpeter@813 |    161 |     struct PathData
 | 
| kpeter@813 |    162 |     {
 | 
| kpeter@942 |    163 |       LargeCost dist;
 | 
| kpeter@813 |    164 |       Arc pred;
 | 
| kpeter@942 |    165 |       PathData(LargeCost d, Arc p = INVALID) :
 | 
| kpeter@814 |    166 |         dist(d), pred(p) {}
 | 
| kpeter@813 |    167 |     };
 | 
| kpeter@813 |    168 | 
 | 
| kpeter@813 |    169 |     typedef typename Digraph::template NodeMap<std::vector<PathData> >
 | 
| kpeter@813 |    170 |       PathDataNodeMap;
 | 
| kpeter@813 |    171 | 
 | 
| kpeter@813 |    172 |   private:
 | 
| kpeter@813 |    173 | 
 | 
| kpeter@813 |    174 |     // The digraph the algorithm runs on
 | 
| kpeter@813 |    175 |     const Digraph &_gr;
 | 
| kpeter@942 |    176 |     // The cost of the arcs
 | 
| kpeter@942 |    177 |     const CostMap &_cost;
 | 
| kpeter@813 |    178 | 
 | 
| kpeter@813 |    179 |     // Data for storing the strongly connected components
 | 
| kpeter@813 |    180 |     int _comp_num;
 | 
| kpeter@813 |    181 |     typename Digraph::template NodeMap<int> _comp;
 | 
| kpeter@813 |    182 |     std::vector<std::vector<Node> > _comp_nodes;
 | 
| kpeter@813 |    183 |     std::vector<Node>* _nodes;
 | 
| kpeter@813 |    184 |     typename Digraph::template NodeMap<std::vector<Arc> > _out_arcs;
 | 
| kpeter@813 |    185 | 
 | 
| kpeter@813 |    186 |     // Data for the found cycles
 | 
| kpeter@813 |    187 |     bool _curr_found, _best_found;
 | 
| kpeter@942 |    188 |     LargeCost _curr_cost, _best_cost;
 | 
| kpeter@813 |    189 |     int _curr_size, _best_size;
 | 
| kpeter@813 |    190 |     Node _curr_node, _best_node;
 | 
| kpeter@813 |    191 |     int _curr_level, _best_level;
 | 
| kpeter@813 |    192 | 
 | 
| kpeter@813 |    193 |     Path *_cycle_path;
 | 
| kpeter@813 |    194 |     bool _local_path;
 | 
| kpeter@813 |    195 | 
 | 
| kpeter@813 |    196 |     // Node map for storing path data
 | 
| kpeter@813 |    197 |     PathDataNodeMap _data;
 | 
| kpeter@813 |    198 |     // The processed nodes in the last round
 | 
| kpeter@813 |    199 |     std::vector<Node> _process;
 | 
| kpeter@813 |    200 | 
 | 
| kpeter@813 |    201 |     Tolerance _tolerance;
 | 
| kpeter@813 |    202 | 
 | 
| kpeter@814 |    203 |     // Infinite constant
 | 
| kpeter@942 |    204 |     const LargeCost INF;
 | 
| kpeter@814 |    205 | 
 | 
| kpeter@813 |    206 |   public:
 | 
| kpeter@813 |    207 | 
 | 
| kpeter@813 |    208 |     /// \name Named Template Parameters
 | 
| kpeter@813 |    209 |     /// @{
 | 
| kpeter@813 |    210 | 
 | 
| kpeter@813 |    211 |     template <typename T>
 | 
| kpeter@942 |    212 |     struct SetLargeCostTraits : public Traits {
 | 
| kpeter@942 |    213 |       typedef T LargeCost;
 | 
| kpeter@813 |    214 |       typedef lemon::Tolerance<T> Tolerance;
 | 
| kpeter@813 |    215 |     };
 | 
| kpeter@813 |    216 | 
 | 
| kpeter@813 |    217 |     /// \brief \ref named-templ-param "Named parameter" for setting
 | 
| kpeter@942 |    218 |     /// \c LargeCost type.
 | 
| kpeter@813 |    219 |     ///
 | 
| kpeter@942 |    220 |     /// \ref named-templ-param "Named parameter" for setting \c LargeCost
 | 
| kpeter@813 |    221 |     /// type. It is used for internal computations in the algorithm.
 | 
| kpeter@813 |    222 |     template <typename T>
 | 
| kpeter@942 |    223 |     struct SetLargeCost
 | 
| kpeter@942 |    224 |       : public HartmannOrlinMmc<GR, CM, SetLargeCostTraits<T> > {
 | 
| kpeter@942 |    225 |       typedef HartmannOrlinMmc<GR, CM, SetLargeCostTraits<T> > Create;
 | 
| kpeter@813 |    226 |     };
 | 
| kpeter@813 |    227 | 
 | 
| kpeter@813 |    228 |     template <typename T>
 | 
| kpeter@813 |    229 |     struct SetPathTraits : public Traits {
 | 
| kpeter@813 |    230 |       typedef T Path;
 | 
| kpeter@813 |    231 |     };
 | 
| kpeter@813 |    232 | 
 | 
| kpeter@813 |    233 |     /// \brief \ref named-templ-param "Named parameter" for setting
 | 
| kpeter@813 |    234 |     /// \c %Path type.
 | 
| kpeter@813 |    235 |     ///
 | 
| kpeter@813 |    236 |     /// \ref named-templ-param "Named parameter" for setting the \c %Path
 | 
| kpeter@813 |    237 |     /// type of the found cycles.
 | 
| kpeter@813 |    238 |     /// It must conform to the \ref lemon::concepts::Path "Path" concept
 | 
| kpeter@813 |    239 |     /// and it must have an \c addFront() function.
 | 
| kpeter@813 |    240 |     template <typename T>
 | 
| kpeter@813 |    241 |     struct SetPath
 | 
| kpeter@942 |    242 |       : public HartmannOrlinMmc<GR, CM, SetPathTraits<T> > {
 | 
| kpeter@942 |    243 |       typedef HartmannOrlinMmc<GR, CM, SetPathTraits<T> > Create;
 | 
| kpeter@813 |    244 |     };
 | 
| kpeter@813 |    245 | 
 | 
| kpeter@813 |    246 |     /// @}
 | 
| kpeter@813 |    247 | 
 | 
| kpeter@941 |    248 |   protected:
 | 
| kpeter@941 |    249 | 
 | 
| kpeter@942 |    250 |     HartmannOrlinMmc() {}
 | 
| kpeter@941 |    251 | 
 | 
| kpeter@813 |    252 |   public:
 | 
| kpeter@813 |    253 | 
 | 
| kpeter@813 |    254 |     /// \brief Constructor.
 | 
| kpeter@813 |    255 |     ///
 | 
| kpeter@813 |    256 |     /// The constructor of the class.
 | 
| kpeter@813 |    257 |     ///
 | 
| kpeter@813 |    258 |     /// \param digraph The digraph the algorithm runs on.
 | 
| kpeter@942 |    259 |     /// \param cost The costs of the arcs.
 | 
| kpeter@942 |    260 |     HartmannOrlinMmc( const Digraph &digraph,
 | 
| kpeter@942 |    261 |                       const CostMap &cost ) :
 | 
| kpeter@942 |    262 |       _gr(digraph), _cost(cost), _comp(digraph), _out_arcs(digraph),
 | 
| kpeter@942 |    263 |       _best_found(false), _best_cost(0), _best_size(1),
 | 
| kpeter@814 |    264 |       _cycle_path(NULL), _local_path(false), _data(digraph),
 | 
| kpeter@942 |    265 |       INF(std::numeric_limits<LargeCost>::has_infinity ?
 | 
| kpeter@942 |    266 |           std::numeric_limits<LargeCost>::infinity() :
 | 
| kpeter@942 |    267 |           std::numeric_limits<LargeCost>::max())
 | 
| kpeter@813 |    268 |     {}
 | 
| kpeter@813 |    269 | 
 | 
| kpeter@813 |    270 |     /// Destructor.
 | 
| kpeter@942 |    271 |     ~HartmannOrlinMmc() {
 | 
| kpeter@813 |    272 |       if (_local_path) delete _cycle_path;
 | 
| kpeter@813 |    273 |     }
 | 
| kpeter@813 |    274 | 
 | 
| kpeter@813 |    275 |     /// \brief Set the path structure for storing the found cycle.
 | 
| kpeter@813 |    276 |     ///
 | 
| kpeter@813 |    277 |     /// This function sets an external path structure for storing the
 | 
| kpeter@813 |    278 |     /// found cycle.
 | 
| kpeter@813 |    279 |     ///
 | 
| kpeter@813 |    280 |     /// If you don't call this function before calling \ref run() or
 | 
| kpeter@1217 |    281 |     /// \ref findCycleMean(), a local \ref Path "path" structure
 | 
| kpeter@1217 |    282 |     /// will be allocated. The destuctor deallocates this automatically
 | 
| kpeter@813 |    283 |     /// allocated object, of course.
 | 
| kpeter@813 |    284 |     ///
 | 
| kpeter@813 |    285 |     /// \note The algorithm calls only the \ref lemon::Path::addFront()
 | 
| kpeter@813 |    286 |     /// "addFront()" function of the given path structure.
 | 
| kpeter@813 |    287 |     ///
 | 
| kpeter@813 |    288 |     /// \return <tt>(*this)</tt>
 | 
| kpeter@942 |    289 |     HartmannOrlinMmc& cycle(Path &path) {
 | 
| kpeter@813 |    290 |       if (_local_path) {
 | 
| kpeter@813 |    291 |         delete _cycle_path;
 | 
| kpeter@813 |    292 |         _local_path = false;
 | 
| kpeter@813 |    293 |       }
 | 
| kpeter@813 |    294 |       _cycle_path = &path;
 | 
| kpeter@813 |    295 |       return *this;
 | 
| kpeter@813 |    296 |     }
 | 
| kpeter@813 |    297 | 
 | 
| kpeter@816 |    298 |     /// \brief Set the tolerance used by the algorithm.
 | 
| kpeter@816 |    299 |     ///
 | 
| kpeter@816 |    300 |     /// This function sets the tolerance object used by the algorithm.
 | 
| kpeter@816 |    301 |     ///
 | 
| kpeter@816 |    302 |     /// \return <tt>(*this)</tt>
 | 
| kpeter@942 |    303 |     HartmannOrlinMmc& tolerance(const Tolerance& tolerance) {
 | 
| kpeter@816 |    304 |       _tolerance = tolerance;
 | 
| kpeter@816 |    305 |       return *this;
 | 
| kpeter@816 |    306 |     }
 | 
| kpeter@816 |    307 | 
 | 
| kpeter@816 |    308 |     /// \brief Return a const reference to the tolerance.
 | 
| kpeter@816 |    309 |     ///
 | 
| kpeter@816 |    310 |     /// This function returns a const reference to the tolerance object
 | 
| kpeter@816 |    311 |     /// used by the algorithm.
 | 
| kpeter@816 |    312 |     const Tolerance& tolerance() const {
 | 
| kpeter@816 |    313 |       return _tolerance;
 | 
| kpeter@816 |    314 |     }
 | 
| kpeter@816 |    315 | 
 | 
| kpeter@813 |    316 |     /// \name Execution control
 | 
| kpeter@813 |    317 |     /// The simplest way to execute the algorithm is to call the \ref run()
 | 
| kpeter@813 |    318 |     /// function.\n
 | 
| kpeter@942 |    319 |     /// If you only need the minimum mean cost, you may call
 | 
| kpeter@942 |    320 |     /// \ref findCycleMean().
 | 
| kpeter@813 |    321 | 
 | 
| kpeter@813 |    322 |     /// @{
 | 
| kpeter@813 |    323 | 
 | 
| kpeter@813 |    324 |     /// \brief Run the algorithm.
 | 
| kpeter@813 |    325 |     ///
 | 
| kpeter@813 |    326 |     /// This function runs the algorithm.
 | 
| kpeter@813 |    327 |     /// It can be called more than once (e.g. if the underlying digraph
 | 
| kpeter@942 |    328 |     /// and/or the arc costs have been modified).
 | 
| kpeter@813 |    329 |     ///
 | 
| kpeter@813 |    330 |     /// \return \c true if a directed cycle exists in the digraph.
 | 
| kpeter@813 |    331 |     ///
 | 
| kpeter@813 |    332 |     /// \note <tt>mmc.run()</tt> is just a shortcut of the following code.
 | 
| kpeter@813 |    333 |     /// \code
 | 
| kpeter@942 |    334 |     ///   return mmc.findCycleMean() && mmc.findCycle();
 | 
| kpeter@813 |    335 |     /// \endcode
 | 
| kpeter@813 |    336 |     bool run() {
 | 
| kpeter@942 |    337 |       return findCycleMean() && findCycle();
 | 
| kpeter@813 |    338 |     }
 | 
| kpeter@813 |    339 | 
 | 
| kpeter@813 |    340 |     /// \brief Find the minimum cycle mean.
 | 
| kpeter@813 |    341 |     ///
 | 
| kpeter@942 |    342 |     /// This function finds the minimum mean cost of the directed
 | 
| kpeter@813 |    343 |     /// cycles in the digraph.
 | 
| kpeter@813 |    344 |     ///
 | 
| kpeter@813 |    345 |     /// \return \c true if a directed cycle exists in the digraph.
 | 
| kpeter@942 |    346 |     bool findCycleMean() {
 | 
| kpeter@813 |    347 |       // Initialization and find strongly connected components
 | 
| kpeter@813 |    348 |       init();
 | 
| kpeter@813 |    349 |       findComponents();
 | 
| alpar@956 |    350 | 
 | 
| kpeter@813 |    351 |       // Find the minimum cycle mean in the components
 | 
| kpeter@813 |    352 |       for (int comp = 0; comp < _comp_num; ++comp) {
 | 
| kpeter@813 |    353 |         if (!initComponent(comp)) continue;
 | 
| kpeter@813 |    354 |         processRounds();
 | 
| alpar@956 |    355 | 
 | 
| kpeter@813 |    356 |         // Update the best cycle (global minimum mean cycle)
 | 
| alpar@956 |    357 |         if ( _curr_found && (!_best_found ||
 | 
| kpeter@942 |    358 |              _curr_cost * _best_size < _best_cost * _curr_size) ) {
 | 
| kpeter@813 |    359 |           _best_found = true;
 | 
| kpeter@942 |    360 |           _best_cost = _curr_cost;
 | 
| kpeter@813 |    361 |           _best_size = _curr_size;
 | 
| kpeter@813 |    362 |           _best_node = _curr_node;
 | 
| kpeter@813 |    363 |           _best_level = _curr_level;
 | 
| kpeter@813 |    364 |         }
 | 
| kpeter@813 |    365 |       }
 | 
| kpeter@813 |    366 |       return _best_found;
 | 
| kpeter@813 |    367 |     }
 | 
| kpeter@813 |    368 | 
 | 
| kpeter@813 |    369 |     /// \brief Find a minimum mean directed cycle.
 | 
| kpeter@813 |    370 |     ///
 | 
| kpeter@942 |    371 |     /// This function finds a directed cycle of minimum mean cost
 | 
| kpeter@942 |    372 |     /// in the digraph using the data computed by findCycleMean().
 | 
| kpeter@813 |    373 |     ///
 | 
| kpeter@813 |    374 |     /// \return \c true if a directed cycle exists in the digraph.
 | 
| kpeter@813 |    375 |     ///
 | 
| kpeter@942 |    376 |     /// \pre \ref findCycleMean() must be called before using this function.
 | 
| kpeter@813 |    377 |     bool findCycle() {
 | 
| kpeter@813 |    378 |       if (!_best_found) return false;
 | 
| kpeter@813 |    379 |       IntNodeMap reached(_gr, -1);
 | 
| kpeter@813 |    380 |       int r = _best_level + 1;
 | 
| kpeter@813 |    381 |       Node u = _best_node;
 | 
| kpeter@813 |    382 |       while (reached[u] < 0) {
 | 
| kpeter@813 |    383 |         reached[u] = --r;
 | 
| kpeter@813 |    384 |         u = _gr.source(_data[u][r].pred);
 | 
| kpeter@813 |    385 |       }
 | 
| kpeter@813 |    386 |       r = reached[u];
 | 
| kpeter@813 |    387 |       Arc e = _data[u][r].pred;
 | 
| kpeter@813 |    388 |       _cycle_path->addFront(e);
 | 
| kpeter@942 |    389 |       _best_cost = _cost[e];
 | 
| kpeter@813 |    390 |       _best_size = 1;
 | 
| kpeter@813 |    391 |       Node v;
 | 
| kpeter@813 |    392 |       while ((v = _gr.source(e)) != u) {
 | 
| kpeter@813 |    393 |         e = _data[v][--r].pred;
 | 
| kpeter@813 |    394 |         _cycle_path->addFront(e);
 | 
| kpeter@942 |    395 |         _best_cost += _cost[e];
 | 
| kpeter@813 |    396 |         ++_best_size;
 | 
| kpeter@813 |    397 |       }
 | 
| kpeter@813 |    398 |       return true;
 | 
| kpeter@813 |    399 |     }
 | 
| kpeter@813 |    400 | 
 | 
| kpeter@813 |    401 |     /// @}
 | 
| kpeter@813 |    402 | 
 | 
| kpeter@813 |    403 |     /// \name Query Functions
 | 
| kpeter@813 |    404 |     /// The results of the algorithm can be obtained using these
 | 
| kpeter@813 |    405 |     /// functions.\n
 | 
| kpeter@813 |    406 |     /// The algorithm should be executed before using them.
 | 
| kpeter@813 |    407 | 
 | 
| kpeter@813 |    408 |     /// @{
 | 
| kpeter@813 |    409 | 
 | 
| kpeter@942 |    410 |     /// \brief Return the total cost of the found cycle.
 | 
| kpeter@813 |    411 |     ///
 | 
| kpeter@942 |    412 |     /// This function returns the total cost of the found cycle.
 | 
| kpeter@813 |    413 |     ///
 | 
| kpeter@942 |    414 |     /// \pre \ref run() or \ref findCycleMean() must be called before
 | 
| kpeter@813 |    415 |     /// using this function.
 | 
| kpeter@942 |    416 |     Cost cycleCost() const {
 | 
| kpeter@942 |    417 |       return static_cast<Cost>(_best_cost);
 | 
| kpeter@813 |    418 |     }
 | 
| kpeter@813 |    419 | 
 | 
| kpeter@813 |    420 |     /// \brief Return the number of arcs on the found cycle.
 | 
| kpeter@813 |    421 |     ///
 | 
| kpeter@813 |    422 |     /// This function returns the number of arcs on the found cycle.
 | 
| kpeter@813 |    423 |     ///
 | 
| kpeter@942 |    424 |     /// \pre \ref run() or \ref findCycleMean() must be called before
 | 
| kpeter@813 |    425 |     /// using this function.
 | 
| kpeter@942 |    426 |     int cycleSize() const {
 | 
| kpeter@813 |    427 |       return _best_size;
 | 
| kpeter@813 |    428 |     }
 | 
| kpeter@813 |    429 | 
 | 
| kpeter@942 |    430 |     /// \brief Return the mean cost of the found cycle.
 | 
| kpeter@813 |    431 |     ///
 | 
| kpeter@942 |    432 |     /// This function returns the mean cost of the found cycle.
 | 
| kpeter@813 |    433 |     ///
 | 
| kpeter@813 |    434 |     /// \note <tt>alg.cycleMean()</tt> is just a shortcut of the
 | 
| kpeter@813 |    435 |     /// following code.
 | 
| kpeter@813 |    436 |     /// \code
 | 
| kpeter@942 |    437 |     ///   return static_cast<double>(alg.cycleCost()) / alg.cycleSize();
 | 
| kpeter@813 |    438 |     /// \endcode
 | 
| kpeter@813 |    439 |     ///
 | 
| kpeter@942 |    440 |     /// \pre \ref run() or \ref findCycleMean() must be called before
 | 
| kpeter@813 |    441 |     /// using this function.
 | 
| kpeter@813 |    442 |     double cycleMean() const {
 | 
| kpeter@942 |    443 |       return static_cast<double>(_best_cost) / _best_size;
 | 
| kpeter@813 |    444 |     }
 | 
| kpeter@813 |    445 | 
 | 
| kpeter@813 |    446 |     /// \brief Return the found cycle.
 | 
| kpeter@813 |    447 |     ///
 | 
| kpeter@813 |    448 |     /// This function returns a const reference to the path structure
 | 
| kpeter@813 |    449 |     /// storing the found cycle.
 | 
| kpeter@813 |    450 |     ///
 | 
| kpeter@813 |    451 |     /// \pre \ref run() or \ref findCycle() must be called before using
 | 
| kpeter@813 |    452 |     /// this function.
 | 
| kpeter@813 |    453 |     const Path& cycle() const {
 | 
| kpeter@813 |    454 |       return *_cycle_path;
 | 
| kpeter@813 |    455 |     }
 | 
| kpeter@813 |    456 | 
 | 
| kpeter@813 |    457 |     ///@}
 | 
| kpeter@813 |    458 | 
 | 
| kpeter@813 |    459 |   private:
 | 
| kpeter@813 |    460 | 
 | 
| kpeter@813 |    461 |     // Initialization
 | 
| kpeter@813 |    462 |     void init() {
 | 
| kpeter@813 |    463 |       if (!_cycle_path) {
 | 
| kpeter@813 |    464 |         _local_path = true;
 | 
| kpeter@813 |    465 |         _cycle_path = new Path;
 | 
| kpeter@813 |    466 |       }
 | 
| kpeter@813 |    467 |       _cycle_path->clear();
 | 
| kpeter@813 |    468 |       _best_found = false;
 | 
| kpeter@942 |    469 |       _best_cost = 0;
 | 
| kpeter@813 |    470 |       _best_size = 1;
 | 
| kpeter@813 |    471 |       _cycle_path->clear();
 | 
| kpeter@813 |    472 |       for (NodeIt u(_gr); u != INVALID; ++u)
 | 
| kpeter@813 |    473 |         _data[u].clear();
 | 
| kpeter@813 |    474 |     }
 | 
| kpeter@813 |    475 | 
 | 
| kpeter@813 |    476 |     // Find strongly connected components and initialize _comp_nodes
 | 
| kpeter@813 |    477 |     // and _out_arcs
 | 
| kpeter@813 |    478 |     void findComponents() {
 | 
| kpeter@813 |    479 |       _comp_num = stronglyConnectedComponents(_gr, _comp);
 | 
| kpeter@813 |    480 |       _comp_nodes.resize(_comp_num);
 | 
| kpeter@813 |    481 |       if (_comp_num == 1) {
 | 
| kpeter@813 |    482 |         _comp_nodes[0].clear();
 | 
| kpeter@813 |    483 |         for (NodeIt n(_gr); n != INVALID; ++n) {
 | 
| kpeter@813 |    484 |           _comp_nodes[0].push_back(n);
 | 
| kpeter@813 |    485 |           _out_arcs[n].clear();
 | 
| kpeter@813 |    486 |           for (OutArcIt a(_gr, n); a != INVALID; ++a) {
 | 
| kpeter@813 |    487 |             _out_arcs[n].push_back(a);
 | 
| kpeter@813 |    488 |           }
 | 
| kpeter@813 |    489 |         }
 | 
| kpeter@813 |    490 |       } else {
 | 
| kpeter@813 |    491 |         for (int i = 0; i < _comp_num; ++i)
 | 
| kpeter@813 |    492 |           _comp_nodes[i].clear();
 | 
| kpeter@813 |    493 |         for (NodeIt n(_gr); n != INVALID; ++n) {
 | 
| kpeter@813 |    494 |           int k = _comp[n];
 | 
| kpeter@813 |    495 |           _comp_nodes[k].push_back(n);
 | 
| kpeter@813 |    496 |           _out_arcs[n].clear();
 | 
| kpeter@813 |    497 |           for (OutArcIt a(_gr, n); a != INVALID; ++a) {
 | 
| kpeter@813 |    498 |             if (_comp[_gr.target(a)] == k) _out_arcs[n].push_back(a);
 | 
| kpeter@813 |    499 |           }
 | 
| kpeter@813 |    500 |         }
 | 
| kpeter@813 |    501 |       }
 | 
| kpeter@813 |    502 |     }
 | 
| kpeter@813 |    503 | 
 | 
| kpeter@813 |    504 |     // Initialize path data for the current component
 | 
| kpeter@813 |    505 |     bool initComponent(int comp) {
 | 
| kpeter@813 |    506 |       _nodes = &(_comp_nodes[comp]);
 | 
| kpeter@813 |    507 |       int n = _nodes->size();
 | 
| kpeter@813 |    508 |       if (n < 1 || (n == 1 && _out_arcs[(*_nodes)[0]].size() == 0)) {
 | 
| kpeter@813 |    509 |         return false;
 | 
| alpar@956 |    510 |       }
 | 
| kpeter@813 |    511 |       for (int i = 0; i < n; ++i) {
 | 
| kpeter@814 |    512 |         _data[(*_nodes)[i]].resize(n + 1, PathData(INF));
 | 
| kpeter@813 |    513 |       }
 | 
| kpeter@813 |    514 |       return true;
 | 
| kpeter@813 |    515 |     }
 | 
| kpeter@813 |    516 | 
 | 
| kpeter@813 |    517 |     // Process all rounds of computing path data for the current component.
 | 
| kpeter@942 |    518 |     // _data[v][k] is the cost of a shortest directed walk from the root
 | 
| kpeter@813 |    519 |     // node to node v containing exactly k arcs.
 | 
| kpeter@813 |    520 |     void processRounds() {
 | 
| kpeter@813 |    521 |       Node start = (*_nodes)[0];
 | 
| kpeter@814 |    522 |       _data[start][0] = PathData(0);
 | 
| kpeter@813 |    523 |       _process.clear();
 | 
| kpeter@813 |    524 |       _process.push_back(start);
 | 
| kpeter@813 |    525 | 
 | 
| kpeter@813 |    526 |       int k, n = _nodes->size();
 | 
| kpeter@813 |    527 |       int next_check = 4;
 | 
| kpeter@813 |    528 |       bool terminate = false;
 | 
| kpeter@813 |    529 |       for (k = 1; k <= n && int(_process.size()) < n && !terminate; ++k) {
 | 
| kpeter@813 |    530 |         processNextBuildRound(k);
 | 
| kpeter@813 |    531 |         if (k == next_check || k == n) {
 | 
| kpeter@813 |    532 |           terminate = checkTermination(k);
 | 
| kpeter@813 |    533 |           next_check = next_check * 3 / 2;
 | 
| kpeter@813 |    534 |         }
 | 
| kpeter@813 |    535 |       }
 | 
| kpeter@813 |    536 |       for ( ; k <= n && !terminate; ++k) {
 | 
| kpeter@813 |    537 |         processNextFullRound(k);
 | 
| kpeter@813 |    538 |         if (k == next_check || k == n) {
 | 
| kpeter@813 |    539 |           terminate = checkTermination(k);
 | 
| kpeter@813 |    540 |           next_check = next_check * 3 / 2;
 | 
| kpeter@813 |    541 |         }
 | 
| kpeter@813 |    542 |       }
 | 
| kpeter@813 |    543 |     }
 | 
| kpeter@813 |    544 | 
 | 
| kpeter@813 |    545 |     // Process one round and rebuild _process
 | 
| kpeter@813 |    546 |     void processNextBuildRound(int k) {
 | 
| kpeter@813 |    547 |       std::vector<Node> next;
 | 
| kpeter@813 |    548 |       Node u, v;
 | 
| kpeter@813 |    549 |       Arc e;
 | 
| kpeter@942 |    550 |       LargeCost d;
 | 
| kpeter@813 |    551 |       for (int i = 0; i < int(_process.size()); ++i) {
 | 
| kpeter@813 |    552 |         u = _process[i];
 | 
| kpeter@813 |    553 |         for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
 | 
| kpeter@813 |    554 |           e = _out_arcs[u][j];
 | 
| kpeter@813 |    555 |           v = _gr.target(e);
 | 
| kpeter@942 |    556 |           d = _data[u][k-1].dist + _cost[e];
 | 
| kpeter@814 |    557 |           if (_tolerance.less(d, _data[v][k].dist)) {
 | 
| kpeter@814 |    558 |             if (_data[v][k].dist == INF) next.push_back(v);
 | 
| kpeter@814 |    559 |             _data[v][k] = PathData(d, e);
 | 
| kpeter@813 |    560 |           }
 | 
| kpeter@813 |    561 |         }
 | 
| kpeter@813 |    562 |       }
 | 
| kpeter@813 |    563 |       _process.swap(next);
 | 
| kpeter@813 |    564 |     }
 | 
| kpeter@813 |    565 | 
 | 
| kpeter@813 |    566 |     // Process one round using _nodes instead of _process
 | 
| kpeter@813 |    567 |     void processNextFullRound(int k) {
 | 
| kpeter@813 |    568 |       Node u, v;
 | 
| kpeter@813 |    569 |       Arc e;
 | 
| kpeter@942 |    570 |       LargeCost d;
 | 
| kpeter@813 |    571 |       for (int i = 0; i < int(_nodes->size()); ++i) {
 | 
| kpeter@813 |    572 |         u = (*_nodes)[i];
 | 
| kpeter@813 |    573 |         for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
 | 
| kpeter@813 |    574 |           e = _out_arcs[u][j];
 | 
| kpeter@813 |    575 |           v = _gr.target(e);
 | 
| kpeter@942 |    576 |           d = _data[u][k-1].dist + _cost[e];
 | 
| kpeter@814 |    577 |           if (_tolerance.less(d, _data[v][k].dist)) {
 | 
| kpeter@814 |    578 |             _data[v][k] = PathData(d, e);
 | 
| kpeter@813 |    579 |           }
 | 
| kpeter@813 |    580 |         }
 | 
| kpeter@813 |    581 |       }
 | 
| kpeter@813 |    582 |     }
 | 
| alpar@956 |    583 | 
 | 
| kpeter@813 |    584 |     // Check early termination
 | 
| kpeter@813 |    585 |     bool checkTermination(int k) {
 | 
| kpeter@813 |    586 |       typedef std::pair<int, int> Pair;
 | 
| kpeter@813 |    587 |       typename GR::template NodeMap<Pair> level(_gr, Pair(-1, 0));
 | 
| kpeter@942 |    588 |       typename GR::template NodeMap<LargeCost> pi(_gr);
 | 
| kpeter@813 |    589 |       int n = _nodes->size();
 | 
| kpeter@942 |    590 |       LargeCost cost;
 | 
| kpeter@813 |    591 |       int size;
 | 
| kpeter@813 |    592 |       Node u;
 | 
| alpar@956 |    593 | 
 | 
| kpeter@813 |    594 |       // Search for cycles that are already found
 | 
| kpeter@813 |    595 |       _curr_found = false;
 | 
| kpeter@813 |    596 |       for (int i = 0; i < n; ++i) {
 | 
| kpeter@813 |    597 |         u = (*_nodes)[i];
 | 
| kpeter@814 |    598 |         if (_data[u][k].dist == INF) continue;
 | 
| kpeter@813 |    599 |         for (int j = k; j >= 0; --j) {
 | 
| kpeter@813 |    600 |           if (level[u].first == i && level[u].second > 0) {
 | 
| kpeter@813 |    601 |             // A cycle is found
 | 
| kpeter@942 |    602 |             cost = _data[u][level[u].second].dist - _data[u][j].dist;
 | 
| kpeter@813 |    603 |             size = level[u].second - j;
 | 
| kpeter@942 |    604 |             if (!_curr_found || cost * _curr_size < _curr_cost * size) {
 | 
| kpeter@942 |    605 |               _curr_cost = cost;
 | 
| kpeter@813 |    606 |               _curr_size = size;
 | 
| kpeter@813 |    607 |               _curr_node = u;
 | 
| kpeter@813 |    608 |               _curr_level = level[u].second;
 | 
| kpeter@813 |    609 |               _curr_found = true;
 | 
| kpeter@813 |    610 |             }
 | 
| kpeter@813 |    611 |           }
 | 
| kpeter@813 |    612 |           level[u] = Pair(i, j);
 | 
| deba@859 |    613 |           if (j != 0) {
 | 
| alpar@956 |    614 |             u = _gr.source(_data[u][j].pred);
 | 
| alpar@956 |    615 |           }
 | 
| kpeter@813 |    616 |         }
 | 
| kpeter@813 |    617 |       }
 | 
| kpeter@813 |    618 | 
 | 
| kpeter@813 |    619 |       // If at least one cycle is found, check the optimality condition
 | 
| kpeter@942 |    620 |       LargeCost d;
 | 
| kpeter@813 |    621 |       if (_curr_found && k < n) {
 | 
| kpeter@813 |    622 |         // Find node potentials
 | 
| kpeter@813 |    623 |         for (int i = 0; i < n; ++i) {
 | 
| kpeter@813 |    624 |           u = (*_nodes)[i];
 | 
| kpeter@814 |    625 |           pi[u] = INF;
 | 
| kpeter@813 |    626 |           for (int j = 0; j <= k; ++j) {
 | 
| kpeter@814 |    627 |             if (_data[u][j].dist < INF) {
 | 
| kpeter@942 |    628 |               d = _data[u][j].dist * _curr_size - j * _curr_cost;
 | 
| kpeter@814 |    629 |               if (_tolerance.less(d, pi[u])) pi[u] = d;
 | 
| kpeter@813 |    630 |             }
 | 
| kpeter@813 |    631 |           }
 | 
| kpeter@813 |    632 |         }
 | 
| kpeter@813 |    633 | 
 | 
| kpeter@813 |    634 |         // Check the optimality condition for all arcs
 | 
| kpeter@813 |    635 |         bool done = true;
 | 
| kpeter@813 |    636 |         for (ArcIt a(_gr); a != INVALID; ++a) {
 | 
| kpeter@942 |    637 |           if (_tolerance.less(_cost[a] * _curr_size - _curr_cost,
 | 
| kpeter@813 |    638 |                               pi[_gr.target(a)] - pi[_gr.source(a)]) ) {
 | 
| kpeter@813 |    639 |             done = false;
 | 
| kpeter@813 |    640 |             break;
 | 
| kpeter@813 |    641 |           }
 | 
| kpeter@813 |    642 |         }
 | 
| kpeter@813 |    643 |         return done;
 | 
| kpeter@813 |    644 |       }
 | 
| kpeter@813 |    645 |       return (k == n);
 | 
| kpeter@813 |    646 |     }
 | 
| kpeter@813 |    647 | 
 | 
| kpeter@942 |    648 |   }; //class HartmannOrlinMmc
 | 
| kpeter@813 |    649 | 
 | 
| kpeter@813 |    650 |   ///@}
 | 
| kpeter@813 |    651 | 
 | 
| kpeter@813 |    652 | } //namespace lemon
 | 
| kpeter@813 |    653 | 
 | 
| kpeter@942 |    654 | #endif //LEMON_HARTMANN_ORLIN_MMC_H
 |