lemon/cost_scaling.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 936 ddd3c0d3d9bf
parent 935 6ea176638264
child 937 1226290a9b7d
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@808
     2
 *
alpar@877
     3
 * This file is a part of LEMON, a generic C++ optimization library.
kpeter@808
     4
 *
alpar@877
     5
 * Copyright (C) 2003-2010
kpeter@808
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
kpeter@808
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
kpeter@808
     8
 *
kpeter@808
     9
 * Permission to use, modify and distribute this software is granted
kpeter@808
    10
 * provided that this copyright notice appears in all copies. For
kpeter@808
    11
 * precise terms see the accompanying LICENSE file.
kpeter@808
    12
 *
kpeter@808
    13
 * This software is provided "AS IS" with no warranty of any kind,
kpeter@808
    14
 * express or implied, and with no claim as to its suitability for any
kpeter@808
    15
 * purpose.
kpeter@808
    16
 *
kpeter@808
    17
 */
kpeter@808
    18
kpeter@808
    19
#ifndef LEMON_COST_SCALING_H
kpeter@808
    20
#define LEMON_COST_SCALING_H
kpeter@808
    21
kpeter@808
    22
/// \ingroup min_cost_flow_algs
kpeter@808
    23
/// \file
kpeter@808
    24
/// \brief Cost scaling algorithm for finding a minimum cost flow.
kpeter@808
    25
kpeter@808
    26
#include <vector>
kpeter@808
    27
#include <deque>
kpeter@808
    28
#include <limits>
kpeter@808
    29
kpeter@808
    30
#include <lemon/core.h>
kpeter@808
    31
#include <lemon/maps.h>
kpeter@808
    32
#include <lemon/math.h>
kpeter@809
    33
#include <lemon/static_graph.h>
kpeter@808
    34
#include <lemon/circulation.h>
kpeter@808
    35
#include <lemon/bellman_ford.h>
kpeter@808
    36
kpeter@808
    37
namespace lemon {
kpeter@808
    38
kpeter@809
    39
  /// \brief Default traits class of CostScaling algorithm.
kpeter@809
    40
  ///
kpeter@809
    41
  /// Default traits class of CostScaling algorithm.
kpeter@809
    42
  /// \tparam GR Digraph type.
kpeter@812
    43
  /// \tparam V The number type used for flow amounts, capacity bounds
kpeter@809
    44
  /// and supply values. By default it is \c int.
kpeter@812
    45
  /// \tparam C The number type used for costs and potentials.
kpeter@809
    46
  /// By default it is the same as \c V.
kpeter@809
    47
#ifdef DOXYGEN
kpeter@809
    48
  template <typename GR, typename V = int, typename C = V>
kpeter@809
    49
#else
kpeter@809
    50
  template < typename GR, typename V = int, typename C = V,
kpeter@809
    51
             bool integer = std::numeric_limits<C>::is_integer >
kpeter@809
    52
#endif
kpeter@809
    53
  struct CostScalingDefaultTraits
kpeter@809
    54
  {
kpeter@809
    55
    /// The type of the digraph
kpeter@809
    56
    typedef GR Digraph;
kpeter@809
    57
    /// The type of the flow amounts, capacity bounds and supply values
kpeter@809
    58
    typedef V Value;
kpeter@809
    59
    /// The type of the arc costs
kpeter@809
    60
    typedef C Cost;
kpeter@809
    61
kpeter@809
    62
    /// \brief The large cost type used for internal computations
kpeter@809
    63
    ///
kpeter@809
    64
    /// The large cost type used for internal computations.
kpeter@809
    65
    /// It is \c long \c long if the \c Cost type is integer,
kpeter@809
    66
    /// otherwise it is \c double.
kpeter@809
    67
    /// \c Cost must be convertible to \c LargeCost.
kpeter@809
    68
    typedef double LargeCost;
kpeter@809
    69
  };
kpeter@809
    70
kpeter@809
    71
  // Default traits class for integer cost types
kpeter@809
    72
  template <typename GR, typename V, typename C>
kpeter@809
    73
  struct CostScalingDefaultTraits<GR, V, C, true>
kpeter@809
    74
  {
kpeter@809
    75
    typedef GR Digraph;
kpeter@809
    76
    typedef V Value;
kpeter@809
    77
    typedef C Cost;
kpeter@809
    78
#ifdef LEMON_HAVE_LONG_LONG
kpeter@809
    79
    typedef long long LargeCost;
kpeter@809
    80
#else
kpeter@809
    81
    typedef long LargeCost;
kpeter@809
    82
#endif
kpeter@809
    83
  };
kpeter@809
    84
kpeter@809
    85
kpeter@808
    86
  /// \addtogroup min_cost_flow_algs
kpeter@808
    87
  /// @{
kpeter@808
    88
kpeter@809
    89
  /// \brief Implementation of the Cost Scaling algorithm for
kpeter@809
    90
  /// finding a \ref min_cost_flow "minimum cost flow".
kpeter@808
    91
  ///
kpeter@809
    92
  /// \ref CostScaling implements a cost scaling algorithm that performs
kpeter@813
    93
  /// push/augment and relabel operations for finding a \ref min_cost_flow
kpeter@813
    94
  /// "minimum cost flow" \ref amo93networkflows, \ref goldberg90approximation,
alpar@877
    95
  /// \ref goldberg97efficient, \ref bunnagel98efficient.
kpeter@813
    96
  /// It is a highly efficient primal-dual solution method, which
kpeter@809
    97
  /// can be viewed as the generalization of the \ref Preflow
kpeter@809
    98
  /// "preflow push-relabel" algorithm for the maximum flow problem.
kpeter@808
    99
  ///
kpeter@919
   100
  /// In general, \ref NetworkSimplex and \ref CostScaling are the fastest
kpeter@919
   101
  /// implementations available in LEMON for this problem.
kpeter@919
   102
  ///
kpeter@809
   103
  /// Most of the parameters of the problem (except for the digraph)
kpeter@809
   104
  /// can be given using separate functions, and the algorithm can be
kpeter@809
   105
  /// executed using the \ref run() function. If some parameters are not
kpeter@809
   106
  /// specified, then default values will be used.
kpeter@808
   107
  ///
kpeter@809
   108
  /// \tparam GR The digraph type the algorithm runs on.
kpeter@812
   109
  /// \tparam V The number type used for flow amounts, capacity bounds
kpeter@825
   110
  /// and supply values in the algorithm. By default, it is \c int.
kpeter@812
   111
  /// \tparam C The number type used for costs and potentials in the
kpeter@825
   112
  /// algorithm. By default, it is the same as \c V.
kpeter@825
   113
  /// \tparam TR The traits class that defines various types used by the
kpeter@825
   114
  /// algorithm. By default, it is \ref CostScalingDefaultTraits
kpeter@825
   115
  /// "CostScalingDefaultTraits<GR, V, C>".
kpeter@825
   116
  /// In most cases, this parameter should not be set directly,
kpeter@825
   117
  /// consider to use the named template parameters instead.
kpeter@808
   118
  ///
kpeter@921
   119
  /// \warning Both \c V and \c C must be signed number types.
kpeter@921
   120
  /// \warning All input data (capacities, supply values, and costs) must
kpeter@809
   121
  /// be integer.
kpeter@919
   122
  /// \warning This algorithm does not support negative costs for
kpeter@919
   123
  /// arcs having infinite upper bound.
kpeter@810
   124
  ///
kpeter@810
   125
  /// \note %CostScaling provides three different internal methods,
kpeter@810
   126
  /// from which the most efficient one is used by default.
kpeter@810
   127
  /// For more information, see \ref Method.
kpeter@809
   128
#ifdef DOXYGEN
kpeter@809
   129
  template <typename GR, typename V, typename C, typename TR>
kpeter@809
   130
#else
kpeter@809
   131
  template < typename GR, typename V = int, typename C = V,
kpeter@809
   132
             typename TR = CostScalingDefaultTraits<GR, V, C> >
kpeter@809
   133
#endif
kpeter@808
   134
  class CostScaling
kpeter@808
   135
  {
kpeter@809
   136
  public:
kpeter@808
   137
kpeter@809
   138
    /// The type of the digraph
kpeter@809
   139
    typedef typename TR::Digraph Digraph;
kpeter@809
   140
    /// The type of the flow amounts, capacity bounds and supply values
kpeter@809
   141
    typedef typename TR::Value Value;
kpeter@809
   142
    /// The type of the arc costs
kpeter@809
   143
    typedef typename TR::Cost Cost;
kpeter@808
   144
kpeter@809
   145
    /// \brief The large cost type
kpeter@809
   146
    ///
kpeter@809
   147
    /// The large cost type used for internal computations.
kpeter@825
   148
    /// By default, it is \c long \c long if the \c Cost type is integer,
kpeter@809
   149
    /// otherwise it is \c double.
kpeter@809
   150
    typedef typename TR::LargeCost LargeCost;
kpeter@808
   151
kpeter@809
   152
    /// The \ref CostScalingDefaultTraits "traits class" of the algorithm
kpeter@809
   153
    typedef TR Traits;
kpeter@808
   154
kpeter@808
   155
  public:
kpeter@808
   156
kpeter@809
   157
    /// \brief Problem type constants for the \c run() function.
kpeter@809
   158
    ///
kpeter@809
   159
    /// Enum type containing the problem type constants that can be
kpeter@809
   160
    /// returned by the \ref run() function of the algorithm.
kpeter@809
   161
    enum ProblemType {
kpeter@809
   162
      /// The problem has no feasible solution (flow).
kpeter@809
   163
      INFEASIBLE,
kpeter@809
   164
      /// The problem has optimal solution (i.e. it is feasible and
kpeter@809
   165
      /// bounded), and the algorithm has found optimal flow and node
kpeter@809
   166
      /// potentials (primal and dual solutions).
kpeter@809
   167
      OPTIMAL,
kpeter@809
   168
      /// The digraph contains an arc of negative cost and infinite
kpeter@809
   169
      /// upper bound. It means that the objective function is unbounded
kpeter@812
   170
      /// on that arc, however, note that it could actually be bounded
kpeter@809
   171
      /// over the feasible flows, but this algroithm cannot handle
kpeter@809
   172
      /// these cases.
kpeter@809
   173
      UNBOUNDED
kpeter@809
   174
    };
kpeter@808
   175
kpeter@810
   176
    /// \brief Constants for selecting the internal method.
kpeter@810
   177
    ///
kpeter@810
   178
    /// Enum type containing constants for selecting the internal method
kpeter@810
   179
    /// for the \ref run() function.
kpeter@810
   180
    ///
kpeter@810
   181
    /// \ref CostScaling provides three internal methods that differ mainly
kpeter@810
   182
    /// in their base operations, which are used in conjunction with the
kpeter@810
   183
    /// relabel operation.
kpeter@810
   184
    /// By default, the so called \ref PARTIAL_AUGMENT
kpeter@919
   185
    /// "Partial Augment-Relabel" method is used, which turned out to be
kpeter@810
   186
    /// the most efficient and the most robust on various test inputs.
kpeter@810
   187
    /// However, the other methods can be selected using the \ref run()
kpeter@810
   188
    /// function with the proper parameter.
kpeter@810
   189
    enum Method {
kpeter@810
   190
      /// Local push operations are used, i.e. flow is moved only on one
kpeter@810
   191
      /// admissible arc at once.
kpeter@810
   192
      PUSH,
kpeter@810
   193
      /// Augment operations are used, i.e. flow is moved on admissible
kpeter@810
   194
      /// paths from a node with excess to a node with deficit.
kpeter@810
   195
      AUGMENT,
alpar@877
   196
      /// Partial augment operations are used, i.e. flow is moved on
kpeter@810
   197
      /// admissible paths started from a node with excess, but the
kpeter@810
   198
      /// lengths of these paths are limited. This method can be viewed
kpeter@810
   199
      /// as a combined version of the previous two operations.
kpeter@810
   200
      PARTIAL_AUGMENT
kpeter@810
   201
    };
kpeter@810
   202
kpeter@808
   203
  private:
kpeter@808
   204
kpeter@809
   205
    TEMPLATE_DIGRAPH_TYPEDEFS(GR);
kpeter@808
   206
kpeter@809
   207
    typedef std::vector<int> IntVector;
kpeter@809
   208
    typedef std::vector<Value> ValueVector;
kpeter@809
   209
    typedef std::vector<Cost> CostVector;
kpeter@809
   210
    typedef std::vector<LargeCost> LargeCostVector;
kpeter@839
   211
    typedef std::vector<char> BoolVector;
kpeter@839
   212
    // Note: vector<char> is used instead of vector<bool> for efficiency reasons
kpeter@808
   213
kpeter@809
   214
  private:
alpar@877
   215
kpeter@809
   216
    template <typename KT, typename VT>
kpeter@820
   217
    class StaticVectorMap {
kpeter@808
   218
    public:
kpeter@809
   219
      typedef KT Key;
kpeter@809
   220
      typedef VT Value;
alpar@877
   221
kpeter@820
   222
      StaticVectorMap(std::vector<Value>& v) : _v(v) {}
alpar@877
   223
kpeter@809
   224
      const Value& operator[](const Key& key) const {
kpeter@809
   225
        return _v[StaticDigraph::id(key)];
kpeter@808
   226
      }
kpeter@808
   227
kpeter@809
   228
      Value& operator[](const Key& key) {
kpeter@809
   229
        return _v[StaticDigraph::id(key)];
kpeter@809
   230
      }
alpar@877
   231
kpeter@809
   232
      void set(const Key& key, const Value& val) {
kpeter@809
   233
        _v[StaticDigraph::id(key)] = val;
kpeter@808
   234
      }
kpeter@808
   235
kpeter@809
   236
    private:
kpeter@809
   237
      std::vector<Value>& _v;
kpeter@809
   238
    };
kpeter@809
   239
kpeter@820
   240
    typedef StaticVectorMap<StaticDigraph::Node, LargeCost> LargeCostNodeMap;
kpeter@820
   241
    typedef StaticVectorMap<StaticDigraph::Arc, LargeCost> LargeCostArcMap;
kpeter@808
   242
kpeter@808
   243
  private:
kpeter@808
   244
kpeter@809
   245
    // Data related to the underlying digraph
kpeter@809
   246
    const GR &_graph;
kpeter@809
   247
    int _node_num;
kpeter@809
   248
    int _arc_num;
kpeter@809
   249
    int _res_node_num;
kpeter@809
   250
    int _res_arc_num;
kpeter@809
   251
    int _root;
kpeter@808
   252
kpeter@809
   253
    // Parameters of the problem
kpeter@809
   254
    bool _have_lower;
kpeter@809
   255
    Value _sum_supply;
kpeter@839
   256
    int _sup_node_num;
kpeter@808
   257
kpeter@809
   258
    // Data structures for storing the digraph
kpeter@809
   259
    IntNodeMap _node_id;
kpeter@809
   260
    IntArcMap _arc_idf;
kpeter@809
   261
    IntArcMap _arc_idb;
kpeter@809
   262
    IntVector _first_out;
kpeter@809
   263
    BoolVector _forward;
kpeter@809
   264
    IntVector _source;
kpeter@809
   265
    IntVector _target;
kpeter@809
   266
    IntVector _reverse;
kpeter@809
   267
kpeter@809
   268
    // Node and arc data
kpeter@809
   269
    ValueVector _lower;
kpeter@809
   270
    ValueVector _upper;
kpeter@809
   271
    CostVector _scost;
kpeter@809
   272
    ValueVector _supply;
kpeter@809
   273
kpeter@809
   274
    ValueVector _res_cap;
kpeter@809
   275
    LargeCostVector _cost;
kpeter@809
   276
    LargeCostVector _pi;
kpeter@809
   277
    ValueVector _excess;
kpeter@809
   278
    IntVector _next_out;
kpeter@809
   279
    std::deque<int> _active_nodes;
kpeter@809
   280
kpeter@809
   281
    // Data for scaling
kpeter@809
   282
    LargeCost _epsilon;
kpeter@808
   283
    int _alpha;
kpeter@808
   284
kpeter@839
   285
    IntVector _buckets;
kpeter@839
   286
    IntVector _bucket_next;
kpeter@839
   287
    IntVector _bucket_prev;
kpeter@839
   288
    IntVector _rank;
kpeter@839
   289
    int _max_rank;
alpar@877
   290
kpeter@809
   291
    // Data for a StaticDigraph structure
kpeter@809
   292
    typedef std::pair<int, int> IntPair;
kpeter@809
   293
    StaticDigraph _sgr;
kpeter@809
   294
    std::vector<IntPair> _arc_vec;
kpeter@809
   295
    std::vector<LargeCost> _cost_vec;
kpeter@809
   296
    LargeCostArcMap _cost_map;
kpeter@809
   297
    LargeCostNodeMap _pi_map;
alpar@877
   298
kpeter@809
   299
  public:
alpar@877
   300
kpeter@809
   301
    /// \brief Constant for infinite upper bounds (capacities).
kpeter@809
   302
    ///
kpeter@809
   303
    /// Constant for infinite upper bounds (capacities).
kpeter@809
   304
    /// It is \c std::numeric_limits<Value>::infinity() if available,
kpeter@809
   305
    /// \c std::numeric_limits<Value>::max() otherwise.
kpeter@809
   306
    const Value INF;
kpeter@809
   307
kpeter@808
   308
  public:
kpeter@808
   309
kpeter@809
   310
    /// \name Named Template Parameters
kpeter@809
   311
    /// @{
kpeter@809
   312
kpeter@809
   313
    template <typename T>
kpeter@809
   314
    struct SetLargeCostTraits : public Traits {
kpeter@809
   315
      typedef T LargeCost;
kpeter@809
   316
    };
kpeter@809
   317
kpeter@809
   318
    /// \brief \ref named-templ-param "Named parameter" for setting
kpeter@809
   319
    /// \c LargeCost type.
kpeter@808
   320
    ///
kpeter@809
   321
    /// \ref named-templ-param "Named parameter" for setting \c LargeCost
kpeter@809
   322
    /// type, which is used for internal computations in the algorithm.
kpeter@809
   323
    /// \c Cost must be convertible to \c LargeCost.
kpeter@809
   324
    template <typename T>
kpeter@809
   325
    struct SetLargeCost
kpeter@809
   326
      : public CostScaling<GR, V, C, SetLargeCostTraits<T> > {
kpeter@809
   327
      typedef  CostScaling<GR, V, C, SetLargeCostTraits<T> > Create;
kpeter@809
   328
    };
kpeter@809
   329
kpeter@809
   330
    /// @}
kpeter@809
   331
kpeter@863
   332
  protected:
kpeter@863
   333
kpeter@863
   334
    CostScaling() {}
kpeter@863
   335
kpeter@809
   336
  public:
kpeter@809
   337
kpeter@809
   338
    /// \brief Constructor.
kpeter@808
   339
    ///
kpeter@809
   340
    /// The constructor of the class.
kpeter@809
   341
    ///
kpeter@809
   342
    /// \param graph The digraph the algorithm runs on.
kpeter@809
   343
    CostScaling(const GR& graph) :
kpeter@809
   344
      _graph(graph), _node_id(graph), _arc_idf(graph), _arc_idb(graph),
kpeter@809
   345
      _cost_map(_cost_vec), _pi_map(_pi),
kpeter@809
   346
      INF(std::numeric_limits<Value>::has_infinity ?
kpeter@809
   347
          std::numeric_limits<Value>::infinity() :
kpeter@809
   348
          std::numeric_limits<Value>::max())
kpeter@808
   349
    {
kpeter@812
   350
      // Check the number types
kpeter@809
   351
      LEMON_ASSERT(std::numeric_limits<Value>::is_signed,
kpeter@809
   352
        "The flow type of CostScaling must be signed");
kpeter@809
   353
      LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
kpeter@809
   354
        "The cost type of CostScaling must be signed");
alpar@877
   355
kpeter@830
   356
      // Reset data structures
kpeter@809
   357
      reset();
kpeter@808
   358
    }
kpeter@808
   359
kpeter@809
   360
    /// \name Parameters
kpeter@809
   361
    /// The parameters of the algorithm can be specified using these
kpeter@809
   362
    /// functions.
kpeter@809
   363
kpeter@809
   364
    /// @{
kpeter@809
   365
kpeter@809
   366
    /// \brief Set the lower bounds on the arcs.
kpeter@808
   367
    ///
kpeter@809
   368
    /// This function sets the lower bounds on the arcs.
kpeter@809
   369
    /// If it is not used before calling \ref run(), the lower bounds
kpeter@809
   370
    /// will be set to zero on all arcs.
kpeter@808
   371
    ///
kpeter@809
   372
    /// \param map An arc map storing the lower bounds.
kpeter@809
   373
    /// Its \c Value type must be convertible to the \c Value type
kpeter@809
   374
    /// of the algorithm.
kpeter@809
   375
    ///
kpeter@809
   376
    /// \return <tt>(*this)</tt>
kpeter@809
   377
    template <typename LowerMap>
kpeter@809
   378
    CostScaling& lowerMap(const LowerMap& map) {
kpeter@809
   379
      _have_lower = true;
kpeter@809
   380
      for (ArcIt a(_graph); a != INVALID; ++a) {
kpeter@809
   381
        _lower[_arc_idf[a]] = map[a];
kpeter@809
   382
        _lower[_arc_idb[a]] = map[a];
kpeter@808
   383
      }
kpeter@808
   384
      return *this;
kpeter@808
   385
    }
kpeter@808
   386
kpeter@809
   387
    /// \brief Set the upper bounds (capacities) on the arcs.
kpeter@808
   388
    ///
kpeter@809
   389
    /// This function sets the upper bounds (capacities) on the arcs.
kpeter@809
   390
    /// If it is not used before calling \ref run(), the upper bounds
kpeter@809
   391
    /// will be set to \ref INF on all arcs (i.e. the flow value will be
kpeter@812
   392
    /// unbounded from above).
kpeter@808
   393
    ///
kpeter@809
   394
    /// \param map An arc map storing the upper bounds.
kpeter@809
   395
    /// Its \c Value type must be convertible to the \c Value type
kpeter@809
   396
    /// of the algorithm.
kpeter@809
   397
    ///
kpeter@809
   398
    /// \return <tt>(*this)</tt>
kpeter@809
   399
    template<typename UpperMap>
kpeter@809
   400
    CostScaling& upperMap(const UpperMap& map) {
kpeter@809
   401
      for (ArcIt a(_graph); a != INVALID; ++a) {
kpeter@809
   402
        _upper[_arc_idf[a]] = map[a];
kpeter@808
   403
      }
kpeter@808
   404
      return *this;
kpeter@808
   405
    }
kpeter@808
   406
kpeter@809
   407
    /// \brief Set the costs of the arcs.
kpeter@809
   408
    ///
kpeter@809
   409
    /// This function sets the costs of the arcs.
kpeter@809
   410
    /// If it is not used before calling \ref run(), the costs
kpeter@809
   411
    /// will be set to \c 1 on all arcs.
kpeter@809
   412
    ///
kpeter@809
   413
    /// \param map An arc map storing the costs.
kpeter@809
   414
    /// Its \c Value type must be convertible to the \c Cost type
kpeter@809
   415
    /// of the algorithm.
kpeter@809
   416
    ///
kpeter@809
   417
    /// \return <tt>(*this)</tt>
kpeter@809
   418
    template<typename CostMap>
kpeter@809
   419
    CostScaling& costMap(const CostMap& map) {
kpeter@809
   420
      for (ArcIt a(_graph); a != INVALID; ++a) {
kpeter@809
   421
        _scost[_arc_idf[a]] =  map[a];
kpeter@809
   422
        _scost[_arc_idb[a]] = -map[a];
kpeter@809
   423
      }
kpeter@809
   424
      return *this;
kpeter@809
   425
    }
kpeter@809
   426
kpeter@809
   427
    /// \brief Set the supply values of the nodes.
kpeter@809
   428
    ///
kpeter@809
   429
    /// This function sets the supply values of the nodes.
kpeter@809
   430
    /// If neither this function nor \ref stSupply() is used before
kpeter@809
   431
    /// calling \ref run(), the supply of each node will be set to zero.
kpeter@809
   432
    ///
kpeter@809
   433
    /// \param map A node map storing the supply values.
kpeter@809
   434
    /// Its \c Value type must be convertible to the \c Value type
kpeter@809
   435
    /// of the algorithm.
kpeter@809
   436
    ///
kpeter@809
   437
    /// \return <tt>(*this)</tt>
kpeter@809
   438
    template<typename SupplyMap>
kpeter@809
   439
    CostScaling& supplyMap(const SupplyMap& map) {
kpeter@809
   440
      for (NodeIt n(_graph); n != INVALID; ++n) {
kpeter@809
   441
        _supply[_node_id[n]] = map[n];
kpeter@809
   442
      }
kpeter@809
   443
      return *this;
kpeter@809
   444
    }
kpeter@809
   445
kpeter@809
   446
    /// \brief Set single source and target nodes and a supply value.
kpeter@809
   447
    ///
kpeter@809
   448
    /// This function sets a single source node and a single target node
kpeter@809
   449
    /// and the required flow value.
kpeter@809
   450
    /// If neither this function nor \ref supplyMap() is used before
kpeter@809
   451
    /// calling \ref run(), the supply of each node will be set to zero.
kpeter@809
   452
    ///
kpeter@809
   453
    /// Using this function has the same effect as using \ref supplyMap()
kpeter@919
   454
    /// with a map in which \c k is assigned to \c s, \c -k is
kpeter@809
   455
    /// assigned to \c t and all other nodes have zero supply value.
kpeter@809
   456
    ///
kpeter@809
   457
    /// \param s The source node.
kpeter@809
   458
    /// \param t The target node.
kpeter@809
   459
    /// \param k The required amount of flow from node \c s to node \c t
kpeter@809
   460
    /// (i.e. the supply of \c s and the demand of \c t).
kpeter@809
   461
    ///
kpeter@809
   462
    /// \return <tt>(*this)</tt>
kpeter@809
   463
    CostScaling& stSupply(const Node& s, const Node& t, Value k) {
kpeter@809
   464
      for (int i = 0; i != _res_node_num; ++i) {
kpeter@809
   465
        _supply[i] = 0;
kpeter@809
   466
      }
kpeter@809
   467
      _supply[_node_id[s]] =  k;
kpeter@809
   468
      _supply[_node_id[t]] = -k;
kpeter@809
   469
      return *this;
kpeter@809
   470
    }
alpar@877
   471
kpeter@809
   472
    /// @}
kpeter@809
   473
kpeter@808
   474
    /// \name Execution control
kpeter@809
   475
    /// The algorithm can be executed using \ref run().
kpeter@808
   476
kpeter@808
   477
    /// @{
kpeter@808
   478
kpeter@808
   479
    /// \brief Run the algorithm.
kpeter@808
   480
    ///
kpeter@809
   481
    /// This function runs the algorithm.
kpeter@809
   482
    /// The paramters can be specified using functions \ref lowerMap(),
kpeter@809
   483
    /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply().
kpeter@809
   484
    /// For example,
kpeter@809
   485
    /// \code
kpeter@809
   486
    ///   CostScaling<ListDigraph> cs(graph);
kpeter@809
   487
    ///   cs.lowerMap(lower).upperMap(upper).costMap(cost)
kpeter@809
   488
    ///     .supplyMap(sup).run();
kpeter@809
   489
    /// \endcode
kpeter@809
   490
    ///
kpeter@830
   491
    /// This function can be called more than once. All the given parameters
kpeter@830
   492
    /// are kept for the next call, unless \ref resetParams() or \ref reset()
kpeter@830
   493
    /// is used, thus only the modified parameters have to be set again.
kpeter@830
   494
    /// If the underlying digraph was also modified after the construction
kpeter@830
   495
    /// of the class (or the last \ref reset() call), then the \ref reset()
kpeter@830
   496
    /// function must be called.
kpeter@808
   497
    ///
kpeter@810
   498
    /// \param method The internal method that will be used in the
kpeter@810
   499
    /// algorithm. For more information, see \ref Method.
kpeter@810
   500
    /// \param factor The cost scaling factor. It must be larger than one.
kpeter@808
   501
    ///
kpeter@809
   502
    /// \return \c INFEASIBLE if no feasible flow exists,
kpeter@809
   503
    /// \n \c OPTIMAL if the problem has optimal solution
kpeter@809
   504
    /// (i.e. it is feasible and bounded), and the algorithm has found
kpeter@809
   505
    /// optimal flow and node potentials (primal and dual solutions),
kpeter@809
   506
    /// \n \c UNBOUNDED if the digraph contains an arc of negative cost
kpeter@809
   507
    /// and infinite upper bound. It means that the objective function
kpeter@812
   508
    /// is unbounded on that arc, however, note that it could actually be
kpeter@809
   509
    /// bounded over the feasible flows, but this algroithm cannot handle
kpeter@809
   510
    /// these cases.
kpeter@809
   511
    ///
kpeter@810
   512
    /// \see ProblemType, Method
kpeter@830
   513
    /// \see resetParams(), reset()
kpeter@810
   514
    ProblemType run(Method method = PARTIAL_AUGMENT, int factor = 8) {
kpeter@810
   515
      _alpha = factor;
kpeter@809
   516
      ProblemType pt = init();
kpeter@809
   517
      if (pt != OPTIMAL) return pt;
kpeter@810
   518
      start(method);
kpeter@809
   519
      return OPTIMAL;
kpeter@809
   520
    }
kpeter@809
   521
kpeter@809
   522
    /// \brief Reset all the parameters that have been given before.
kpeter@809
   523
    ///
kpeter@809
   524
    /// This function resets all the paramaters that have been given
kpeter@809
   525
    /// before using functions \ref lowerMap(), \ref upperMap(),
kpeter@809
   526
    /// \ref costMap(), \ref supplyMap(), \ref stSupply().
kpeter@809
   527
    ///
kpeter@830
   528
    /// It is useful for multiple \ref run() calls. Basically, all the given
kpeter@830
   529
    /// parameters are kept for the next \ref run() call, unless
kpeter@830
   530
    /// \ref resetParams() or \ref reset() is used.
kpeter@830
   531
    /// If the underlying digraph was also modified after the construction
kpeter@830
   532
    /// of the class or the last \ref reset() call, then the \ref reset()
kpeter@830
   533
    /// function must be used, otherwise \ref resetParams() is sufficient.
kpeter@809
   534
    ///
kpeter@809
   535
    /// For example,
kpeter@809
   536
    /// \code
kpeter@809
   537
    ///   CostScaling<ListDigraph> cs(graph);
kpeter@809
   538
    ///
kpeter@809
   539
    ///   // First run
kpeter@809
   540
    ///   cs.lowerMap(lower).upperMap(upper).costMap(cost)
kpeter@809
   541
    ///     .supplyMap(sup).run();
kpeter@809
   542
    ///
kpeter@830
   543
    ///   // Run again with modified cost map (resetParams() is not called,
kpeter@809
   544
    ///   // so only the cost map have to be set again)
kpeter@809
   545
    ///   cost[e] += 100;
kpeter@809
   546
    ///   cs.costMap(cost).run();
kpeter@809
   547
    ///
kpeter@830
   548
    ///   // Run again from scratch using resetParams()
kpeter@809
   549
    ///   // (the lower bounds will be set to zero on all arcs)
kpeter@830
   550
    ///   cs.resetParams();
kpeter@809
   551
    ///   cs.upperMap(capacity).costMap(cost)
kpeter@809
   552
    ///     .supplyMap(sup).run();
kpeter@809
   553
    /// \endcode
kpeter@809
   554
    ///
kpeter@809
   555
    /// \return <tt>(*this)</tt>
kpeter@830
   556
    ///
kpeter@830
   557
    /// \see reset(), run()
kpeter@830
   558
    CostScaling& resetParams() {
kpeter@809
   559
      for (int i = 0; i != _res_node_num; ++i) {
kpeter@809
   560
        _supply[i] = 0;
kpeter@808
   561
      }
kpeter@809
   562
      int limit = _first_out[_root];
kpeter@809
   563
      for (int j = 0; j != limit; ++j) {
kpeter@809
   564
        _lower[j] = 0;
kpeter@809
   565
        _upper[j] = INF;
kpeter@809
   566
        _scost[j] = _forward[j] ? 1 : -1;
kpeter@809
   567
      }
kpeter@809
   568
      for (int j = limit; j != _res_arc_num; ++j) {
kpeter@809
   569
        _lower[j] = 0;
kpeter@809
   570
        _upper[j] = INF;
kpeter@809
   571
        _scost[j] = 0;
kpeter@809
   572
        _scost[_reverse[j]] = 0;
alpar@877
   573
      }
kpeter@809
   574
      _have_lower = false;
kpeter@809
   575
      return *this;
kpeter@808
   576
    }
kpeter@808
   577
kpeter@934
   578
    /// \brief Reset the internal data structures and all the parameters
kpeter@934
   579
    /// that have been given before.
kpeter@830
   580
    ///
kpeter@934
   581
    /// This function resets the internal data structures and all the
kpeter@934
   582
    /// paramaters that have been given before using functions \ref lowerMap(),
kpeter@934
   583
    /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply().
kpeter@830
   584
    ///
kpeter@934
   585
    /// It is useful for multiple \ref run() calls. By default, all the given
kpeter@934
   586
    /// parameters are kept for the next \ref run() call, unless
kpeter@934
   587
    /// \ref resetParams() or \ref reset() is used.
kpeter@934
   588
    /// If the underlying digraph was also modified after the construction
kpeter@934
   589
    /// of the class or the last \ref reset() call, then the \ref reset()
kpeter@934
   590
    /// function must be used, otherwise \ref resetParams() is sufficient.
kpeter@934
   591
    ///
kpeter@934
   592
    /// See \ref resetParams() for examples.
kpeter@934
   593
    ///
kpeter@830
   594
    /// \return <tt>(*this)</tt>
kpeter@934
   595
    ///
kpeter@934
   596
    /// \see resetParams(), run()
kpeter@830
   597
    CostScaling& reset() {
kpeter@830
   598
      // Resize vectors
kpeter@830
   599
      _node_num = countNodes(_graph);
kpeter@830
   600
      _arc_num = countArcs(_graph);
kpeter@830
   601
      _res_node_num = _node_num + 1;
kpeter@830
   602
      _res_arc_num = 2 * (_arc_num + _node_num);
kpeter@830
   603
      _root = _node_num;
kpeter@830
   604
kpeter@830
   605
      _first_out.resize(_res_node_num + 1);
kpeter@830
   606
      _forward.resize(_res_arc_num);
kpeter@830
   607
      _source.resize(_res_arc_num);
kpeter@830
   608
      _target.resize(_res_arc_num);
kpeter@830
   609
      _reverse.resize(_res_arc_num);
kpeter@830
   610
kpeter@830
   611
      _lower.resize(_res_arc_num);
kpeter@830
   612
      _upper.resize(_res_arc_num);
kpeter@830
   613
      _scost.resize(_res_arc_num);
kpeter@830
   614
      _supply.resize(_res_node_num);
alpar@877
   615
kpeter@830
   616
      _res_cap.resize(_res_arc_num);
kpeter@830
   617
      _cost.resize(_res_arc_num);
kpeter@830
   618
      _pi.resize(_res_node_num);
kpeter@830
   619
      _excess.resize(_res_node_num);
kpeter@830
   620
      _next_out.resize(_res_node_num);
kpeter@830
   621
kpeter@830
   622
      _arc_vec.reserve(_res_arc_num);
kpeter@830
   623
      _cost_vec.reserve(_res_arc_num);
kpeter@830
   624
kpeter@830
   625
      // Copy the graph
kpeter@830
   626
      int i = 0, j = 0, k = 2 * _arc_num + _node_num;
kpeter@830
   627
      for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
kpeter@830
   628
        _node_id[n] = i;
kpeter@830
   629
      }
kpeter@830
   630
      i = 0;
kpeter@830
   631
      for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
kpeter@830
   632
        _first_out[i] = j;
kpeter@830
   633
        for (OutArcIt a(_graph, n); a != INVALID; ++a, ++j) {
kpeter@830
   634
          _arc_idf[a] = j;
kpeter@830
   635
          _forward[j] = true;
kpeter@830
   636
          _source[j] = i;
kpeter@830
   637
          _target[j] = _node_id[_graph.runningNode(a)];
kpeter@830
   638
        }
kpeter@830
   639
        for (InArcIt a(_graph, n); a != INVALID; ++a, ++j) {
kpeter@830
   640
          _arc_idb[a] = j;
kpeter@830
   641
          _forward[j] = false;
kpeter@830
   642
          _source[j] = i;
kpeter@830
   643
          _target[j] = _node_id[_graph.runningNode(a)];
kpeter@830
   644
        }
kpeter@830
   645
        _forward[j] = false;
kpeter@830
   646
        _source[j] = i;
kpeter@830
   647
        _target[j] = _root;
kpeter@830
   648
        _reverse[j] = k;
kpeter@830
   649
        _forward[k] = true;
kpeter@830
   650
        _source[k] = _root;
kpeter@830
   651
        _target[k] = i;
kpeter@830
   652
        _reverse[k] = j;
kpeter@830
   653
        ++j; ++k;
kpeter@830
   654
      }
kpeter@830
   655
      _first_out[i] = j;
kpeter@830
   656
      _first_out[_res_node_num] = k;
kpeter@830
   657
      for (ArcIt a(_graph); a != INVALID; ++a) {
kpeter@830
   658
        int fi = _arc_idf[a];
kpeter@830
   659
        int bi = _arc_idb[a];
kpeter@830
   660
        _reverse[fi] = bi;
kpeter@830
   661
        _reverse[bi] = fi;
kpeter@830
   662
      }
alpar@877
   663
kpeter@830
   664
      // Reset parameters
kpeter@830
   665
      resetParams();
kpeter@830
   666
      return *this;
kpeter@830
   667
    }
kpeter@830
   668
kpeter@808
   669
    /// @}
kpeter@808
   670
kpeter@808
   671
    /// \name Query Functions
kpeter@809
   672
    /// The results of the algorithm can be obtained using these
kpeter@808
   673
    /// functions.\n
kpeter@809
   674
    /// The \ref run() function must be called before using them.
kpeter@808
   675
kpeter@808
   676
    /// @{
kpeter@808
   677
kpeter@809
   678
    /// \brief Return the total cost of the found flow.
kpeter@808
   679
    ///
kpeter@809
   680
    /// This function returns the total cost of the found flow.
kpeter@809
   681
    /// Its complexity is O(e).
kpeter@809
   682
    ///
kpeter@809
   683
    /// \note The return type of the function can be specified as a
kpeter@809
   684
    /// template parameter. For example,
kpeter@809
   685
    /// \code
kpeter@809
   686
    ///   cs.totalCost<double>();
kpeter@809
   687
    /// \endcode
kpeter@809
   688
    /// It is useful if the total cost cannot be stored in the \c Cost
kpeter@809
   689
    /// type of the algorithm, which is the default return type of the
kpeter@809
   690
    /// function.
kpeter@808
   691
    ///
kpeter@808
   692
    /// \pre \ref run() must be called before using this function.
kpeter@809
   693
    template <typename Number>
kpeter@809
   694
    Number totalCost() const {
kpeter@809
   695
      Number c = 0;
kpeter@809
   696
      for (ArcIt a(_graph); a != INVALID; ++a) {
kpeter@809
   697
        int i = _arc_idb[a];
kpeter@809
   698
        c += static_cast<Number>(_res_cap[i]) *
kpeter@809
   699
             (-static_cast<Number>(_scost[i]));
kpeter@809
   700
      }
kpeter@809
   701
      return c;
kpeter@808
   702
    }
kpeter@808
   703
kpeter@809
   704
#ifndef DOXYGEN
kpeter@809
   705
    Cost totalCost() const {
kpeter@809
   706
      return totalCost<Cost>();
kpeter@808
   707
    }
kpeter@809
   708
#endif
kpeter@808
   709
kpeter@808
   710
    /// \brief Return the flow on the given arc.
kpeter@808
   711
    ///
kpeter@809
   712
    /// This function returns the flow on the given arc.
kpeter@808
   713
    ///
kpeter@808
   714
    /// \pre \ref run() must be called before using this function.
kpeter@809
   715
    Value flow(const Arc& a) const {
kpeter@809
   716
      return _res_cap[_arc_idb[a]];
kpeter@808
   717
    }
kpeter@808
   718
kpeter@809
   719
    /// \brief Return the flow map (the primal solution).
kpeter@808
   720
    ///
kpeter@809
   721
    /// This function copies the flow value on each arc into the given
kpeter@809
   722
    /// map. The \c Value type of the algorithm must be convertible to
kpeter@809
   723
    /// the \c Value type of the map.
kpeter@808
   724
    ///
kpeter@808
   725
    /// \pre \ref run() must be called before using this function.
kpeter@809
   726
    template <typename FlowMap>
kpeter@809
   727
    void flowMap(FlowMap &map) const {
kpeter@809
   728
      for (ArcIt a(_graph); a != INVALID; ++a) {
kpeter@809
   729
        map.set(a, _res_cap[_arc_idb[a]]);
kpeter@809
   730
      }
kpeter@808
   731
    }
kpeter@808
   732
kpeter@809
   733
    /// \brief Return the potential (dual value) of the given node.
kpeter@808
   734
    ///
kpeter@809
   735
    /// This function returns the potential (dual value) of the
kpeter@809
   736
    /// given node.
kpeter@808
   737
    ///
kpeter@808
   738
    /// \pre \ref run() must be called before using this function.
kpeter@809
   739
    Cost potential(const Node& n) const {
kpeter@809
   740
      return static_cast<Cost>(_pi[_node_id[n]]);
kpeter@809
   741
    }
kpeter@809
   742
kpeter@809
   743
    /// \brief Return the potential map (the dual solution).
kpeter@809
   744
    ///
kpeter@809
   745
    /// This function copies the potential (dual value) of each node
kpeter@809
   746
    /// into the given map.
kpeter@809
   747
    /// The \c Cost type of the algorithm must be convertible to the
kpeter@809
   748
    /// \c Value type of the map.
kpeter@809
   749
    ///
kpeter@809
   750
    /// \pre \ref run() must be called before using this function.
kpeter@809
   751
    template <typename PotentialMap>
kpeter@809
   752
    void potentialMap(PotentialMap &map) const {
kpeter@809
   753
      for (NodeIt n(_graph); n != INVALID; ++n) {
kpeter@809
   754
        map.set(n, static_cast<Cost>(_pi[_node_id[n]]));
kpeter@809
   755
      }
kpeter@808
   756
    }
kpeter@808
   757
kpeter@808
   758
    /// @}
kpeter@808
   759
kpeter@808
   760
  private:
kpeter@808
   761
kpeter@809
   762
    // Initialize the algorithm
kpeter@809
   763
    ProblemType init() {
kpeter@821
   764
      if (_res_node_num <= 1) return INFEASIBLE;
kpeter@809
   765
kpeter@809
   766
      // Check the sum of supply values
kpeter@809
   767
      _sum_supply = 0;
kpeter@809
   768
      for (int i = 0; i != _root; ++i) {
kpeter@809
   769
        _sum_supply += _supply[i];
kpeter@808
   770
      }
kpeter@809
   771
      if (_sum_supply > 0) return INFEASIBLE;
alpar@877
   772
kpeter@809
   773
kpeter@809
   774
      // Initialize vectors
kpeter@809
   775
      for (int i = 0; i != _res_node_num; ++i) {
kpeter@809
   776
        _pi[i] = 0;
kpeter@809
   777
        _excess[i] = _supply[i];
kpeter@809
   778
      }
alpar@877
   779
kpeter@809
   780
      // Remove infinite upper bounds and check negative arcs
kpeter@809
   781
      const Value MAX = std::numeric_limits<Value>::max();
kpeter@809
   782
      int last_out;
kpeter@809
   783
      if (_have_lower) {
kpeter@809
   784
        for (int i = 0; i != _root; ++i) {
kpeter@809
   785
          last_out = _first_out[i+1];
kpeter@809
   786
          for (int j = _first_out[i]; j != last_out; ++j) {
kpeter@809
   787
            if (_forward[j]) {
kpeter@809
   788
              Value c = _scost[j] < 0 ? _upper[j] : _lower[j];
kpeter@809
   789
              if (c >= MAX) return UNBOUNDED;
kpeter@809
   790
              _excess[i] -= c;
kpeter@809
   791
              _excess[_target[j]] += c;
kpeter@809
   792
            }
kpeter@809
   793
          }
kpeter@809
   794
        }
kpeter@809
   795
      } else {
kpeter@809
   796
        for (int i = 0; i != _root; ++i) {
kpeter@809
   797
          last_out = _first_out[i+1];
kpeter@809
   798
          for (int j = _first_out[i]; j != last_out; ++j) {
kpeter@809
   799
            if (_forward[j] && _scost[j] < 0) {
kpeter@809
   800
              Value c = _upper[j];
kpeter@809
   801
              if (c >= MAX) return UNBOUNDED;
kpeter@809
   802
              _excess[i] -= c;
kpeter@809
   803
              _excess[_target[j]] += c;
kpeter@809
   804
            }
kpeter@809
   805
          }
kpeter@809
   806
        }
kpeter@809
   807
      }
kpeter@809
   808
      Value ex, max_cap = 0;
kpeter@809
   809
      for (int i = 0; i != _res_node_num; ++i) {
kpeter@809
   810
        ex = _excess[i];
kpeter@809
   811
        _excess[i] = 0;
kpeter@809
   812
        if (ex < 0) max_cap -= ex;
kpeter@809
   813
      }
kpeter@809
   814
      for (int j = 0; j != _res_arc_num; ++j) {
kpeter@809
   815
        if (_upper[j] >= MAX) _upper[j] = max_cap;
kpeter@808
   816
      }
kpeter@808
   817
kpeter@809
   818
      // Initialize the large cost vector and the epsilon parameter
kpeter@809
   819
      _epsilon = 0;
kpeter@809
   820
      LargeCost lc;
kpeter@809
   821
      for (int i = 0; i != _root; ++i) {
kpeter@809
   822
        last_out = _first_out[i+1];
kpeter@809
   823
        for (int j = _first_out[i]; j != last_out; ++j) {
kpeter@809
   824
          lc = static_cast<LargeCost>(_scost[j]) * _res_node_num * _alpha;
kpeter@809
   825
          _cost[j] = lc;
kpeter@809
   826
          if (lc > _epsilon) _epsilon = lc;
kpeter@809
   827
        }
kpeter@809
   828
      }
kpeter@809
   829
      _epsilon /= _alpha;
kpeter@808
   830
kpeter@809
   831
      // Initialize maps for Circulation and remove non-zero lower bounds
kpeter@809
   832
      ConstMap<Arc, Value> low(0);
kpeter@809
   833
      typedef typename Digraph::template ArcMap<Value> ValueArcMap;
kpeter@809
   834
      typedef typename Digraph::template NodeMap<Value> ValueNodeMap;
kpeter@809
   835
      ValueArcMap cap(_graph), flow(_graph);
kpeter@809
   836
      ValueNodeMap sup(_graph);
kpeter@809
   837
      for (NodeIt n(_graph); n != INVALID; ++n) {
kpeter@809
   838
        sup[n] = _supply[_node_id[n]];
kpeter@808
   839
      }
kpeter@809
   840
      if (_have_lower) {
kpeter@809
   841
        for (ArcIt a(_graph); a != INVALID; ++a) {
kpeter@809
   842
          int j = _arc_idf[a];
kpeter@809
   843
          Value c = _lower[j];
kpeter@809
   844
          cap[a] = _upper[j] - c;
kpeter@809
   845
          sup[_graph.source(a)] -= c;
kpeter@809
   846
          sup[_graph.target(a)] += c;
kpeter@809
   847
        }
kpeter@809
   848
      } else {
kpeter@809
   849
        for (ArcIt a(_graph); a != INVALID; ++a) {
kpeter@809
   850
          cap[a] = _upper[_arc_idf[a]];
kpeter@809
   851
        }
kpeter@809
   852
      }
kpeter@808
   853
kpeter@839
   854
      _sup_node_num = 0;
kpeter@839
   855
      for (NodeIt n(_graph); n != INVALID; ++n) {
kpeter@839
   856
        if (sup[n] > 0) ++_sup_node_num;
kpeter@839
   857
      }
kpeter@839
   858
kpeter@808
   859
      // Find a feasible flow using Circulation
kpeter@809
   860
      Circulation<Digraph, ConstMap<Arc, Value>, ValueArcMap, ValueNodeMap>
kpeter@809
   861
        circ(_graph, low, cap, sup);
kpeter@809
   862
      if (!circ.flowMap(flow).run()) return INFEASIBLE;
kpeter@809
   863
kpeter@809
   864
      // Set residual capacities and handle GEQ supply type
kpeter@809
   865
      if (_sum_supply < 0) {
kpeter@809
   866
        for (ArcIt a(_graph); a != INVALID; ++a) {
kpeter@809
   867
          Value fa = flow[a];
kpeter@809
   868
          _res_cap[_arc_idf[a]] = cap[a] - fa;
kpeter@809
   869
          _res_cap[_arc_idb[a]] = fa;
kpeter@809
   870
          sup[_graph.source(a)] -= fa;
kpeter@809
   871
          sup[_graph.target(a)] += fa;
kpeter@809
   872
        }
kpeter@809
   873
        for (NodeIt n(_graph); n != INVALID; ++n) {
kpeter@809
   874
          _excess[_node_id[n]] = sup[n];
kpeter@809
   875
        }
kpeter@809
   876
        for (int a = _first_out[_root]; a != _res_arc_num; ++a) {
kpeter@809
   877
          int u = _target[a];
kpeter@809
   878
          int ra = _reverse[a];
kpeter@809
   879
          _res_cap[a] = -_sum_supply + 1;
kpeter@809
   880
          _res_cap[ra] = -_excess[u];
kpeter@809
   881
          _cost[a] = 0;
kpeter@809
   882
          _cost[ra] = 0;
kpeter@809
   883
          _excess[u] = 0;
kpeter@809
   884
        }
kpeter@809
   885
      } else {
kpeter@809
   886
        for (ArcIt a(_graph); a != INVALID; ++a) {
kpeter@809
   887
          Value fa = flow[a];
kpeter@809
   888
          _res_cap[_arc_idf[a]] = cap[a] - fa;
kpeter@809
   889
          _res_cap[_arc_idb[a]] = fa;
kpeter@809
   890
        }
kpeter@809
   891
        for (int a = _first_out[_root]; a != _res_arc_num; ++a) {
kpeter@809
   892
          int ra = _reverse[a];
kpeter@839
   893
          _res_cap[a] = 0;
kpeter@809
   894
          _res_cap[ra] = 0;
kpeter@809
   895
          _cost[a] = 0;
kpeter@809
   896
          _cost[ra] = 0;
kpeter@809
   897
        }
kpeter@809
   898
      }
alpar@877
   899
alpar@877
   900
      // Initialize data structures for buckets
kpeter@839
   901
      _max_rank = _alpha * _res_node_num;
kpeter@839
   902
      _buckets.resize(_max_rank);
kpeter@839
   903
      _bucket_next.resize(_res_node_num + 1);
kpeter@839
   904
      _bucket_prev.resize(_res_node_num + 1);
kpeter@839
   905
      _rank.resize(_res_node_num + 1);
alpar@877
   906
kpeter@934
   907
      return OPTIMAL;
kpeter@934
   908
    }
kpeter@934
   909
kpeter@934
   910
    // Execute the algorithm and transform the results
kpeter@934
   911
    void start(Method method) {
kpeter@934
   912
      const int MAX_PARTIAL_PATH_LENGTH = 4;
kpeter@934
   913
kpeter@810
   914
      switch (method) {
kpeter@810
   915
        case PUSH:
kpeter@810
   916
          startPush();
kpeter@810
   917
          break;
kpeter@810
   918
        case AUGMENT:
kpeter@931
   919
          startAugment(_res_node_num - 1);
kpeter@810
   920
          break;
kpeter@810
   921
        case PARTIAL_AUGMENT:
kpeter@934
   922
          startAugment(MAX_PARTIAL_PATH_LENGTH);
kpeter@810
   923
          break;
kpeter@809
   924
      }
kpeter@809
   925
kpeter@809
   926
      // Compute node potentials for the original costs
kpeter@809
   927
      _arc_vec.clear();
kpeter@809
   928
      _cost_vec.clear();
kpeter@809
   929
      for (int j = 0; j != _res_arc_num; ++j) {
kpeter@809
   930
        if (_res_cap[j] > 0) {
kpeter@809
   931
          _arc_vec.push_back(IntPair(_source[j], _target[j]));
kpeter@809
   932
          _cost_vec.push_back(_scost[j]);
kpeter@809
   933
        }
kpeter@809
   934
      }
kpeter@809
   935
      _sgr.build(_res_node_num, _arc_vec.begin(), _arc_vec.end());
kpeter@809
   936
kpeter@809
   937
      typename BellmanFord<StaticDigraph, LargeCostArcMap>
kpeter@809
   938
        ::template SetDistMap<LargeCostNodeMap>::Create bf(_sgr, _cost_map);
kpeter@809
   939
      bf.distMap(_pi_map);
kpeter@809
   940
      bf.init(0);
kpeter@809
   941
      bf.start();
kpeter@809
   942
kpeter@809
   943
      // Handle non-zero lower bounds
kpeter@809
   944
      if (_have_lower) {
kpeter@809
   945
        int limit = _first_out[_root];
kpeter@809
   946
        for (int j = 0; j != limit; ++j) {
kpeter@809
   947
          if (!_forward[j]) _res_cap[j] += _lower[j];
kpeter@809
   948
        }
kpeter@809
   949
      }
kpeter@808
   950
    }
alpar@877
   951
kpeter@839
   952
    // Initialize a cost scaling phase
kpeter@839
   953
    void initPhase() {
kpeter@839
   954
      // Saturate arcs not satisfying the optimality condition
kpeter@839
   955
      for (int u = 0; u != _res_node_num; ++u) {
kpeter@839
   956
        int last_out = _first_out[u+1];
kpeter@839
   957
        LargeCost pi_u = _pi[u];
kpeter@839
   958
        for (int a = _first_out[u]; a != last_out; ++a) {
kpeter@934
   959
          Value delta = _res_cap[a];
kpeter@934
   960
          if (delta > 0) {
kpeter@934
   961
            int v = _target[a];
kpeter@934
   962
            if (_cost[a] + pi_u - _pi[v] < 0) {
kpeter@934
   963
              _excess[u] -= delta;
kpeter@934
   964
              _excess[v] += delta;
kpeter@934
   965
              _res_cap[a] = 0;
kpeter@934
   966
              _res_cap[_reverse[a]] += delta;
kpeter@934
   967
            }
kpeter@839
   968
          }
kpeter@839
   969
        }
kpeter@839
   970
      }
alpar@877
   971
kpeter@839
   972
      // Find active nodes (i.e. nodes with positive excess)
kpeter@839
   973
      for (int u = 0; u != _res_node_num; ++u) {
kpeter@839
   974
        if (_excess[u] > 0) _active_nodes.push_back(u);
kpeter@839
   975
      }
kpeter@839
   976
kpeter@839
   977
      // Initialize the next arcs
kpeter@839
   978
      for (int u = 0; u != _res_node_num; ++u) {
kpeter@839
   979
        _next_out[u] = _first_out[u];
kpeter@839
   980
      }
kpeter@839
   981
    }
alpar@877
   982
kpeter@936
   983
    // Price (potential) refinement heuristic
kpeter@936
   984
    bool priceRefinement() {
kpeter@839
   985
kpeter@936
   986
      // Stack for stroing the topological order
kpeter@936
   987
      IntVector stack(_res_node_num);
kpeter@936
   988
      int stack_top;
kpeter@936
   989
kpeter@936
   990
      // Perform phases
kpeter@936
   991
      while (topologicalSort(stack, stack_top)) {
kpeter@936
   992
kpeter@936
   993
        // Compute node ranks in the acyclic admissible network and
kpeter@936
   994
        // store the nodes in buckets
kpeter@936
   995
        for (int i = 0; i != _res_node_num; ++i) {
kpeter@936
   996
          _rank[i] = 0;
kpeter@839
   997
        }
kpeter@936
   998
        const int bucket_end = _root + 1;
kpeter@936
   999
        for (int r = 0; r != _max_rank; ++r) {
kpeter@936
  1000
          _buckets[r] = bucket_end;
kpeter@936
  1001
        }
kpeter@936
  1002
        int top_rank = 0;
kpeter@936
  1003
        for ( ; stack_top >= 0; --stack_top) {
kpeter@936
  1004
          int u = stack[stack_top], v;
kpeter@936
  1005
          int rank_u = _rank[u];
kpeter@936
  1006
kpeter@936
  1007
          LargeCost rc, pi_u = _pi[u];
kpeter@936
  1008
          int last_out = _first_out[u+1];
kpeter@936
  1009
          for (int a = _first_out[u]; a != last_out; ++a) {
kpeter@936
  1010
            if (_res_cap[a] > 0) {
kpeter@936
  1011
              v = _target[a];
kpeter@936
  1012
              rc = _cost[a] + pi_u - _pi[v];
kpeter@936
  1013
              if (rc < 0) {
kpeter@936
  1014
                LargeCost nrc = static_cast<LargeCost>((-rc - 0.5) / _epsilon);
kpeter@936
  1015
                if (nrc < LargeCost(_max_rank)) {
kpeter@936
  1016
                  int new_rank_v = rank_u + static_cast<int>(nrc);
kpeter@936
  1017
                  if (new_rank_v > _rank[v]) {
kpeter@936
  1018
                    _rank[v] = new_rank_v;
kpeter@936
  1019
                  }
kpeter@936
  1020
                }
kpeter@936
  1021
              }
kpeter@936
  1022
            }
kpeter@936
  1023
          }
kpeter@936
  1024
kpeter@936
  1025
          if (rank_u > 0) {
kpeter@936
  1026
            top_rank = std::max(top_rank, rank_u);
kpeter@936
  1027
            int bfirst = _buckets[rank_u];
kpeter@936
  1028
            _bucket_next[u] = bfirst;
kpeter@936
  1029
            _bucket_prev[bfirst] = u;
kpeter@936
  1030
            _buckets[rank_u] = u;
kpeter@936
  1031
          }
kpeter@936
  1032
        }
kpeter@936
  1033
kpeter@936
  1034
        // Check if the current flow is epsilon-optimal
kpeter@936
  1035
        if (top_rank == 0) {
kpeter@936
  1036
          return true;
kpeter@936
  1037
        }
kpeter@936
  1038
kpeter@936
  1039
        // Process buckets in top-down order
kpeter@936
  1040
        for (int rank = top_rank; rank > 0; --rank) {
kpeter@936
  1041
          while (_buckets[rank] != bucket_end) {
kpeter@936
  1042
            // Remove the first node from the current bucket
kpeter@936
  1043
            int u = _buckets[rank];
kpeter@936
  1044
            _buckets[rank] = _bucket_next[u];
kpeter@936
  1045
kpeter@936
  1046
            // Search the outgoing arcs of u
kpeter@936
  1047
            LargeCost rc, pi_u = _pi[u];
kpeter@936
  1048
            int last_out = _first_out[u+1];
kpeter@936
  1049
            int v, old_rank_v, new_rank_v;
kpeter@936
  1050
            for (int a = _first_out[u]; a != last_out; ++a) {
kpeter@936
  1051
              if (_res_cap[a] > 0) {
kpeter@936
  1052
                v = _target[a];
kpeter@936
  1053
                old_rank_v = _rank[v];
kpeter@936
  1054
kpeter@936
  1055
                if (old_rank_v < rank) {
kpeter@936
  1056
kpeter@936
  1057
                  // Compute the new rank of node v
kpeter@936
  1058
                  rc = _cost[a] + pi_u - _pi[v];
kpeter@936
  1059
                  if (rc < 0) {
kpeter@936
  1060
                    new_rank_v = rank;
kpeter@936
  1061
                  } else {
kpeter@936
  1062
                    LargeCost nrc = rc / _epsilon;
kpeter@936
  1063
                    new_rank_v = 0;
kpeter@936
  1064
                    if (nrc < LargeCost(_max_rank)) {
kpeter@936
  1065
                      new_rank_v = rank - 1 - static_cast<int>(nrc);
kpeter@936
  1066
                    }
kpeter@936
  1067
                  }
kpeter@936
  1068
kpeter@936
  1069
                  // Change the rank of node v
kpeter@936
  1070
                  if (new_rank_v > old_rank_v) {
kpeter@936
  1071
                    _rank[v] = new_rank_v;
kpeter@936
  1072
kpeter@936
  1073
                    // Remove v from its old bucket
kpeter@936
  1074
                    if (old_rank_v > 0) {
kpeter@936
  1075
                      if (_buckets[old_rank_v] == v) {
kpeter@936
  1076
                        _buckets[old_rank_v] = _bucket_next[v];
kpeter@936
  1077
                      } else {
kpeter@936
  1078
                        int pv = _bucket_prev[v], nv = _bucket_next[v];
kpeter@936
  1079
                        _bucket_next[pv] = nv;
kpeter@936
  1080
                        _bucket_prev[nv] = pv;
kpeter@936
  1081
                      }
kpeter@936
  1082
                    }
kpeter@936
  1083
kpeter@936
  1084
                    // Insert v into its new bucket
kpeter@936
  1085
                    int nv = _buckets[new_rank_v];
kpeter@936
  1086
                    _bucket_next[v] = nv;
kpeter@936
  1087
                    _bucket_prev[nv] = v;
kpeter@936
  1088
                    _buckets[new_rank_v] = v;
kpeter@936
  1089
                  }
kpeter@936
  1090
                }
kpeter@936
  1091
              }
kpeter@936
  1092
            }
kpeter@936
  1093
kpeter@936
  1094
            // Refine potential of node u
kpeter@936
  1095
            _pi[u] -= rank * _epsilon;
kpeter@936
  1096
          }
kpeter@936
  1097
        }
kpeter@936
  1098
kpeter@839
  1099
      }
kpeter@839
  1100
kpeter@936
  1101
      return false;
kpeter@936
  1102
    }
kpeter@936
  1103
kpeter@936
  1104
    // Find and cancel cycles in the admissible network and
kpeter@936
  1105
    // determine topological order using DFS
kpeter@936
  1106
    bool topologicalSort(IntVector &stack, int &stack_top) {
kpeter@936
  1107
      const int MAX_CYCLE_CANCEL = 1;
kpeter@936
  1108
kpeter@936
  1109
      BoolVector reached(_res_node_num, false);
kpeter@936
  1110
      BoolVector processed(_res_node_num, false);
kpeter@936
  1111
      IntVector pred(_res_node_num);
kpeter@936
  1112
      for (int i = 0; i != _res_node_num; ++i) {
kpeter@936
  1113
        _next_out[i] = _first_out[i];
kpeter@839
  1114
      }
kpeter@936
  1115
      stack_top = -1;
kpeter@936
  1116
kpeter@936
  1117
      int cycle_cnt = 0;
kpeter@936
  1118
      for (int start = 0; start != _res_node_num; ++start) {
kpeter@936
  1119
        if (reached[start]) continue;
kpeter@936
  1120
kpeter@936
  1121
        // Start DFS search from this start node
kpeter@936
  1122
        pred[start] = -1;
kpeter@936
  1123
        int tip = start, v;
kpeter@936
  1124
        while (true) {
kpeter@936
  1125
          // Check the outgoing arcs of the current tip node
kpeter@936
  1126
          reached[tip] = true;
kpeter@936
  1127
          LargeCost pi_tip = _pi[tip];
kpeter@936
  1128
          int a, last_out = _first_out[tip+1];
kpeter@936
  1129
          for (a = _next_out[tip]; a != last_out; ++a) {
kpeter@936
  1130
            if (_res_cap[a] > 0) {
kpeter@936
  1131
              v = _target[a];
kpeter@936
  1132
              if (_cost[a] + pi_tip - _pi[v] < 0) {
kpeter@936
  1133
                if (!reached[v]) {
kpeter@936
  1134
                  // A new node is reached
kpeter@936
  1135
                  reached[v] = true;
kpeter@936
  1136
                  pred[v] = tip;
kpeter@936
  1137
                  _next_out[tip] = a;
kpeter@936
  1138
                  tip = v;
kpeter@936
  1139
                  a = _next_out[tip];
kpeter@936
  1140
                  last_out = _first_out[tip+1];
kpeter@936
  1141
                  break;
kpeter@936
  1142
                }
kpeter@936
  1143
                else if (!processed[v]) {
kpeter@936
  1144
                  // A cycle is found
kpeter@936
  1145
                  ++cycle_cnt;
kpeter@936
  1146
                  _next_out[tip] = a;
kpeter@936
  1147
kpeter@936
  1148
                  // Find the minimum residual capacity along the cycle
kpeter@936
  1149
                  Value d, delta = _res_cap[a];
kpeter@936
  1150
                  int u, delta_node = tip;
kpeter@936
  1151
                  for (u = tip; u != v; ) {
kpeter@936
  1152
                    u = pred[u];
kpeter@936
  1153
                    d = _res_cap[_next_out[u]];
kpeter@936
  1154
                    if (d <= delta) {
kpeter@936
  1155
                      delta = d;
kpeter@936
  1156
                      delta_node = u;
kpeter@936
  1157
                    }
kpeter@936
  1158
                  }
kpeter@936
  1159
kpeter@936
  1160
                  // Augment along the cycle
kpeter@936
  1161
                  _res_cap[a] -= delta;
kpeter@936
  1162
                  _res_cap[_reverse[a]] += delta;
kpeter@936
  1163
                  for (u = tip; u != v; ) {
kpeter@936
  1164
                    u = pred[u];
kpeter@936
  1165
                    int ca = _next_out[u];
kpeter@936
  1166
                    _res_cap[ca] -= delta;
kpeter@936
  1167
                    _res_cap[_reverse[ca]] += delta;
kpeter@936
  1168
                  }
kpeter@936
  1169
kpeter@936
  1170
                  // Check the maximum number of cycle canceling
kpeter@936
  1171
                  if (cycle_cnt >= MAX_CYCLE_CANCEL) {
kpeter@936
  1172
                    return false;
kpeter@936
  1173
                  }
kpeter@936
  1174
kpeter@936
  1175
                  // Roll back search to delta_node
kpeter@936
  1176
                  if (delta_node != tip) {
kpeter@936
  1177
                    for (u = tip; u != delta_node; u = pred[u]) {
kpeter@936
  1178
                      reached[u] = false;
kpeter@936
  1179
                    }
kpeter@936
  1180
                    tip = delta_node;
kpeter@936
  1181
                    a = _next_out[tip] + 1;
kpeter@936
  1182
                    last_out = _first_out[tip+1];
kpeter@936
  1183
                    break;
kpeter@936
  1184
                  }
kpeter@936
  1185
                }
kpeter@936
  1186
              }
kpeter@936
  1187
            }
kpeter@936
  1188
          }
kpeter@936
  1189
kpeter@936
  1190
          // Step back to the previous node
kpeter@936
  1191
          if (a == last_out) {
kpeter@936
  1192
            processed[tip] = true;
kpeter@936
  1193
            stack[++stack_top] = tip;
kpeter@936
  1194
            tip = pred[tip];
kpeter@936
  1195
            if (tip < 0) {
kpeter@936
  1196
              // Finish DFS from the current start node
kpeter@936
  1197
              break;
kpeter@936
  1198
            }
kpeter@936
  1199
            ++_next_out[tip];
kpeter@936
  1200
          }
kpeter@936
  1201
        }
kpeter@936
  1202
kpeter@936
  1203
      }
kpeter@936
  1204
kpeter@936
  1205
      return (cycle_cnt == 0);
kpeter@839
  1206
    }
kpeter@839
  1207
kpeter@839
  1208
    // Global potential update heuristic
kpeter@839
  1209
    void globalUpdate() {
kpeter@934
  1210
      const int bucket_end = _root + 1;
alpar@877
  1211
kpeter@839
  1212
      // Initialize buckets
kpeter@839
  1213
      for (int r = 0; r != _max_rank; ++r) {
kpeter@839
  1214
        _buckets[r] = bucket_end;
kpeter@839
  1215
      }
kpeter@839
  1216
      Value total_excess = 0;
kpeter@934
  1217
      int b0 = bucket_end;
kpeter@839
  1218
      for (int i = 0; i != _res_node_num; ++i) {
kpeter@839
  1219
        if (_excess[i] < 0) {
kpeter@839
  1220
          _rank[i] = 0;
kpeter@934
  1221
          _bucket_next[i] = b0;
kpeter@934
  1222
          _bucket_prev[b0] = i;
kpeter@934
  1223
          b0 = i;
kpeter@839
  1224
        } else {
kpeter@839
  1225
          total_excess += _excess[i];
kpeter@839
  1226
          _rank[i] = _max_rank;
kpeter@839
  1227
        }
kpeter@839
  1228
      }
kpeter@839
  1229
      if (total_excess == 0) return;
kpeter@934
  1230
      _buckets[0] = b0;
kpeter@839
  1231
kpeter@839
  1232
      // Search the buckets
kpeter@839
  1233
      int r = 0;
kpeter@839
  1234
      for ( ; r != _max_rank; ++r) {
kpeter@839
  1235
        while (_buckets[r] != bucket_end) {
kpeter@839
  1236
          // Remove the first node from the current bucket
kpeter@839
  1237
          int u = _buckets[r];
kpeter@839
  1238
          _buckets[r] = _bucket_next[u];
alpar@877
  1239
kpeter@839
  1240
          // Search the incomming arcs of u
kpeter@839
  1241
          LargeCost pi_u = _pi[u];
kpeter@839
  1242
          int last_out = _first_out[u+1];
kpeter@839
  1243
          for (int a = _first_out[u]; a != last_out; ++a) {
kpeter@839
  1244
            int ra = _reverse[a];
kpeter@839
  1245
            if (_res_cap[ra] > 0) {
kpeter@839
  1246
              int v = _source[ra];
kpeter@839
  1247
              int old_rank_v = _rank[v];
kpeter@839
  1248
              if (r < old_rank_v) {
kpeter@839
  1249
                // Compute the new rank of v
kpeter@839
  1250
                LargeCost nrc = (_cost[ra] + _pi[v] - pi_u) / _epsilon;
kpeter@839
  1251
                int new_rank_v = old_rank_v;
kpeter@934
  1252
                if (nrc < LargeCost(_max_rank)) {
kpeter@934
  1253
                  new_rank_v = r + 1 + static_cast<int>(nrc);
kpeter@934
  1254
                }
alpar@877
  1255
kpeter@839
  1256
                // Change the rank of v
kpeter@839
  1257
                if (new_rank_v < old_rank_v) {
kpeter@839
  1258
                  _rank[v] = new_rank_v;
kpeter@839
  1259
                  _next_out[v] = _first_out[v];
alpar@877
  1260
kpeter@839
  1261
                  // Remove v from its old bucket
kpeter@839
  1262
                  if (old_rank_v < _max_rank) {
kpeter@839
  1263
                    if (_buckets[old_rank_v] == v) {
kpeter@839
  1264
                      _buckets[old_rank_v] = _bucket_next[v];
kpeter@839
  1265
                    } else {
kpeter@934
  1266
                      int pv = _bucket_prev[v], nv = _bucket_next[v];
kpeter@934
  1267
                      _bucket_next[pv] = nv;
kpeter@934
  1268
                      _bucket_prev[nv] = pv;
kpeter@839
  1269
                    }
kpeter@839
  1270
                  }
alpar@877
  1271
kpeter@934
  1272
                  // Insert v into its new bucket
kpeter@934
  1273
                  int nv = _buckets[new_rank_v];
kpeter@934
  1274
                  _bucket_next[v] = nv;
kpeter@934
  1275
                  _bucket_prev[nv] = v;
kpeter@839
  1276
                  _buckets[new_rank_v] = v;
kpeter@839
  1277
                }
kpeter@839
  1278
              }
kpeter@839
  1279
            }
kpeter@839
  1280
          }
kpeter@839
  1281
kpeter@839
  1282
          // Finish search if there are no more active nodes
kpeter@839
  1283
          if (_excess[u] > 0) {
kpeter@839
  1284
            total_excess -= _excess[u];
kpeter@839
  1285
            if (total_excess <= 0) break;
kpeter@839
  1286
          }
kpeter@839
  1287
        }
kpeter@839
  1288
        if (total_excess <= 0) break;
kpeter@839
  1289
      }
alpar@877
  1290
kpeter@839
  1291
      // Relabel nodes
kpeter@839
  1292
      for (int u = 0; u != _res_node_num; ++u) {
kpeter@839
  1293
        int k = std::min(_rank[u], r);
kpeter@839
  1294
        if (k > 0) {
kpeter@839
  1295
          _pi[u] -= _epsilon * k;
kpeter@839
  1296
          _next_out[u] = _first_out[u];
kpeter@839
  1297
        }
kpeter@839
  1298
      }
kpeter@839
  1299
    }
kpeter@808
  1300
kpeter@810
  1301
    /// Execute the algorithm performing augment and relabel operations
kpeter@931
  1302
    void startAugment(int max_length) {
kpeter@808
  1303
      // Paramters for heuristics
kpeter@936
  1304
      const int PRICE_REFINEMENT_LIMIT = 2;
kpeter@935
  1305
      const double GLOBAL_UPDATE_FACTOR = 1.0;
kpeter@935
  1306
      const int global_update_skip = static_cast<int>(GLOBAL_UPDATE_FACTOR *
kpeter@839
  1307
        (_res_node_num + _sup_node_num * _sup_node_num));
kpeter@935
  1308
      int next_global_update_limit = global_update_skip;
alpar@877
  1309
kpeter@809
  1310
      // Perform cost scaling phases
kpeter@935
  1311
      IntVector path;
kpeter@935
  1312
      BoolVector path_arc(_res_arc_num, false);
kpeter@935
  1313
      int relabel_cnt = 0;
kpeter@936
  1314
      int eps_phase_cnt = 0;
kpeter@808
  1315
      for ( ; _epsilon >= 1; _epsilon = _epsilon < _alpha && _epsilon > 1 ?
kpeter@808
  1316
                                        1 : _epsilon / _alpha )
kpeter@808
  1317
      {
kpeter@936
  1318
        ++eps_phase_cnt;
kpeter@936
  1319
kpeter@936
  1320
        // Price refinement heuristic
kpeter@936
  1321
        if (eps_phase_cnt >= PRICE_REFINEMENT_LIMIT) {
kpeter@936
  1322
          if (priceRefinement()) continue;
kpeter@808
  1323
        }
alpar@877
  1324
kpeter@839
  1325
        // Initialize current phase
kpeter@839
  1326
        initPhase();
alpar@877
  1327
kpeter@808
  1328
        // Perform partial augment and relabel operations
kpeter@809
  1329
        while (true) {
kpeter@808
  1330
          // Select an active node (FIFO selection)
kpeter@809
  1331
          while (_active_nodes.size() > 0 &&
kpeter@809
  1332
                 _excess[_active_nodes.front()] <= 0) {
kpeter@809
  1333
            _active_nodes.pop_front();
kpeter@808
  1334
          }
kpeter@809
  1335
          if (_active_nodes.size() == 0) break;
kpeter@809
  1336
          int start = _active_nodes.front();
kpeter@808
  1337
kpeter@808
  1338
          // Find an augmenting path from the start node
kpeter@809
  1339
          int tip = start;
kpeter@935
  1340
          while (int(path.size()) < max_length && _excess[tip] >= 0) {
kpeter@809
  1341
            int u;
kpeter@935
  1342
            LargeCost rc, min_red_cost = std::numeric_limits<LargeCost>::max();
kpeter@935
  1343
            LargeCost pi_tip = _pi[tip];
kpeter@839
  1344
            int last_out = _first_out[tip+1];
kpeter@809
  1345
            for (int a = _next_out[tip]; a != last_out; ++a) {
kpeter@935
  1346
              if (_res_cap[a] > 0) {
kpeter@935
  1347
                u = _target[a];
kpeter@935
  1348
                rc = _cost[a] + pi_tip - _pi[u];
kpeter@935
  1349
                if (rc < 0) {
kpeter@935
  1350
                  path.push_back(a);
kpeter@935
  1351
                  _next_out[tip] = a;
kpeter@935
  1352
                  if (path_arc[a]) {
kpeter@935
  1353
                    goto augment;   // a cycle is found, stop path search
kpeter@935
  1354
                  }
kpeter@935
  1355
                  tip = u;
kpeter@935
  1356
                  path_arc[a] = true;
kpeter@935
  1357
                  goto next_step;
kpeter@935
  1358
                }
kpeter@935
  1359
                else if (rc < min_red_cost) {
kpeter@935
  1360
                  min_red_cost = rc;
kpeter@935
  1361
                }
kpeter@808
  1362
              }
kpeter@808
  1363
            }
kpeter@808
  1364
kpeter@808
  1365
            // Relabel tip node
kpeter@839
  1366
            if (tip != start) {
kpeter@839
  1367
              int ra = _reverse[path.back()];
kpeter@935
  1368
              min_red_cost =
kpeter@935
  1369
                std::min(min_red_cost, _cost[ra] + pi_tip - _pi[_target[ra]]);
kpeter@839
  1370
            }
kpeter@935
  1371
            last_out = _next_out[tip];
kpeter@809
  1372
            for (int a = _first_out[tip]; a != last_out; ++a) {
kpeter@935
  1373
              if (_res_cap[a] > 0) {
kpeter@935
  1374
                rc = _cost[a] + pi_tip - _pi[_target[a]];
kpeter@935
  1375
                if (rc < min_red_cost) {
kpeter@935
  1376
                  min_red_cost = rc;
kpeter@935
  1377
                }
kpeter@809
  1378
              }
kpeter@808
  1379
            }
kpeter@809
  1380
            _pi[tip] -= min_red_cost + _epsilon;
kpeter@809
  1381
            _next_out[tip] = _first_out[tip];
kpeter@839
  1382
            ++relabel_cnt;
kpeter@808
  1383
kpeter@808
  1384
            // Step back
kpeter@808
  1385
            if (tip != start) {
kpeter@935
  1386
              int pa = path.back();
kpeter@935
  1387
              path_arc[pa] = false;
kpeter@935
  1388
              tip = _source[pa];
kpeter@839
  1389
              path.pop_back();
kpeter@808
  1390
            }
kpeter@808
  1391
kpeter@809
  1392
          next_step: ;
kpeter@808
  1393
          }
kpeter@808
  1394
kpeter@808
  1395
          // Augment along the found path (as much flow as possible)
kpeter@935
  1396
        augment:
kpeter@809
  1397
          Value delta;
kpeter@839
  1398
          int pa, u, v = start;
kpeter@839
  1399
          for (int i = 0; i != int(path.size()); ++i) {
kpeter@839
  1400
            pa = path[i];
kpeter@809
  1401
            u = v;
kpeter@839
  1402
            v = _target[pa];
kpeter@935
  1403
            path_arc[pa] = false;
kpeter@809
  1404
            delta = std::min(_res_cap[pa], _excess[u]);
kpeter@809
  1405
            _res_cap[pa] -= delta;
kpeter@809
  1406
            _res_cap[_reverse[pa]] += delta;
kpeter@809
  1407
            _excess[u] -= delta;
kpeter@809
  1408
            _excess[v] += delta;
kpeter@935
  1409
            if (_excess[v] > 0 && _excess[v] <= delta) {
kpeter@809
  1410
              _active_nodes.push_back(v);
kpeter@935
  1411
            }
kpeter@808
  1412
          }
kpeter@935
  1413
          path.clear();
kpeter@839
  1414
kpeter@839
  1415
          // Global update heuristic
kpeter@935
  1416
          if (relabel_cnt >= next_global_update_limit) {
kpeter@839
  1417
            globalUpdate();
kpeter@935
  1418
            next_global_update_limit += global_update_skip;
kpeter@839
  1419
          }
kpeter@808
  1420
        }
kpeter@935
  1421
kpeter@808
  1422
      }
kpeter@935
  1423
kpeter@808
  1424
    }
kpeter@808
  1425
kpeter@809
  1426
    /// Execute the algorithm performing push and relabel operations
kpeter@810
  1427
    void startPush() {
kpeter@808
  1428
      // Paramters for heuristics
kpeter@936
  1429
      const int PRICE_REFINEMENT_LIMIT = 2;
kpeter@839
  1430
      const double GLOBAL_UPDATE_FACTOR = 2.0;
kpeter@808
  1431
kpeter@935
  1432
      const int global_update_skip = static_cast<int>(GLOBAL_UPDATE_FACTOR *
kpeter@839
  1433
        (_res_node_num + _sup_node_num * _sup_node_num));
kpeter@935
  1434
      int next_global_update_limit = global_update_skip;
alpar@877
  1435
kpeter@809
  1436
      // Perform cost scaling phases
kpeter@809
  1437
      BoolVector hyper(_res_node_num, false);
kpeter@839
  1438
      LargeCostVector hyper_cost(_res_node_num);
kpeter@935
  1439
      int relabel_cnt = 0;
kpeter@936
  1440
      int eps_phase_cnt = 0;
kpeter@808
  1441
      for ( ; _epsilon >= 1; _epsilon = _epsilon < _alpha && _epsilon > 1 ?
kpeter@808
  1442
                                        1 : _epsilon / _alpha )
kpeter@808
  1443
      {
kpeter@936
  1444
        ++eps_phase_cnt;
kpeter@936
  1445
kpeter@936
  1446
        // Price refinement heuristic
kpeter@936
  1447
        if (eps_phase_cnt >= PRICE_REFINEMENT_LIMIT) {
kpeter@936
  1448
          if (priceRefinement()) continue;
kpeter@808
  1449
        }
alpar@877
  1450
kpeter@839
  1451
        // Initialize current phase
kpeter@839
  1452
        initPhase();
kpeter@808
  1453
kpeter@808
  1454
        // Perform push and relabel operations
kpeter@809
  1455
        while (_active_nodes.size() > 0) {
kpeter@839
  1456
          LargeCost min_red_cost, rc, pi_n;
kpeter@809
  1457
          Value delta;
kpeter@809
  1458
          int n, t, a, last_out = _res_arc_num;
kpeter@809
  1459
kpeter@839
  1460
        next_node:
kpeter@808
  1461
          // Select an active node (FIFO selection)
kpeter@809
  1462
          n = _active_nodes.front();
kpeter@839
  1463
          last_out = _first_out[n+1];
kpeter@839
  1464
          pi_n = _pi[n];
alpar@877
  1465
kpeter@808
  1466
          // Perform push operations if there are admissible arcs
kpeter@809
  1467
          if (_excess[n] > 0) {
kpeter@809
  1468
            for (a = _next_out[n]; a != last_out; ++a) {
kpeter@809
  1469
              if (_res_cap[a] > 0 &&
kpeter@839
  1470
                  _cost[a] + pi_n - _pi[_target[a]] < 0) {
kpeter@809
  1471
                delta = std::min(_res_cap[a], _excess[n]);
kpeter@809
  1472
                t = _target[a];
kpeter@808
  1473
kpeter@808
  1474
                // Push-look-ahead heuristic
kpeter@809
  1475
                Value ahead = -_excess[t];
kpeter@839
  1476
                int last_out_t = _first_out[t+1];
kpeter@839
  1477
                LargeCost pi_t = _pi[t];
kpeter@809
  1478
                for (int ta = _next_out[t]; ta != last_out_t; ++ta) {
alpar@877
  1479
                  if (_res_cap[ta] > 0 &&
kpeter@839
  1480
                      _cost[ta] + pi_t - _pi[_target[ta]] < 0)
kpeter@809
  1481
                    ahead += _res_cap[ta];
kpeter@809
  1482
                  if (ahead >= delta) break;
kpeter@808
  1483
                }
kpeter@808
  1484
                if (ahead < 0) ahead = 0;
kpeter@808
  1485
kpeter@808
  1486
                // Push flow along the arc
kpeter@839
  1487
                if (ahead < delta && !hyper[t]) {
kpeter@809
  1488
                  _res_cap[a] -= ahead;
kpeter@809
  1489
                  _res_cap[_reverse[a]] += ahead;
kpeter@808
  1490
                  _excess[n] -= ahead;
kpeter@808
  1491
                  _excess[t] += ahead;
kpeter@809
  1492
                  _active_nodes.push_front(t);
kpeter@808
  1493
                  hyper[t] = true;
kpeter@839
  1494
                  hyper_cost[t] = _cost[a] + pi_n - pi_t;
kpeter@809
  1495
                  _next_out[n] = a;
kpeter@809
  1496
                  goto next_node;
kpeter@808
  1497
                } else {
kpeter@809
  1498
                  _res_cap[a] -= delta;
kpeter@809
  1499
                  _res_cap[_reverse[a]] += delta;
kpeter@808
  1500
                  _excess[n] -= delta;
kpeter@808
  1501
                  _excess[t] += delta;
kpeter@808
  1502
                  if (_excess[t] > 0 && _excess[t] <= delta)
kpeter@809
  1503
                    _active_nodes.push_back(t);
kpeter@808
  1504
                }
kpeter@808
  1505
kpeter@809
  1506
                if (_excess[n] == 0) {
kpeter@809
  1507
                  _next_out[n] = a;
kpeter@809
  1508
                  goto remove_nodes;
kpeter@809
  1509
                }
kpeter@808
  1510
              }
kpeter@808
  1511
            }
kpeter@809
  1512
            _next_out[n] = a;
kpeter@808
  1513
          }
kpeter@808
  1514
kpeter@808
  1515
          // Relabel the node if it is still active (or hyper)
kpeter@809
  1516
          if (_excess[n] > 0 || hyper[n]) {
kpeter@839
  1517
             min_red_cost = hyper[n] ? -hyper_cost[n] :
kpeter@839
  1518
               std::numeric_limits<LargeCost>::max();
kpeter@809
  1519
            for (int a = _first_out[n]; a != last_out; ++a) {
kpeter@935
  1520
              if (_res_cap[a] > 0) {
kpeter@935
  1521
                rc = _cost[a] + pi_n - _pi[_target[a]];
kpeter@935
  1522
                if (rc < min_red_cost) {
kpeter@935
  1523
                  min_red_cost = rc;
kpeter@935
  1524
                }
kpeter@809
  1525
              }
kpeter@808
  1526
            }
kpeter@809
  1527
            _pi[n] -= min_red_cost + _epsilon;
kpeter@839
  1528
            _next_out[n] = _first_out[n];
kpeter@808
  1529
            hyper[n] = false;
kpeter@839
  1530
            ++relabel_cnt;
kpeter@808
  1531
          }
alpar@877
  1532
kpeter@808
  1533
          // Remove nodes that are not active nor hyper
kpeter@809
  1534
        remove_nodes:
kpeter@809
  1535
          while ( _active_nodes.size() > 0 &&
kpeter@809
  1536
                  _excess[_active_nodes.front()] <= 0 &&
kpeter@809
  1537
                  !hyper[_active_nodes.front()] ) {
kpeter@809
  1538
            _active_nodes.pop_front();
kpeter@808
  1539
          }
alpar@877
  1540
kpeter@839
  1541
          // Global update heuristic
kpeter@935
  1542
          if (relabel_cnt >= next_global_update_limit) {
kpeter@839
  1543
            globalUpdate();
kpeter@839
  1544
            for (int u = 0; u != _res_node_num; ++u)
kpeter@839
  1545
              hyper[u] = false;
kpeter@935
  1546
            next_global_update_limit += global_update_skip;
kpeter@839
  1547
          }
kpeter@808
  1548
        }
kpeter@808
  1549
      }
kpeter@808
  1550
    }
kpeter@808
  1551
kpeter@808
  1552
  }; //class CostScaling
kpeter@808
  1553
kpeter@808
  1554
  ///@}
kpeter@808
  1555
kpeter@808
  1556
} //namespace lemon
kpeter@808
  1557
kpeter@808
  1558
#endif //LEMON_COST_SCALING_H