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