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