lemon/hartmann_orlin_mmc.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 936 ddd3c0d3d9bf
parent 877 141f9c0db4a3
child 1002 f63ba40a60f4
permissions -rw-r--r--
Implement the scaling Price Refinement heuristic in CostScaling (#417)
instead of Early Termination.

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