lemon/karp.h
author Peter Kovacs <kpeter@inf.elte.hu>
Thu, 12 Nov 2009 23:26:13 +0100
changeset 806 fa6f37d7a25b
parent 771 8452ca46e29a
child 825 75e6020b19b1
permissions -rw-r--r--
Entirely rework CapacityScaling (#180)

- Use the new interface similarly to NetworkSimplex.
- Rework the implementation using an efficient internal structure
for handling the residual network. This improvement made the
code much faster (up to 2-5 times faster on large graphs).
- Handle GEQ supply type (LEQ is not supported).
- Handle negative costs for arcs of finite capacity.
(Note that this algorithm cannot handle arcs of negative cost
and infinite upper bound, thus it returns UNBOUNDED if such
an arc exists.)
- Extend the documentation.
kpeter@765
     1
/* -*- C++ -*-
kpeter@765
     2
 *
kpeter@765
     3
 * This file is a part of LEMON, a generic C++ optimization library
kpeter@765
     4
 *
kpeter@765
     5
 * Copyright (C) 2003-2008
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@765
    19
#ifndef LEMON_KARP_H
kpeter@765
    20
#define LEMON_KARP_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@765
    36
  /// \brief Default traits class of Karp algorithm.
kpeter@765
    37
  ///
kpeter@765
    38
  /// Default traits class of Karp algorithm.
kpeter@765
    39
  /// \tparam GR The type of the digraph.
kpeter@765
    40
  /// \tparam LEN The type of the length map.
kpeter@765
    41
  /// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
kpeter@765
    42
#ifdef DOXYGEN
kpeter@765
    43
  template <typename GR, typename LEN>
kpeter@765
    44
#else
kpeter@765
    45
  template <typename GR, typename LEN,
kpeter@765
    46
    bool integer = std::numeric_limits<typename LEN::Value>::is_integer>
kpeter@765
    47
#endif
kpeter@765
    48
  struct KarpDefaultTraits
kpeter@765
    49
  {
kpeter@765
    50
    /// The type of the digraph
kpeter@765
    51
    typedef GR Digraph;
kpeter@765
    52
    /// The type of the length map
kpeter@765
    53
    typedef LEN LengthMap;
kpeter@765
    54
    /// The type of the arc lengths
kpeter@765
    55
    typedef typename LengthMap::Value Value;
kpeter@765
    56
kpeter@765
    57
    /// \brief The large value type used for internal computations
kpeter@765
    58
    ///
kpeter@765
    59
    /// The large value type used for internal computations.
kpeter@765
    60
    /// It is \c long \c long if the \c Value type is integer,
kpeter@765
    61
    /// otherwise it is \c double.
kpeter@765
    62
    /// \c Value must be convertible to \c LargeValue.
kpeter@765
    63
    typedef double LargeValue;
kpeter@765
    64
kpeter@765
    65
    /// The tolerance type used for internal computations
kpeter@765
    66
    typedef lemon::Tolerance<LargeValue> 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@765
    76
  // Default traits class for integer value types
kpeter@765
    77
  template <typename GR, typename LEN>
kpeter@765
    78
  struct KarpDefaultTraits<GR, LEN, true>
kpeter@765
    79
  {
kpeter@765
    80
    typedef GR Digraph;
kpeter@765
    81
    typedef LEN LengthMap;
kpeter@765
    82
    typedef typename LengthMap::Value Value;
kpeter@765
    83
#ifdef LEMON_HAVE_LONG_LONG
kpeter@765
    84
    typedef long long LargeValue;
kpeter@765
    85
#else
kpeter@765
    86
    typedef long LargeValue;
kpeter@765
    87
#endif
kpeter@765
    88
    typedef lemon::Tolerance<LargeValue> 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@771
   100
  /// cycle of minimum mean length (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@765
   105
  /// \tparam LEN The type of the length map. The default
kpeter@765
   106
  /// map type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
kpeter@765
   107
#ifdef DOXYGEN
kpeter@765
   108
  template <typename GR, typename LEN, typename TR>
kpeter@765
   109
#else
kpeter@765
   110
  template < typename GR,
kpeter@765
   111
             typename LEN = typename GR::template ArcMap<int>,
kpeter@765
   112
             typename TR = KarpDefaultTraits<GR, LEN> >
kpeter@765
   113
#endif
kpeter@765
   114
  class Karp
kpeter@765
   115
  {
kpeter@765
   116
  public:
kpeter@765
   117
kpeter@765
   118
    /// The type of the digraph
kpeter@765
   119
    typedef typename TR::Digraph Digraph;
kpeter@765
   120
    /// The type of the length map
kpeter@765
   121
    typedef typename TR::LengthMap LengthMap;
kpeter@765
   122
    /// The type of the arc lengths
kpeter@765
   123
    typedef typename TR::Value Value;
kpeter@765
   124
kpeter@765
   125
    /// \brief The large value type
kpeter@765
   126
    ///
kpeter@765
   127
    /// The large value type used for internal computations.
kpeter@765
   128
    /// Using the \ref KarpDefaultTraits "default traits class",
kpeter@765
   129
    /// it is \c long \c long if the \c Value type is integer,
kpeter@765
   130
    /// otherwise it is \c double.
kpeter@765
   131
    typedef typename TR::LargeValue LargeValue;
kpeter@765
   132
kpeter@765
   133
    /// The tolerance type
kpeter@765
   134
    typedef typename TR::Tolerance Tolerance;
kpeter@765
   135
kpeter@765
   136
    /// \brief The path type of the found cycles
kpeter@765
   137
    ///
kpeter@765
   138
    /// The path type of the found cycles.
kpeter@765
   139
    /// Using the \ref KarpDefaultTraits "default traits class",
kpeter@765
   140
    /// it is \ref lemon::Path "Path<Digraph>".
kpeter@765
   141
    typedef typename TR::Path Path;
kpeter@765
   142
kpeter@765
   143
    /// The \ref KarpDefaultTraits "traits class" of the algorithm
kpeter@765
   144
    typedef TR Traits;
kpeter@765
   145
kpeter@765
   146
  private:
kpeter@765
   147
kpeter@765
   148
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
kpeter@765
   149
kpeter@765
   150
    // Data sturcture for path data
kpeter@765
   151
    struct PathData
kpeter@765
   152
    {
kpeter@765
   153
      LargeValue dist;
kpeter@765
   154
      Arc pred;
kpeter@767
   155
      PathData(LargeValue d, Arc p = INVALID) :
kpeter@767
   156
        dist(d), pred(p) {}
kpeter@765
   157
    };
kpeter@765
   158
kpeter@765
   159
    typedef typename Digraph::template NodeMap<std::vector<PathData> >
kpeter@765
   160
      PathDataNodeMap;
kpeter@765
   161
kpeter@765
   162
  private:
kpeter@765
   163
kpeter@765
   164
    // The digraph the algorithm runs on
kpeter@765
   165
    const Digraph &_gr;
kpeter@765
   166
    // The length of the arcs
kpeter@765
   167
    const LengthMap &_length;
kpeter@765
   168
kpeter@765
   169
    // Data for storing the strongly connected components
kpeter@765
   170
    int _comp_num;
kpeter@765
   171
    typename Digraph::template NodeMap<int> _comp;
kpeter@765
   172
    std::vector<std::vector<Node> > _comp_nodes;
kpeter@765
   173
    std::vector<Node>* _nodes;
kpeter@765
   174
    typename Digraph::template NodeMap<std::vector<Arc> > _out_arcs;
kpeter@765
   175
kpeter@765
   176
    // Data for the found cycle
kpeter@765
   177
    LargeValue _cycle_length;
kpeter@765
   178
    int _cycle_size;
kpeter@765
   179
    Node _cycle_node;
kpeter@765
   180
kpeter@765
   181
    Path *_cycle_path;
kpeter@765
   182
    bool _local_path;
kpeter@765
   183
kpeter@765
   184
    // Node map for storing path data
kpeter@765
   185
    PathDataNodeMap _data;
kpeter@765
   186
    // The processed nodes in the last round
kpeter@765
   187
    std::vector<Node> _process;
kpeter@765
   188
kpeter@765
   189
    Tolerance _tolerance;
kpeter@767
   190
    
kpeter@767
   191
    // Infinite constant
kpeter@767
   192
    const LargeValue INF;
kpeter@765
   193
kpeter@765
   194
  public:
kpeter@765
   195
kpeter@765
   196
    /// \name Named Template Parameters
kpeter@765
   197
    /// @{
kpeter@765
   198
kpeter@765
   199
    template <typename T>
kpeter@765
   200
    struct SetLargeValueTraits : public Traits {
kpeter@765
   201
      typedef T LargeValue;
kpeter@765
   202
      typedef lemon::Tolerance<T> Tolerance;
kpeter@765
   203
    };
kpeter@765
   204
kpeter@765
   205
    /// \brief \ref named-templ-param "Named parameter" for setting
kpeter@765
   206
    /// \c LargeValue type.
kpeter@765
   207
    ///
kpeter@765
   208
    /// \ref named-templ-param "Named parameter" for setting \c LargeValue
kpeter@765
   209
    /// type. It is used for internal computations in the algorithm.
kpeter@765
   210
    template <typename T>
kpeter@765
   211
    struct SetLargeValue
kpeter@765
   212
      : public Karp<GR, LEN, SetLargeValueTraits<T> > {
kpeter@765
   213
      typedef Karp<GR, LEN, SetLargeValueTraits<T> > Create;
kpeter@765
   214
    };
kpeter@765
   215
kpeter@765
   216
    template <typename T>
kpeter@765
   217
    struct SetPathTraits : public Traits {
kpeter@765
   218
      typedef T Path;
kpeter@765
   219
    };
kpeter@765
   220
kpeter@765
   221
    /// \brief \ref named-templ-param "Named parameter" for setting
kpeter@765
   222
    /// \c %Path type.
kpeter@765
   223
    ///
kpeter@765
   224
    /// \ref named-templ-param "Named parameter" for setting the \c %Path
kpeter@765
   225
    /// type of the found cycles.
kpeter@765
   226
    /// It must conform to the \ref lemon::concepts::Path "Path" concept
kpeter@765
   227
    /// and it must have an \c addFront() function.
kpeter@765
   228
    template <typename T>
kpeter@765
   229
    struct SetPath
kpeter@765
   230
      : public Karp<GR, LEN, SetPathTraits<T> > {
kpeter@765
   231
      typedef Karp<GR, LEN, SetPathTraits<T> > Create;
kpeter@765
   232
    };
kpeter@765
   233
kpeter@765
   234
    /// @}
kpeter@765
   235
kpeter@765
   236
  public:
kpeter@765
   237
kpeter@765
   238
    /// \brief Constructor.
kpeter@765
   239
    ///
kpeter@765
   240
    /// The constructor of the class.
kpeter@765
   241
    ///
kpeter@765
   242
    /// \param digraph The digraph the algorithm runs on.
kpeter@765
   243
    /// \param length The lengths (costs) of the arcs.
kpeter@765
   244
    Karp( const Digraph &digraph,
kpeter@765
   245
          const LengthMap &length ) :
kpeter@765
   246
      _gr(digraph), _length(length), _comp(digraph), _out_arcs(digraph),
kpeter@765
   247
      _cycle_length(0), _cycle_size(1), _cycle_node(INVALID),
kpeter@767
   248
      _cycle_path(NULL), _local_path(false), _data(digraph),
kpeter@767
   249
      INF(std::numeric_limits<LargeValue>::has_infinity ?
kpeter@767
   250
          std::numeric_limits<LargeValue>::infinity() :
kpeter@767
   251
          std::numeric_limits<LargeValue>::max())
kpeter@765
   252
    {}
kpeter@765
   253
kpeter@765
   254
    /// Destructor.
kpeter@765
   255
    ~Karp() {
kpeter@765
   256
      if (_local_path) delete _cycle_path;
kpeter@765
   257
    }
kpeter@765
   258
kpeter@765
   259
    /// \brief Set the path structure for storing the found cycle.
kpeter@765
   260
    ///
kpeter@765
   261
    /// This function sets an external path structure for storing the
kpeter@765
   262
    /// found cycle.
kpeter@765
   263
    ///
kpeter@765
   264
    /// If you don't call this function before calling \ref run() or
kpeter@765
   265
    /// \ref findMinMean(), it will allocate a local \ref Path "path"
kpeter@765
   266
    /// structure. The destuctor deallocates this automatically
kpeter@765
   267
    /// allocated object, of course.
kpeter@765
   268
    ///
kpeter@765
   269
    /// \note The algorithm calls only the \ref lemon::Path::addFront()
kpeter@765
   270
    /// "addFront()" function of the given path structure.
kpeter@765
   271
    ///
kpeter@765
   272
    /// \return <tt>(*this)</tt>
kpeter@765
   273
    Karp& cycle(Path &path) {
kpeter@765
   274
      if (_local_path) {
kpeter@765
   275
        delete _cycle_path;
kpeter@765
   276
        _local_path = false;
kpeter@765
   277
      }
kpeter@765
   278
      _cycle_path = &path;
kpeter@765
   279
      return *this;
kpeter@765
   280
    }
kpeter@765
   281
kpeter@769
   282
    /// \brief Set the tolerance used by the algorithm.
kpeter@769
   283
    ///
kpeter@769
   284
    /// This function sets the tolerance object used by the algorithm.
kpeter@769
   285
    ///
kpeter@769
   286
    /// \return <tt>(*this)</tt>
kpeter@769
   287
    Karp& tolerance(const Tolerance& tolerance) {
kpeter@769
   288
      _tolerance = tolerance;
kpeter@769
   289
      return *this;
kpeter@769
   290
    }
kpeter@769
   291
kpeter@769
   292
    /// \brief Return a const reference to the tolerance.
kpeter@769
   293
    ///
kpeter@769
   294
    /// This function returns a const reference to the tolerance object
kpeter@769
   295
    /// used by the algorithm.
kpeter@769
   296
    const Tolerance& tolerance() const {
kpeter@769
   297
      return _tolerance;
kpeter@769
   298
    }
kpeter@769
   299
kpeter@765
   300
    /// \name Execution control
kpeter@765
   301
    /// The simplest way to execute the algorithm is to call the \ref run()
kpeter@765
   302
    /// function.\n
kpeter@765
   303
    /// If you only need the minimum mean length, you may call
kpeter@765
   304
    /// \ref findMinMean().
kpeter@765
   305
kpeter@765
   306
    /// @{
kpeter@765
   307
kpeter@765
   308
    /// \brief Run the algorithm.
kpeter@765
   309
    ///
kpeter@765
   310
    /// This function runs the algorithm.
kpeter@765
   311
    /// It can be called more than once (e.g. if the underlying digraph
kpeter@765
   312
    /// and/or the arc lengths have been modified).
kpeter@765
   313
    ///
kpeter@765
   314
    /// \return \c true if a directed cycle exists in the digraph.
kpeter@765
   315
    ///
kpeter@765
   316
    /// \note <tt>mmc.run()</tt> is just a shortcut of the following code.
kpeter@765
   317
    /// \code
kpeter@765
   318
    ///   return mmc.findMinMean() && mmc.findCycle();
kpeter@765
   319
    /// \endcode
kpeter@765
   320
    bool run() {
kpeter@765
   321
      return findMinMean() && findCycle();
kpeter@765
   322
    }
kpeter@765
   323
kpeter@765
   324
    /// \brief Find the minimum cycle mean.
kpeter@765
   325
    ///
kpeter@765
   326
    /// This function finds the minimum mean length of the directed
kpeter@765
   327
    /// cycles in the digraph.
kpeter@765
   328
    ///
kpeter@765
   329
    /// \return \c true if a directed cycle exists in the digraph.
kpeter@765
   330
    bool findMinMean() {
kpeter@765
   331
      // Initialization and find strongly connected components
kpeter@765
   332
      init();
kpeter@765
   333
      findComponents();
kpeter@765
   334
      
kpeter@765
   335
      // Find the minimum cycle mean in the components
kpeter@765
   336
      for (int comp = 0; comp < _comp_num; ++comp) {
kpeter@765
   337
        if (!initComponent(comp)) continue;
kpeter@765
   338
        processRounds();
kpeter@765
   339
        updateMinMean();
kpeter@765
   340
      }
kpeter@765
   341
      return (_cycle_node != INVALID);
kpeter@765
   342
    }
kpeter@765
   343
kpeter@765
   344
    /// \brief Find a minimum mean directed cycle.
kpeter@765
   345
    ///
kpeter@765
   346
    /// This function finds a directed cycle of minimum mean length
kpeter@765
   347
    /// in the digraph using the data computed by findMinMean().
kpeter@765
   348
    ///
kpeter@765
   349
    /// \return \c true if a directed cycle exists in the digraph.
kpeter@765
   350
    ///
kpeter@765
   351
    /// \pre \ref findMinMean() must be called before using this function.
kpeter@765
   352
    bool findCycle() {
kpeter@765
   353
      if (_cycle_node == INVALID) return false;
kpeter@765
   354
      IntNodeMap reached(_gr, -1);
kpeter@765
   355
      int r = _data[_cycle_node].size();
kpeter@765
   356
      Node u = _cycle_node;
kpeter@765
   357
      while (reached[u] < 0) {
kpeter@765
   358
        reached[u] = --r;
kpeter@765
   359
        u = _gr.source(_data[u][r].pred);
kpeter@765
   360
      }
kpeter@765
   361
      r = reached[u];
kpeter@765
   362
      Arc e = _data[u][r].pred;
kpeter@765
   363
      _cycle_path->addFront(e);
kpeter@765
   364
      _cycle_length = _length[e];
kpeter@765
   365
      _cycle_size = 1;
kpeter@765
   366
      Node v;
kpeter@765
   367
      while ((v = _gr.source(e)) != u) {
kpeter@765
   368
        e = _data[v][--r].pred;
kpeter@765
   369
        _cycle_path->addFront(e);
kpeter@765
   370
        _cycle_length += _length[e];
kpeter@765
   371
        ++_cycle_size;
kpeter@765
   372
      }
kpeter@765
   373
      return true;
kpeter@765
   374
    }
kpeter@765
   375
kpeter@765
   376
    /// @}
kpeter@765
   377
kpeter@765
   378
    /// \name Query Functions
kpeter@765
   379
    /// The results of the algorithm can be obtained using these
kpeter@765
   380
    /// functions.\n
kpeter@765
   381
    /// The algorithm should be executed before using them.
kpeter@765
   382
kpeter@765
   383
    /// @{
kpeter@765
   384
kpeter@765
   385
    /// \brief Return the total length of the found cycle.
kpeter@765
   386
    ///
kpeter@765
   387
    /// This function returns the total length of the found cycle.
kpeter@765
   388
    ///
kpeter@765
   389
    /// \pre \ref run() or \ref findMinMean() must be called before
kpeter@765
   390
    /// using this function.
kpeter@765
   391
    LargeValue cycleLength() const {
kpeter@765
   392
      return _cycle_length;
kpeter@765
   393
    }
kpeter@765
   394
kpeter@765
   395
    /// \brief Return the number of arcs on the found cycle.
kpeter@765
   396
    ///
kpeter@765
   397
    /// This function returns the number of arcs on the found cycle.
kpeter@765
   398
    ///
kpeter@765
   399
    /// \pre \ref run() or \ref findMinMean() must be called before
kpeter@765
   400
    /// using this function.
kpeter@765
   401
    int cycleArcNum() const {
kpeter@765
   402
      return _cycle_size;
kpeter@765
   403
    }
kpeter@765
   404
kpeter@765
   405
    /// \brief Return the mean length of the found cycle.
kpeter@765
   406
    ///
kpeter@765
   407
    /// This function returns the mean length of the found cycle.
kpeter@765
   408
    ///
kpeter@765
   409
    /// \note <tt>alg.cycleMean()</tt> is just a shortcut of the
kpeter@765
   410
    /// following code.
kpeter@765
   411
    /// \code
kpeter@765
   412
    ///   return static_cast<double>(alg.cycleLength()) / alg.cycleArcNum();
kpeter@765
   413
    /// \endcode
kpeter@765
   414
    ///
kpeter@765
   415
    /// \pre \ref run() or \ref findMinMean() must be called before
kpeter@765
   416
    /// using this function.
kpeter@765
   417
    double cycleMean() const {
kpeter@765
   418
      return static_cast<double>(_cycle_length) / _cycle_size;
kpeter@765
   419
    }
kpeter@765
   420
kpeter@765
   421
    /// \brief Return the found cycle.
kpeter@765
   422
    ///
kpeter@765
   423
    /// This function returns a const reference to the path structure
kpeter@765
   424
    /// storing the found cycle.
kpeter@765
   425
    ///
kpeter@765
   426
    /// \pre \ref run() or \ref findCycle() must be called before using
kpeter@765
   427
    /// this function.
kpeter@765
   428
    const Path& cycle() const {
kpeter@765
   429
      return *_cycle_path;
kpeter@765
   430
    }
kpeter@765
   431
kpeter@765
   432
    ///@}
kpeter@765
   433
kpeter@765
   434
  private:
kpeter@765
   435
kpeter@765
   436
    // Initialization
kpeter@765
   437
    void init() {
kpeter@765
   438
      if (!_cycle_path) {
kpeter@765
   439
        _local_path = true;
kpeter@765
   440
        _cycle_path = new Path;
kpeter@765
   441
      }
kpeter@765
   442
      _cycle_path->clear();
kpeter@765
   443
      _cycle_length = 0;
kpeter@765
   444
      _cycle_size = 1;
kpeter@765
   445
      _cycle_node = INVALID;
kpeter@765
   446
      for (NodeIt u(_gr); u != INVALID; ++u)
kpeter@765
   447
        _data[u].clear();
kpeter@765
   448
    }
kpeter@765
   449
kpeter@765
   450
    // Find strongly connected components and initialize _comp_nodes
kpeter@765
   451
    // and _out_arcs
kpeter@765
   452
    void findComponents() {
kpeter@765
   453
      _comp_num = stronglyConnectedComponents(_gr, _comp);
kpeter@765
   454
      _comp_nodes.resize(_comp_num);
kpeter@765
   455
      if (_comp_num == 1) {
kpeter@765
   456
        _comp_nodes[0].clear();
kpeter@765
   457
        for (NodeIt n(_gr); n != INVALID; ++n) {
kpeter@765
   458
          _comp_nodes[0].push_back(n);
kpeter@765
   459
          _out_arcs[n].clear();
kpeter@765
   460
          for (OutArcIt a(_gr, n); a != INVALID; ++a) {
kpeter@765
   461
            _out_arcs[n].push_back(a);
kpeter@765
   462
          }
kpeter@765
   463
        }
kpeter@765
   464
      } else {
kpeter@765
   465
        for (int i = 0; i < _comp_num; ++i)
kpeter@765
   466
          _comp_nodes[i].clear();
kpeter@765
   467
        for (NodeIt n(_gr); n != INVALID; ++n) {
kpeter@765
   468
          int k = _comp[n];
kpeter@765
   469
          _comp_nodes[k].push_back(n);
kpeter@765
   470
          _out_arcs[n].clear();
kpeter@765
   471
          for (OutArcIt a(_gr, n); a != INVALID; ++a) {
kpeter@765
   472
            if (_comp[_gr.target(a)] == k) _out_arcs[n].push_back(a);
kpeter@765
   473
          }
kpeter@765
   474
        }
kpeter@765
   475
      }
kpeter@765
   476
    }
kpeter@765
   477
kpeter@765
   478
    // Initialize path data for the current component
kpeter@765
   479
    bool initComponent(int comp) {
kpeter@765
   480
      _nodes = &(_comp_nodes[comp]);
kpeter@765
   481
      int n = _nodes->size();
kpeter@765
   482
      if (n < 1 || (n == 1 && _out_arcs[(*_nodes)[0]].size() == 0)) {
kpeter@765
   483
        return false;
kpeter@765
   484
      }      
kpeter@765
   485
      for (int i = 0; i < n; ++i) {
kpeter@767
   486
        _data[(*_nodes)[i]].resize(n + 1, PathData(INF));
kpeter@765
   487
      }
kpeter@765
   488
      return true;
kpeter@765
   489
    }
kpeter@765
   490
kpeter@765
   491
    // Process all rounds of computing path data for the current component.
kpeter@765
   492
    // _data[v][k] is the length of a shortest directed walk from the root
kpeter@765
   493
    // node to node v containing exactly k arcs.
kpeter@765
   494
    void processRounds() {
kpeter@765
   495
      Node start = (*_nodes)[0];
kpeter@767
   496
      _data[start][0] = PathData(0);
kpeter@765
   497
      _process.clear();
kpeter@765
   498
      _process.push_back(start);
kpeter@765
   499
kpeter@765
   500
      int k, n = _nodes->size();
kpeter@765
   501
      for (k = 1; k <= n && int(_process.size()) < n; ++k) {
kpeter@765
   502
        processNextBuildRound(k);
kpeter@765
   503
      }
kpeter@765
   504
      for ( ; k <= n; ++k) {
kpeter@765
   505
        processNextFullRound(k);
kpeter@765
   506
      }
kpeter@765
   507
    }
kpeter@765
   508
kpeter@765
   509
    // Process one round and rebuild _process
kpeter@765
   510
    void processNextBuildRound(int k) {
kpeter@765
   511
      std::vector<Node> next;
kpeter@765
   512
      Node u, v;
kpeter@765
   513
      Arc e;
kpeter@765
   514
      LargeValue d;
kpeter@765
   515
      for (int i = 0; i < int(_process.size()); ++i) {
kpeter@765
   516
        u = _process[i];
kpeter@765
   517
        for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
kpeter@765
   518
          e = _out_arcs[u][j];
kpeter@765
   519
          v = _gr.target(e);
kpeter@765
   520
          d = _data[u][k-1].dist + _length[e];
kpeter@767
   521
          if (_tolerance.less(d, _data[v][k].dist)) {
kpeter@767
   522
            if (_data[v][k].dist == INF) next.push_back(v);
kpeter@767
   523
            _data[v][k] = PathData(d, e);
kpeter@765
   524
          }
kpeter@765
   525
        }
kpeter@765
   526
      }
kpeter@765
   527
      _process.swap(next);
kpeter@765
   528
    }
kpeter@765
   529
kpeter@765
   530
    // Process one round using _nodes instead of _process
kpeter@765
   531
    void processNextFullRound(int k) {
kpeter@765
   532
      Node u, v;
kpeter@765
   533
      Arc e;
kpeter@765
   534
      LargeValue d;
kpeter@765
   535
      for (int i = 0; i < int(_nodes->size()); ++i) {
kpeter@765
   536
        u = (*_nodes)[i];
kpeter@765
   537
        for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
kpeter@765
   538
          e = _out_arcs[u][j];
kpeter@765
   539
          v = _gr.target(e);
kpeter@765
   540
          d = _data[u][k-1].dist + _length[e];
kpeter@767
   541
          if (_tolerance.less(d, _data[v][k].dist)) {
kpeter@767
   542
            _data[v][k] = PathData(d, e);
kpeter@765
   543
          }
kpeter@765
   544
        }
kpeter@765
   545
      }
kpeter@765
   546
    }
kpeter@765
   547
kpeter@765
   548
    // Update the minimum cycle mean
kpeter@765
   549
    void updateMinMean() {
kpeter@765
   550
      int n = _nodes->size();
kpeter@765
   551
      for (int i = 0; i < n; ++i) {
kpeter@765
   552
        Node u = (*_nodes)[i];
kpeter@767
   553
        if (_data[u][n].dist == INF) continue;
kpeter@765
   554
        LargeValue length, max_length = 0;
kpeter@765
   555
        int size, max_size = 1;
kpeter@765
   556
        bool found_curr = false;
kpeter@765
   557
        for (int k = 0; k < n; ++k) {
kpeter@767
   558
          if (_data[u][k].dist == INF) continue;
kpeter@765
   559
          length = _data[u][n].dist - _data[u][k].dist;
kpeter@765
   560
          size = n - k;
kpeter@765
   561
          if (!found_curr || length * max_size > max_length * size) {
kpeter@765
   562
            found_curr = true;
kpeter@765
   563
            max_length = length;
kpeter@765
   564
            max_size = size;
kpeter@765
   565
          }
kpeter@765
   566
        }
kpeter@765
   567
        if ( found_curr && (_cycle_node == INVALID ||
kpeter@765
   568
             max_length * _cycle_size < _cycle_length * max_size) ) {
kpeter@765
   569
          _cycle_length = max_length;
kpeter@765
   570
          _cycle_size = max_size;
kpeter@765
   571
          _cycle_node = u;
kpeter@765
   572
        }
kpeter@765
   573
      }
kpeter@765
   574
    }
kpeter@765
   575
kpeter@765
   576
  }; //class Karp
kpeter@765
   577
kpeter@765
   578
  ///@}
kpeter@765
   579
kpeter@765
   580
} //namespace lemon
kpeter@765
   581
kpeter@765
   582
#endif //LEMON_KARP_H