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