lemon/cost_scaling.h
author kpeter
Wed, 15 Oct 2008 12:04:11 +0000
changeset 2625 c51b320bc51c
parent 2623 90defb96ee61
child 2629 84354c78b068
permissions -rw-r--r--
Major improvement in the cost scaling algorithm

- Add a new variant that use the partial augment-relabel method.
- Use this method instead of push-relabel by default.
- Use the "Early Termination" heuristic instead of "Price Refinement".

Using the new method and heuristic the algorithm proved to be
2-2.5 times faster on all input files.
kpeter@2577
     1
/* -*- C++ -*-
kpeter@2577
     2
 *
kpeter@2577
     3
 * This file is a part of LEMON, a generic C++ optimization library
kpeter@2577
     4
 *
kpeter@2577
     5
 * Copyright (C) 2003-2008
kpeter@2577
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
kpeter@2577
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
kpeter@2577
     8
 *
kpeter@2577
     9
 * Permission to use, modify and distribute this software is granted
kpeter@2577
    10
 * provided that this copyright notice appears in all copies. For
kpeter@2577
    11
 * precise terms see the accompanying LICENSE file.
kpeter@2577
    12
 *
kpeter@2577
    13
 * This software is provided "AS IS" with no warranty of any kind,
kpeter@2577
    14
 * express or implied, and with no claim as to its suitability for any
kpeter@2577
    15
 * purpose.
kpeter@2577
    16
 *
kpeter@2577
    17
 */
kpeter@2577
    18
kpeter@2577
    19
#ifndef LEMON_COST_SCALING_H
kpeter@2577
    20
#define LEMON_COST_SCALING_H
kpeter@2577
    21
kpeter@2577
    22
/// \ingroup min_cost_flow
kpeter@2577
    23
/// \file
kpeter@2577
    24
/// \brief Cost scaling algorithm for finding a minimum cost flow.
kpeter@2577
    25
kpeter@2577
    26
#include <deque>
kpeter@2577
    27
#include <lemon/graph_adaptor.h>
kpeter@2577
    28
#include <lemon/graph_utils.h>
kpeter@2577
    29
#include <lemon/maps.h>
kpeter@2577
    30
#include <lemon/math.h>
kpeter@2577
    31
kpeter@2577
    32
#include <lemon/circulation.h>
kpeter@2577
    33
#include <lemon/bellman_ford.h>
kpeter@2577
    34
kpeter@2577
    35
namespace lemon {
kpeter@2577
    36
kpeter@2577
    37
  /// \addtogroup min_cost_flow
kpeter@2577
    38
  /// @{
kpeter@2577
    39
kpeter@2577
    40
  /// \brief Implementation of the cost scaling algorithm for finding a
kpeter@2577
    41
  /// minimum cost flow.
kpeter@2577
    42
  ///
kpeter@2577
    43
  /// \ref CostScaling implements the cost scaling algorithm performing
kpeter@2625
    44
  /// augment/push and relabel operations for finding a minimum cost
kpeter@2577
    45
  /// flow.
kpeter@2577
    46
  ///
kpeter@2577
    47
  /// \tparam Graph The directed graph type the algorithm runs on.
kpeter@2577
    48
  /// \tparam LowerMap The type of the lower bound map.
kpeter@2577
    49
  /// \tparam CapacityMap The type of the capacity (upper bound) map.
kpeter@2577
    50
  /// \tparam CostMap The type of the cost (length) map.
kpeter@2577
    51
  /// \tparam SupplyMap The type of the supply map.
kpeter@2577
    52
  ///
kpeter@2577
    53
  /// \warning
kpeter@2577
    54
  /// - Edge capacities and costs should be \e non-negative \e integers.
kpeter@2577
    55
  /// - Supply values should be \e signed \e integers.
kpeter@2581
    56
  /// - The value types of the maps should be convertible to each other.
kpeter@2581
    57
  /// - \c CostMap::Value must be signed type.
kpeter@2577
    58
  ///
kpeter@2577
    59
  /// \note Edge costs are multiplied with the number of nodes during
kpeter@2577
    60
  /// the algorithm so overflow problems may arise more easily than with
kpeter@2577
    61
  /// other minimum cost flow algorithms.
kpeter@2577
    62
  /// If it is available, <tt>long long int</tt> type is used instead of
kpeter@2577
    63
  /// <tt>long int</tt> in the inside computations.
kpeter@2577
    64
  ///
kpeter@2577
    65
  /// \author Peter Kovacs
kpeter@2577
    66
  template < typename Graph,
kpeter@2577
    67
             typename LowerMap = typename Graph::template EdgeMap<int>,
kpeter@2577
    68
             typename CapacityMap = typename Graph::template EdgeMap<int>,
kpeter@2577
    69
             typename CostMap = typename Graph::template EdgeMap<int>,
kpeter@2577
    70
             typename SupplyMap = typename Graph::template NodeMap<int> >
kpeter@2577
    71
  class CostScaling
kpeter@2577
    72
  {
kpeter@2577
    73
    GRAPH_TYPEDEFS(typename Graph);
kpeter@2577
    74
kpeter@2577
    75
    typedef typename CapacityMap::Value Capacity;
kpeter@2577
    76
    typedef typename CostMap::Value Cost;
kpeter@2577
    77
    typedef typename SupplyMap::Value Supply;
kpeter@2577
    78
    typedef typename Graph::template EdgeMap<Capacity> CapacityEdgeMap;
kpeter@2577
    79
    typedef typename Graph::template NodeMap<Supply> SupplyNodeMap;
kpeter@2577
    80
kpeter@2577
    81
    typedef ResGraphAdaptor< const Graph, Capacity,
kpeter@2577
    82
                             CapacityEdgeMap, CapacityEdgeMap > ResGraph;
kpeter@2577
    83
    typedef typename ResGraph::Edge ResEdge;
kpeter@2577
    84
kpeter@2577
    85
#if defined __GNUC__ && !defined __STRICT_ANSI__
kpeter@2577
    86
    typedef long long int LCost;
kpeter@2577
    87
#else
kpeter@2577
    88
    typedef long int LCost;
kpeter@2577
    89
#endif
kpeter@2577
    90
    typedef typename Graph::template EdgeMap<LCost> LargeCostMap;
kpeter@2577
    91
kpeter@2577
    92
  public:
kpeter@2577
    93
kpeter@2577
    94
    /// The type of the flow map.
kpeter@2581
    95
    typedef typename Graph::template EdgeMap<Capacity> FlowMap;
kpeter@2577
    96
    /// The type of the potential map.
kpeter@2577
    97
    typedef typename Graph::template NodeMap<LCost> PotentialMap;
kpeter@2577
    98
kpeter@2577
    99
  private:
kpeter@2577
   100
kpeter@2577
   101
    /// \brief Map adaptor class for handling residual edge costs.
kpeter@2577
   102
    ///
kpeter@2620
   103
    /// Map adaptor class for handling residual edge costs.
kpeter@2581
   104
    template <typename Map>
kpeter@2581
   105
    class ResidualCostMap : public MapBase<ResEdge, typename Map::Value>
kpeter@2577
   106
    {
kpeter@2577
   107
    private:
kpeter@2577
   108
kpeter@2581
   109
      const Map &_cost_map;
kpeter@2577
   110
kpeter@2577
   111
    public:
kpeter@2577
   112
kpeter@2577
   113
      ///\e
kpeter@2581
   114
      ResidualCostMap(const Map &cost_map) :
kpeter@2577
   115
        _cost_map(cost_map) {}
kpeter@2577
   116
kpeter@2577
   117
      ///\e
kpeter@2625
   118
      inline typename Map::Value operator[](const ResEdge &e) const {
kpeter@2625
   119
        return ResGraph::forward(e) ? _cost_map[e] : -_cost_map[e];
kpeter@2577
   120
      }
kpeter@2577
   121
kpeter@2577
   122
    }; //class ResidualCostMap
kpeter@2577
   123
kpeter@2577
   124
    /// \brief Map adaptor class for handling reduced edge costs.
kpeter@2577
   125
    ///
kpeter@2620
   126
    /// Map adaptor class for handling reduced edge costs.
kpeter@2577
   127
    class ReducedCostMap : public MapBase<Edge, LCost>
kpeter@2577
   128
    {
kpeter@2577
   129
    private:
kpeter@2577
   130
kpeter@2577
   131
      const Graph &_gr;
kpeter@2577
   132
      const LargeCostMap &_cost_map;
kpeter@2577
   133
      const PotentialMap &_pot_map;
kpeter@2577
   134
kpeter@2577
   135
    public:
kpeter@2577
   136
kpeter@2577
   137
      ///\e
kpeter@2577
   138
      ReducedCostMap( const Graph &gr,
kpeter@2577
   139
                      const LargeCostMap &cost_map,
kpeter@2577
   140
                      const PotentialMap &pot_map ) :
kpeter@2577
   141
        _gr(gr), _cost_map(cost_map), _pot_map(pot_map) {}
kpeter@2577
   142
kpeter@2577
   143
      ///\e
kpeter@2625
   144
      inline LCost operator[](const Edge &e) const {
kpeter@2577
   145
        return _cost_map[e] + _pot_map[_gr.source(e)]
kpeter@2577
   146
                            - _pot_map[_gr.target(e)];
kpeter@2577
   147
      }
kpeter@2577
   148
kpeter@2577
   149
    }; //class ReducedCostMap
kpeter@2577
   150
kpeter@2577
   151
  private:
kpeter@2577
   152
kpeter@2577
   153
    // The directed graph the algorithm runs on
kpeter@2577
   154
    const Graph &_graph;
kpeter@2577
   155
    // The original lower bound map
kpeter@2577
   156
    const LowerMap *_lower;
kpeter@2577
   157
    // The modified capacity map
kpeter@2577
   158
    CapacityEdgeMap _capacity;
kpeter@2577
   159
    // The original cost map
kpeter@2577
   160
    const CostMap &_orig_cost;
kpeter@2577
   161
    // The scaled cost map
kpeter@2577
   162
    LargeCostMap _cost;
kpeter@2577
   163
    // The modified supply map
kpeter@2577
   164
    SupplyNodeMap _supply;
kpeter@2577
   165
    bool _valid_supply;
kpeter@2577
   166
kpeter@2577
   167
    // Edge map of the current flow
kpeter@2581
   168
    FlowMap *_flow;
kpeter@2581
   169
    bool _local_flow;
kpeter@2577
   170
    // Node map of the current potentials
kpeter@2581
   171
    PotentialMap *_potential;
kpeter@2581
   172
    bool _local_potential;
kpeter@2577
   173
kpeter@2623
   174
    // The residual cost map
kpeter@2623
   175
    ResidualCostMap<LargeCostMap> _res_cost;
kpeter@2577
   176
    // The residual graph
kpeter@2581
   177
    ResGraph *_res_graph;
kpeter@2577
   178
    // The reduced cost map
kpeter@2581
   179
    ReducedCostMap *_red_cost;
kpeter@2577
   180
    // The excess map
kpeter@2577
   181
    SupplyNodeMap _excess;
kpeter@2577
   182
    // The epsilon parameter used for cost scaling
kpeter@2577
   183
    LCost _epsilon;
kpeter@2625
   184
    // The scaling factor
kpeter@2625
   185
    int _alpha;
kpeter@2577
   186
kpeter@2577
   187
  public:
kpeter@2577
   188
kpeter@2581
   189
    /// \brief General constructor (with lower bounds).
kpeter@2577
   190
    ///
kpeter@2581
   191
    /// General constructor (with lower bounds).
kpeter@2577
   192
    ///
kpeter@2577
   193
    /// \param graph The directed graph the algorithm runs on.
kpeter@2577
   194
    /// \param lower The lower bounds of the edges.
kpeter@2577
   195
    /// \param capacity The capacities (upper bounds) of the edges.
kpeter@2577
   196
    /// \param cost The cost (length) values of the edges.
kpeter@2577
   197
    /// \param supply The supply values of the nodes (signed).
kpeter@2577
   198
    CostScaling( const Graph &graph,
kpeter@2577
   199
                 const LowerMap &lower,
kpeter@2577
   200
                 const CapacityMap &capacity,
kpeter@2577
   201
                 const CostMap &cost,
kpeter@2577
   202
                 const SupplyMap &supply ) :
kpeter@2577
   203
      _graph(graph), _lower(&lower), _capacity(graph), _orig_cost(cost),
kpeter@2623
   204
      _cost(graph), _supply(graph), _flow(NULL), _local_flow(false),
kpeter@2623
   205
      _potential(NULL), _local_potential(false), _res_cost(_cost),
kpeter@2623
   206
      _res_graph(NULL), _red_cost(NULL), _excess(graph, 0)
kpeter@2577
   207
    {
kpeter@2625
   208
      // Remove non-zero lower bounds
kpeter@2577
   209
      _capacity = subMap(capacity, lower);
kpeter@2577
   210
      Supply sum = 0;
kpeter@2577
   211
      for (NodeIt n(_graph); n != INVALID; ++n) {
kpeter@2577
   212
        Supply s = supply[n];
kpeter@2577
   213
        for (InEdgeIt e(_graph, n); e != INVALID; ++e)
kpeter@2577
   214
          s += lower[e];
kpeter@2577
   215
        for (OutEdgeIt e(_graph, n); e != INVALID; ++e)
kpeter@2577
   216
          s -= lower[e];
kpeter@2577
   217
        _supply[n] = s;
kpeter@2577
   218
        sum += s;
kpeter@2577
   219
      }
kpeter@2577
   220
      _valid_supply = sum == 0;
kpeter@2577
   221
    }
kpeter@2577
   222
kpeter@2581
   223
    /// \brief General constructor (without lower bounds).
kpeter@2577
   224
    ///
kpeter@2581
   225
    /// General constructor (without lower bounds).
kpeter@2577
   226
    ///
kpeter@2577
   227
    /// \param graph The directed graph the algorithm runs on.
kpeter@2577
   228
    /// \param capacity The capacities (upper bounds) of the edges.
kpeter@2577
   229
    /// \param cost The cost (length) values of the edges.
kpeter@2577
   230
    /// \param supply The supply values of the nodes (signed).
kpeter@2577
   231
    CostScaling( const Graph &graph,
kpeter@2577
   232
                 const CapacityMap &capacity,
kpeter@2577
   233
                 const CostMap &cost,
kpeter@2577
   234
                 const SupplyMap &supply ) :
kpeter@2577
   235
      _graph(graph), _lower(NULL), _capacity(capacity), _orig_cost(cost),
kpeter@2623
   236
      _cost(graph), _supply(supply), _flow(NULL), _local_flow(false),
kpeter@2623
   237
      _potential(NULL), _local_potential(false), _res_cost(_cost),
kpeter@2623
   238
      _res_graph(NULL), _red_cost(NULL), _excess(graph, 0)
kpeter@2577
   239
    {
kpeter@2625
   240
      // Check the sum of supply values
kpeter@2577
   241
      Supply sum = 0;
kpeter@2577
   242
      for (NodeIt n(_graph); n != INVALID; ++n) sum += _supply[n];
kpeter@2577
   243
      _valid_supply = sum == 0;
kpeter@2577
   244
    }
kpeter@2577
   245
kpeter@2581
   246
    /// \brief Simple constructor (with lower bounds).
kpeter@2577
   247
    ///
kpeter@2581
   248
    /// Simple constructor (with lower bounds).
kpeter@2577
   249
    ///
kpeter@2577
   250
    /// \param graph The directed graph the algorithm runs on.
kpeter@2577
   251
    /// \param lower The lower bounds of the edges.
kpeter@2577
   252
    /// \param capacity The capacities (upper bounds) of the edges.
kpeter@2577
   253
    /// \param cost The cost (length) values of the edges.
kpeter@2577
   254
    /// \param s The source node.
kpeter@2577
   255
    /// \param t The target node.
kpeter@2577
   256
    /// \param flow_value The required amount of flow from node \c s
kpeter@2577
   257
    /// to node \c t (i.e. the supply of \c s and the demand of \c t).
kpeter@2577
   258
    CostScaling( const Graph &graph,
kpeter@2577
   259
                 const LowerMap &lower,
kpeter@2577
   260
                 const CapacityMap &capacity,
kpeter@2577
   261
                 const CostMap &cost,
kpeter@2577
   262
                 Node s, Node t,
kpeter@2577
   263
                 Supply flow_value ) :
kpeter@2577
   264
      _graph(graph), _lower(&lower), _capacity(graph), _orig_cost(cost),
kpeter@2623
   265
      _cost(graph), _supply(graph), _flow(NULL), _local_flow(false),
kpeter@2623
   266
      _potential(NULL), _local_potential(false), _res_cost(_cost),
kpeter@2623
   267
      _res_graph(NULL), _red_cost(NULL), _excess(graph, 0)
kpeter@2577
   268
    {
kpeter@2625
   269
      // Remove nonzero lower bounds
kpeter@2577
   270
      _capacity = subMap(capacity, lower);
kpeter@2577
   271
      for (NodeIt n(_graph); n != INVALID; ++n) {
kpeter@2577
   272
        Supply sum = 0;
kpeter@2577
   273
        if (n == s) sum =  flow_value;
kpeter@2577
   274
        if (n == t) sum = -flow_value;
kpeter@2577
   275
        for (InEdgeIt e(_graph, n); e != INVALID; ++e)
kpeter@2577
   276
          sum += lower[e];
kpeter@2577
   277
        for (OutEdgeIt e(_graph, n); e != INVALID; ++e)
kpeter@2577
   278
          sum -= lower[e];
kpeter@2577
   279
        _supply[n] = sum;
kpeter@2577
   280
      }
kpeter@2577
   281
      _valid_supply = true;
kpeter@2577
   282
    }
kpeter@2577
   283
kpeter@2581
   284
    /// \brief Simple constructor (without lower bounds).
kpeter@2577
   285
    ///
kpeter@2581
   286
    /// Simple constructor (without lower bounds).
kpeter@2577
   287
    ///
kpeter@2577
   288
    /// \param graph The directed graph the algorithm runs on.
kpeter@2577
   289
    /// \param capacity The capacities (upper bounds) of the edges.
kpeter@2577
   290
    /// \param cost The cost (length) values of the edges.
kpeter@2577
   291
    /// \param s The source node.
kpeter@2577
   292
    /// \param t The target node.
kpeter@2577
   293
    /// \param flow_value The required amount of flow from node \c s
kpeter@2577
   294
    /// to node \c t (i.e. the supply of \c s and the demand of \c t).
kpeter@2577
   295
    CostScaling( const Graph &graph,
kpeter@2577
   296
                 const CapacityMap &capacity,
kpeter@2577
   297
                 const CostMap &cost,
kpeter@2577
   298
                 Node s, Node t,
kpeter@2577
   299
                 Supply flow_value ) :
kpeter@2577
   300
      _graph(graph), _lower(NULL), _capacity(capacity), _orig_cost(cost),
kpeter@2623
   301
      _cost(graph), _supply(graph, 0), _flow(NULL), _local_flow(false),
kpeter@2623
   302
      _potential(NULL), _local_potential(false), _res_cost(_cost),
kpeter@2623
   303
      _res_graph(NULL), _red_cost(NULL), _excess(graph, 0)
kpeter@2577
   304
    {
kpeter@2577
   305
      _supply[s] =  flow_value;
kpeter@2577
   306
      _supply[t] = -flow_value;
kpeter@2577
   307
      _valid_supply = true;
kpeter@2577
   308
    }
kpeter@2577
   309
kpeter@2581
   310
    /// Destructor.
kpeter@2581
   311
    ~CostScaling() {
kpeter@2581
   312
      if (_local_flow) delete _flow;
kpeter@2581
   313
      if (_local_potential) delete _potential;
kpeter@2581
   314
      delete _res_graph;
kpeter@2581
   315
      delete _red_cost;
kpeter@2581
   316
    }
kpeter@2581
   317
kpeter@2620
   318
    /// \brief Set the flow map.
kpeter@2581
   319
    ///
kpeter@2620
   320
    /// Set the flow map.
kpeter@2581
   321
    ///
kpeter@2581
   322
    /// \return \c (*this)
kpeter@2581
   323
    CostScaling& flowMap(FlowMap &map) {
kpeter@2581
   324
      if (_local_flow) {
kpeter@2581
   325
        delete _flow;
kpeter@2581
   326
        _local_flow = false;
kpeter@2581
   327
      }
kpeter@2581
   328
      _flow = &map;
kpeter@2581
   329
      return *this;
kpeter@2581
   330
    }
kpeter@2581
   331
kpeter@2620
   332
    /// \brief Set the potential map.
kpeter@2581
   333
    ///
kpeter@2620
   334
    /// Set the potential map.
kpeter@2581
   335
    ///
kpeter@2581
   336
    /// \return \c (*this)
kpeter@2581
   337
    CostScaling& potentialMap(PotentialMap &map) {
kpeter@2581
   338
      if (_local_potential) {
kpeter@2581
   339
        delete _potential;
kpeter@2581
   340
        _local_potential = false;
kpeter@2581
   341
      }
kpeter@2581
   342
      _potential = &map;
kpeter@2581
   343
      return *this;
kpeter@2581
   344
    }
kpeter@2581
   345
kpeter@2581
   346
    /// \name Execution control
kpeter@2581
   347
kpeter@2581
   348
    /// @{
kpeter@2581
   349
kpeter@2620
   350
    /// \brief Run the algorithm.
kpeter@2577
   351
    ///
kpeter@2620
   352
    /// Run the algorithm.
kpeter@2577
   353
    ///
kpeter@2625
   354
    /// \param partial_augment By default the algorithm performs
kpeter@2625
   355
    /// partial augment and relabel operations in the cost scaling
kpeter@2625
   356
    /// phases. Set this parameter to \c false for using local push and
kpeter@2625
   357
    /// relabel operations instead.
kpeter@2625
   358
    ///
kpeter@2577
   359
    /// \return \c true if a feasible flow can be found.
kpeter@2625
   360
    bool run(bool partial_augment = true) {
kpeter@2625
   361
      if (partial_augment) {
kpeter@2625
   362
        return init() && startPartialAugment();
kpeter@2625
   363
      } else {
kpeter@2625
   364
        return init() && startPushRelabel();
kpeter@2625
   365
      }
kpeter@2577
   366
    }
kpeter@2577
   367
kpeter@2581
   368
    /// @}
kpeter@2581
   369
kpeter@2581
   370
    /// \name Query Functions
kpeter@2581
   371
    /// The result of the algorithm can be obtained using these
kpeter@2620
   372
    /// functions.\n
kpeter@2620
   373
    /// \ref lemon::CostScaling::run() "run()" must be called before
kpeter@2620
   374
    /// using them.
kpeter@2581
   375
kpeter@2581
   376
    /// @{
kpeter@2581
   377
kpeter@2620
   378
    /// \brief Return a const reference to the edge map storing the
kpeter@2577
   379
    /// found flow.
kpeter@2577
   380
    ///
kpeter@2620
   381
    /// Return a const reference to the edge map storing the found flow.
kpeter@2577
   382
    ///
kpeter@2577
   383
    /// \pre \ref run() must be called before using this function.
kpeter@2577
   384
    const FlowMap& flowMap() const {
kpeter@2581
   385
      return *_flow;
kpeter@2577
   386
    }
kpeter@2577
   387
kpeter@2620
   388
    /// \brief Return a const reference to the node map storing the
kpeter@2577
   389
    /// found potentials (the dual solution).
kpeter@2577
   390
    ///
kpeter@2620
   391
    /// Return a const reference to the node map storing the found
kpeter@2577
   392
    /// potentials (the dual solution).
kpeter@2577
   393
    ///
kpeter@2577
   394
    /// \pre \ref run() must be called before using this function.
kpeter@2577
   395
    const PotentialMap& potentialMap() const {
kpeter@2581
   396
      return *_potential;
kpeter@2581
   397
    }
kpeter@2581
   398
kpeter@2620
   399
    /// \brief Return the flow on the given edge.
kpeter@2581
   400
    ///
kpeter@2620
   401
    /// Return the flow on the given edge.
kpeter@2581
   402
    ///
kpeter@2581
   403
    /// \pre \ref run() must be called before using this function.
kpeter@2581
   404
    Capacity flow(const Edge& edge) const {
kpeter@2581
   405
      return (*_flow)[edge];
kpeter@2581
   406
    }
kpeter@2581
   407
kpeter@2620
   408
    /// \brief Return the potential of the given node.
kpeter@2581
   409
    ///
kpeter@2620
   410
    /// Return the potential of the given node.
kpeter@2581
   411
    ///
kpeter@2581
   412
    /// \pre \ref run() must be called before using this function.
kpeter@2581
   413
    Cost potential(const Node& node) const {
kpeter@2581
   414
      return (*_potential)[node];
kpeter@2577
   415
    }
kpeter@2577
   416
kpeter@2620
   417
    /// \brief Return the total cost of the found flow.
kpeter@2577
   418
    ///
kpeter@2620
   419
    /// Return the total cost of the found flow. The complexity of the
kpeter@2577
   420
    /// function is \f$ O(e) \f$.
kpeter@2577
   421
    ///
kpeter@2577
   422
    /// \pre \ref run() must be called before using this function.
kpeter@2577
   423
    Cost totalCost() const {
kpeter@2577
   424
      Cost c = 0;
kpeter@2577
   425
      for (EdgeIt e(_graph); e != INVALID; ++e)
kpeter@2581
   426
        c += (*_flow)[e] * _orig_cost[e];
kpeter@2577
   427
      return c;
kpeter@2577
   428
    }
kpeter@2577
   429
kpeter@2581
   430
    /// @}
kpeter@2581
   431
kpeter@2577
   432
  private:
kpeter@2577
   433
kpeter@2620
   434
    /// Initialize the algorithm.
kpeter@2577
   435
    bool init() {
kpeter@2577
   436
      if (!_valid_supply) return false;
kpeter@2625
   437
      // The scaling factor
kpeter@2625
   438
      _alpha = 8;
kpeter@2577
   439
kpeter@2625
   440
      // Initialize flow and potential maps
kpeter@2581
   441
      if (!_flow) {
kpeter@2581
   442
        _flow = new FlowMap(_graph);
kpeter@2581
   443
        _local_flow = true;
kpeter@2581
   444
      }
kpeter@2581
   445
      if (!_potential) {
kpeter@2581
   446
        _potential = new PotentialMap(_graph);
kpeter@2581
   447
        _local_potential = true;
kpeter@2581
   448
      }
kpeter@2581
   449
kpeter@2581
   450
      _red_cost = new ReducedCostMap(_graph, _cost, *_potential);
kpeter@2581
   451
      _res_graph = new ResGraph(_graph, _capacity, *_flow);
kpeter@2581
   452
kpeter@2625
   453
      // Initialize the scaled cost map and the epsilon parameter
kpeter@2577
   454
      Cost max_cost = 0;
kpeter@2577
   455
      int node_num = countNodes(_graph);
kpeter@2577
   456
      for (EdgeIt e(_graph); e != INVALID; ++e) {
kpeter@2625
   457
        _cost[e] = LCost(_orig_cost[e]) * node_num * _alpha;
kpeter@2577
   458
        if (_orig_cost[e] > max_cost) max_cost = _orig_cost[e];
kpeter@2577
   459
      }
kpeter@2577
   460
      _epsilon = max_cost * node_num;
kpeter@2577
   461
kpeter@2625
   462
      // Find a feasible flow using Circulation
kpeter@2577
   463
      Circulation< Graph, ConstMap<Edge, Capacity>, CapacityEdgeMap,
kpeter@2577
   464
                   SupplyMap >
kpeter@2581
   465
        circulation( _graph, constMap<Edge>(Capacity(0)), _capacity,
kpeter@2577
   466
                     _supply );
kpeter@2581
   467
      return circulation.flowMap(*_flow).run();
kpeter@2577
   468
    }
kpeter@2577
   469
kpeter@2625
   470
    /// Execute the algorithm performing partial augmentation and
kpeter@2625
   471
    /// relabel operations.
kpeter@2625
   472
    bool startPartialAugment() {
kpeter@2625
   473
      // Paramters for heuristics
kpeter@2625
   474
      const int BF_HEURISTIC_EPSILON_BOUND = 1000;
kpeter@2625
   475
      const int BF_HEURISTIC_BOUND_FACTOR  = 3;
kpeter@2625
   476
      // Maximum augment path length
kpeter@2625
   477
      const int MAX_PATH_LENGTH = 4;
kpeter@2577
   478
kpeter@2625
   479
      // Variables
kpeter@2625
   480
      typename Graph::template NodeMap<Edge> pred_edge(_graph);
kpeter@2625
   481
      typename Graph::template NodeMap<bool> forward(_graph);
kpeter@2625
   482
      typename Graph::template NodeMap<OutEdgeIt> next_out(_graph);
kpeter@2625
   483
      typename Graph::template NodeMap<InEdgeIt> next_in(_graph);
kpeter@2625
   484
      typename Graph::template NodeMap<bool> next_dir(_graph);
kpeter@2577
   485
      std::deque<Node> active_nodes;
kpeter@2625
   486
      std::vector<Node> path_nodes;
kpeter@2577
   487
kpeter@2577
   488
      int node_num = countNodes(_graph);
kpeter@2625
   489
      for ( ; _epsilon >= 1; _epsilon = _epsilon < _alpha && _epsilon > 1 ?
kpeter@2625
   490
                                        1 : _epsilon / _alpha )
kpeter@2577
   491
      {
kpeter@2625
   492
        // "Early Termination" heuristic: use Bellman-Ford algorithm
kpeter@2625
   493
        // to check if the current flow is optimal
kpeter@2577
   494
        if (_epsilon <= BF_HEURISTIC_EPSILON_BOUND) {
kpeter@2581
   495
          typedef ShiftMap< ResidualCostMap<LargeCostMap> > ShiftCostMap;
kpeter@2625
   496
          ShiftCostMap shift_cost(_res_cost, 1);
kpeter@2581
   497
          BellmanFord<ResGraph, ShiftCostMap> bf(*_res_graph, shift_cost);
kpeter@2577
   498
          bf.init(0);
kpeter@2577
   499
          bool done = false;
kpeter@2577
   500
          int K = int(BF_HEURISTIC_BOUND_FACTOR * sqrt(node_num));
kpeter@2577
   501
          for (int i = 0; i < K && !done; ++i)
kpeter@2577
   502
            done = bf.processNextWeakRound();
kpeter@2625
   503
          if (done) break;
kpeter@2577
   504
        }
kpeter@2577
   505
kpeter@2625
   506
        // Saturate edges not satisfying the optimality condition
kpeter@2577
   507
        Capacity delta;
kpeter@2577
   508
        for (EdgeIt e(_graph); e != INVALID; ++e) {
kpeter@2581
   509
          if (_capacity[e] - (*_flow)[e] > 0 && (*_red_cost)[e] < 0) {
kpeter@2581
   510
            delta = _capacity[e] - (*_flow)[e];
kpeter@2577
   511
            _excess[_graph.source(e)] -= delta;
kpeter@2577
   512
            _excess[_graph.target(e)] += delta;
kpeter@2581
   513
            (*_flow)[e] = _capacity[e];
kpeter@2577
   514
          }
kpeter@2581
   515
          if ((*_flow)[e] > 0 && -(*_red_cost)[e] < 0) {
kpeter@2581
   516
            _excess[_graph.target(e)] -= (*_flow)[e];
kpeter@2581
   517
            _excess[_graph.source(e)] += (*_flow)[e];
kpeter@2581
   518
            (*_flow)[e] = 0;
kpeter@2577
   519
          }
kpeter@2577
   520
        }
kpeter@2577
   521
kpeter@2625
   522
        // Find active nodes (i.e. nodes with positive excess)
kpeter@2625
   523
        for (NodeIt n(_graph); n != INVALID; ++n) {
kpeter@2577
   524
          if (_excess[n] > 0) active_nodes.push_back(n);
kpeter@2625
   525
        }
kpeter@2577
   526
kpeter@2625
   527
        // Initialize the next edge maps
kpeter@2625
   528
        for (NodeIt n(_graph); n != INVALID; ++n) {
kpeter@2625
   529
          next_out[n] = OutEdgeIt(_graph, n);
kpeter@2625
   530
          next_in[n] = InEdgeIt(_graph, n);
kpeter@2625
   531
          next_dir[n] = true;
kpeter@2625
   532
        }
kpeter@2625
   533
kpeter@2625
   534
        // Perform partial augment and relabel operations
kpeter@2577
   535
        while (active_nodes.size() > 0) {
kpeter@2625
   536
          // Select an active node (FIFO selection)
kpeter@2625
   537
          if (_excess[active_nodes[0]] <= 0) {
kpeter@2625
   538
            active_nodes.pop_front();
kpeter@2625
   539
            continue;
kpeter@2625
   540
          }
kpeter@2625
   541
          Node start = active_nodes[0];
kpeter@2625
   542
          path_nodes.clear();
kpeter@2625
   543
          path_nodes.push_back(start);
kpeter@2625
   544
kpeter@2625
   545
          // Find an augmenting path from the start node
kpeter@2625
   546
          Node u, tip = start;
kpeter@2625
   547
          LCost min_red_cost;
kpeter@2625
   548
          while ( _excess[tip] >= 0 &&
kpeter@2625
   549
                  int(path_nodes.size()) <= MAX_PATH_LENGTH )
kpeter@2625
   550
          {
kpeter@2625
   551
            if (next_dir[tip]) {
kpeter@2625
   552
              for (OutEdgeIt e = next_out[tip]; e != INVALID; ++e) {
kpeter@2625
   553
                if (_capacity[e] - (*_flow)[e] > 0 && (*_red_cost)[e] < 0) {
kpeter@2625
   554
                  u = _graph.target(e);
kpeter@2625
   555
                  pred_edge[u] = e;
kpeter@2625
   556
                  forward[u] = true;
kpeter@2625
   557
                  next_out[tip] = e;
kpeter@2625
   558
                  tip = u;
kpeter@2625
   559
                  path_nodes.push_back(tip);
kpeter@2625
   560
                  goto next_step;
kpeter@2625
   561
                }
kpeter@2625
   562
              }
kpeter@2625
   563
              next_dir[tip] = false;
kpeter@2625
   564
            }
kpeter@2625
   565
            for (InEdgeIt e = next_in[tip]; e != INVALID; ++e) {
kpeter@2625
   566
              if ((*_flow)[e] > 0 && -(*_red_cost)[e] < 0) {
kpeter@2625
   567
                u = _graph.source(e);
kpeter@2625
   568
                pred_edge[u] = e;
kpeter@2625
   569
                forward[u] = false;
kpeter@2625
   570
                next_in[tip] = e;
kpeter@2625
   571
                tip = u;
kpeter@2625
   572
                path_nodes.push_back(tip);
kpeter@2625
   573
                goto next_step;
kpeter@2625
   574
              }
kpeter@2625
   575
            }
kpeter@2625
   576
kpeter@2625
   577
            // Relabel tip node
kpeter@2625
   578
            min_red_cost = std::numeric_limits<LCost>::max() / 2;
kpeter@2625
   579
            for (OutEdgeIt oe(_graph, tip); oe != INVALID; ++oe) {
kpeter@2625
   580
              if ( _capacity[oe] - (*_flow)[oe] > 0 &&
kpeter@2625
   581
                   (*_red_cost)[oe] < min_red_cost )
kpeter@2625
   582
                min_red_cost = (*_red_cost)[oe];
kpeter@2625
   583
            }
kpeter@2625
   584
            for (InEdgeIt ie(_graph, tip); ie != INVALID; ++ie) {
kpeter@2625
   585
              if ((*_flow)[ie] > 0 && -(*_red_cost)[ie] < min_red_cost)
kpeter@2625
   586
                min_red_cost = -(*_red_cost)[ie];
kpeter@2625
   587
            }
kpeter@2625
   588
            (*_potential)[tip] -= min_red_cost + _epsilon;
kpeter@2625
   589
kpeter@2625
   590
            // Reset the next edge maps
kpeter@2625
   591
            next_out[tip] = OutEdgeIt(_graph, tip);
kpeter@2625
   592
            next_in[tip] = InEdgeIt(_graph, tip);
kpeter@2625
   593
            next_dir[tip] = true;
kpeter@2625
   594
kpeter@2625
   595
            // Step back
kpeter@2625
   596
            if (tip != start) {
kpeter@2625
   597
              path_nodes.pop_back();
kpeter@2625
   598
              tip = path_nodes[path_nodes.size()-1];
kpeter@2625
   599
            }
kpeter@2625
   600
kpeter@2625
   601
          next_step:
kpeter@2625
   602
            continue;
kpeter@2625
   603
          }
kpeter@2625
   604
kpeter@2625
   605
          // Augment along the found path (as much flow as possible)
kpeter@2625
   606
          Capacity delta;
kpeter@2625
   607
          for (int i = 1; i < int(path_nodes.size()); ++i) {
kpeter@2625
   608
            u = path_nodes[i];
kpeter@2625
   609
            delta = forward[u] ?
kpeter@2625
   610
              _capacity[pred_edge[u]] - (*_flow)[pred_edge[u]] :
kpeter@2625
   611
              (*_flow)[pred_edge[u]];
kpeter@2625
   612
            delta = std::min(delta, _excess[path_nodes[i-1]]);
kpeter@2625
   613
            (*_flow)[pred_edge[u]] += forward[u] ? delta : -delta;
kpeter@2625
   614
            _excess[path_nodes[i-1]] -= delta;
kpeter@2625
   615
            _excess[u] += delta;
kpeter@2625
   616
            if (_excess[u] > 0 && _excess[u] <= delta) active_nodes.push_back(u);
kpeter@2625
   617
          }
kpeter@2625
   618
        }
kpeter@2625
   619
      }
kpeter@2625
   620
kpeter@2625
   621
      // Compute node potentials for the original costs
kpeter@2625
   622
      ResidualCostMap<CostMap> res_cost(_orig_cost);
kpeter@2625
   623
      BellmanFord< ResGraph, ResidualCostMap<CostMap> >
kpeter@2625
   624
        bf(*_res_graph, res_cost);
kpeter@2625
   625
      bf.init(0); bf.start();
kpeter@2625
   626
      for (NodeIt n(_graph); n != INVALID; ++n)
kpeter@2625
   627
        (*_potential)[n] = bf.dist(n);
kpeter@2625
   628
kpeter@2625
   629
      // Handle non-zero lower bounds
kpeter@2625
   630
      if (_lower) {
kpeter@2625
   631
        for (EdgeIt e(_graph); e != INVALID; ++e)
kpeter@2625
   632
          (*_flow)[e] += (*_lower)[e];
kpeter@2625
   633
      }
kpeter@2625
   634
      return true;
kpeter@2625
   635
    }
kpeter@2625
   636
kpeter@2625
   637
    /// Execute the algorithm performing push and relabel operations.
kpeter@2625
   638
    bool startPushRelabel() {
kpeter@2625
   639
      // Paramters for heuristics
kpeter@2625
   640
      const int BF_HEURISTIC_EPSILON_BOUND = 1000;
kpeter@2625
   641
      const int BF_HEURISTIC_BOUND_FACTOR  = 3;
kpeter@2625
   642
kpeter@2625
   643
      typename Graph::template NodeMap<bool> hyper(_graph, false);
kpeter@2625
   644
      typename Graph::template NodeMap<Edge> pred_edge(_graph);
kpeter@2625
   645
      typename Graph::template NodeMap<bool> forward(_graph);
kpeter@2625
   646
      typename Graph::template NodeMap<OutEdgeIt> next_out(_graph);
kpeter@2625
   647
      typename Graph::template NodeMap<InEdgeIt> next_in(_graph);
kpeter@2625
   648
      typename Graph::template NodeMap<bool> next_dir(_graph);
kpeter@2625
   649
      std::deque<Node> active_nodes;
kpeter@2625
   650
kpeter@2625
   651
      int node_num = countNodes(_graph);
kpeter@2625
   652
      for ( ; _epsilon >= 1; _epsilon = _epsilon < _alpha && _epsilon > 1 ?
kpeter@2625
   653
                                        1 : _epsilon / _alpha )
kpeter@2625
   654
      {
kpeter@2625
   655
        // "Early Termination" heuristic: use Bellman-Ford algorithm
kpeter@2625
   656
        // to check if the current flow is optimal
kpeter@2625
   657
        if (_epsilon <= BF_HEURISTIC_EPSILON_BOUND) {
kpeter@2625
   658
          typedef ShiftMap< ResidualCostMap<LargeCostMap> > ShiftCostMap;
kpeter@2625
   659
          ShiftCostMap shift_cost(_res_cost, 1);
kpeter@2625
   660
          BellmanFord<ResGraph, ShiftCostMap> bf(*_res_graph, shift_cost);
kpeter@2625
   661
          bf.init(0);
kpeter@2625
   662
          bool done = false;
kpeter@2625
   663
          int K = int(BF_HEURISTIC_BOUND_FACTOR * sqrt(node_num));
kpeter@2625
   664
          for (int i = 0; i < K && !done; ++i)
kpeter@2625
   665
            done = bf.processNextWeakRound();
kpeter@2625
   666
          if (done) break;
kpeter@2625
   667
        }
kpeter@2625
   668
kpeter@2625
   669
        // Saturate edges not satisfying the optimality condition
kpeter@2625
   670
        Capacity delta;
kpeter@2625
   671
        for (EdgeIt e(_graph); e != INVALID; ++e) {
kpeter@2625
   672
          if (_capacity[e] - (*_flow)[e] > 0 && (*_red_cost)[e] < 0) {
kpeter@2625
   673
            delta = _capacity[e] - (*_flow)[e];
kpeter@2625
   674
            _excess[_graph.source(e)] -= delta;
kpeter@2625
   675
            _excess[_graph.target(e)] += delta;
kpeter@2625
   676
            (*_flow)[e] = _capacity[e];
kpeter@2625
   677
          }
kpeter@2625
   678
          if ((*_flow)[e] > 0 && -(*_red_cost)[e] < 0) {
kpeter@2625
   679
            _excess[_graph.target(e)] -= (*_flow)[e];
kpeter@2625
   680
            _excess[_graph.source(e)] += (*_flow)[e];
kpeter@2625
   681
            (*_flow)[e] = 0;
kpeter@2625
   682
          }
kpeter@2625
   683
        }
kpeter@2625
   684
kpeter@2625
   685
        // Find active nodes (i.e. nodes with positive excess)
kpeter@2625
   686
        for (NodeIt n(_graph); n != INVALID; ++n) {
kpeter@2625
   687
          if (_excess[n] > 0) active_nodes.push_back(n);
kpeter@2625
   688
        }
kpeter@2625
   689
kpeter@2625
   690
        // Initialize the next edge maps
kpeter@2625
   691
        for (NodeIt n(_graph); n != INVALID; ++n) {
kpeter@2625
   692
          next_out[n] = OutEdgeIt(_graph, n);
kpeter@2625
   693
          next_in[n] = InEdgeIt(_graph, n);
kpeter@2625
   694
          next_dir[n] = true;
kpeter@2625
   695
        }
kpeter@2625
   696
kpeter@2625
   697
        // Perform push and relabel operations
kpeter@2625
   698
        while (active_nodes.size() > 0) {
kpeter@2625
   699
          // Select an active node (FIFO selection)
kpeter@2577
   700
          Node n = active_nodes[0], t;
kpeter@2577
   701
          bool relabel_enabled = true;
kpeter@2577
   702
kpeter@2625
   703
          // Perform push operations if there are admissible edges
kpeter@2625
   704
          if (_excess[n] > 0 && next_dir[n]) {
kpeter@2625
   705
            OutEdgeIt e = next_out[n];
kpeter@2625
   706
            for ( ; e != INVALID; ++e) {
kpeter@2581
   707
              if (_capacity[e] - (*_flow)[e] > 0 && (*_red_cost)[e] < 0) {
kpeter@2625
   708
                delta = std::min(_capacity[e] - (*_flow)[e], _excess[n]);
kpeter@2577
   709
                t = _graph.target(e);
kpeter@2577
   710
kpeter@2577
   711
                // Push-look-ahead heuristic
kpeter@2577
   712
                Capacity ahead = -_excess[t];
kpeter@2577
   713
                for (OutEdgeIt oe(_graph, t); oe != INVALID; ++oe) {
kpeter@2581
   714
                  if (_capacity[oe] - (*_flow)[oe] > 0 && (*_red_cost)[oe] < 0)
kpeter@2581
   715
                    ahead += _capacity[oe] - (*_flow)[oe];
kpeter@2577
   716
                }
kpeter@2577
   717
                for (InEdgeIt ie(_graph, t); ie != INVALID; ++ie) {
kpeter@2581
   718
                  if ((*_flow)[ie] > 0 && -(*_red_cost)[ie] < 0)
kpeter@2581
   719
                    ahead += (*_flow)[ie];
kpeter@2577
   720
                }
kpeter@2577
   721
                if (ahead < 0) ahead = 0;
kpeter@2577
   722
kpeter@2625
   723
                // Push flow along the edge
kpeter@2577
   724
                if (ahead < delta) {
kpeter@2581
   725
                  (*_flow)[e] += ahead;
kpeter@2577
   726
                  _excess[n] -= ahead;
kpeter@2577
   727
                  _excess[t] += ahead;
kpeter@2577
   728
                  active_nodes.push_front(t);
kpeter@2577
   729
                  hyper[t] = true;
kpeter@2577
   730
                  relabel_enabled = false;
kpeter@2577
   731
                  break;
kpeter@2577
   732
                } else {
kpeter@2581
   733
                  (*_flow)[e] += delta;
kpeter@2577
   734
                  _excess[n] -= delta;
kpeter@2577
   735
                  _excess[t] += delta;
kpeter@2577
   736
                  if (_excess[t] > 0 && _excess[t] <= delta)
kpeter@2577
   737
                    active_nodes.push_back(t);
kpeter@2577
   738
                }
kpeter@2577
   739
kpeter@2577
   740
                if (_excess[n] == 0) break;
kpeter@2577
   741
              }
kpeter@2577
   742
            }
kpeter@2625
   743
            if (e != INVALID) {
kpeter@2625
   744
              next_out[n] = e;
kpeter@2625
   745
            } else {
kpeter@2625
   746
              next_dir[n] = false;
kpeter@2625
   747
            }
kpeter@2577
   748
          }
kpeter@2577
   749
kpeter@2625
   750
          if (_excess[n] > 0 && !next_dir[n]) {
kpeter@2625
   751
            InEdgeIt e = next_in[n];
kpeter@2625
   752
            for ( ; e != INVALID; ++e) {
kpeter@2581
   753
              if ((*_flow)[e] > 0 && -(*_red_cost)[e] < 0) {
kpeter@2625
   754
                delta = std::min((*_flow)[e], _excess[n]);
kpeter@2577
   755
                t = _graph.source(e);
kpeter@2577
   756
kpeter@2577
   757
                // Push-look-ahead heuristic
kpeter@2577
   758
                Capacity ahead = -_excess[t];
kpeter@2577
   759
                for (OutEdgeIt oe(_graph, t); oe != INVALID; ++oe) {
kpeter@2581
   760
                  if (_capacity[oe] - (*_flow)[oe] > 0 && (*_red_cost)[oe] < 0)
kpeter@2581
   761
                    ahead += _capacity[oe] - (*_flow)[oe];
kpeter@2577
   762
                }
kpeter@2577
   763
                for (InEdgeIt ie(_graph, t); ie != INVALID; ++ie) {
kpeter@2581
   764
                  if ((*_flow)[ie] > 0 && -(*_red_cost)[ie] < 0)
kpeter@2581
   765
                    ahead += (*_flow)[ie];
kpeter@2577
   766
                }
kpeter@2577
   767
                if (ahead < 0) ahead = 0;
kpeter@2577
   768
kpeter@2625
   769
                // Push flow along the edge
kpeter@2577
   770
                if (ahead < delta) {
kpeter@2581
   771
                  (*_flow)[e] -= ahead;
kpeter@2577
   772
                  _excess[n] -= ahead;
kpeter@2577
   773
                  _excess[t] += ahead;
kpeter@2577
   774
                  active_nodes.push_front(t);
kpeter@2577
   775
                  hyper[t] = true;
kpeter@2577
   776
                  relabel_enabled = false;
kpeter@2577
   777
                  break;
kpeter@2577
   778
                } else {
kpeter@2581
   779
                  (*_flow)[e] -= delta;
kpeter@2577
   780
                  _excess[n] -= delta;
kpeter@2577
   781
                  _excess[t] += delta;
kpeter@2577
   782
                  if (_excess[t] > 0 && _excess[t] <= delta)
kpeter@2577
   783
                    active_nodes.push_back(t);
kpeter@2577
   784
                }
kpeter@2577
   785
kpeter@2577
   786
                if (_excess[n] == 0) break;
kpeter@2577
   787
              }
kpeter@2577
   788
            }
kpeter@2625
   789
            next_in[n] = e;
kpeter@2577
   790
          }
kpeter@2577
   791
kpeter@2625
   792
          // Relabel the node if it is still active (or hyper)
kpeter@2577
   793
          if (relabel_enabled && (_excess[n] > 0 || hyper[n])) {
kpeter@2625
   794
            LCost min_red_cost = std::numeric_limits<LCost>::max() / 2;
kpeter@2577
   795
            for (OutEdgeIt oe(_graph, n); oe != INVALID; ++oe) {
kpeter@2581
   796
              if ( _capacity[oe] - (*_flow)[oe] > 0 &&
kpeter@2581
   797
                   (*_red_cost)[oe] < min_red_cost )
kpeter@2581
   798
                min_red_cost = (*_red_cost)[oe];
kpeter@2577
   799
            }
kpeter@2577
   800
            for (InEdgeIt ie(_graph, n); ie != INVALID; ++ie) {
kpeter@2581
   801
              if ((*_flow)[ie] > 0 && -(*_red_cost)[ie] < min_red_cost)
kpeter@2581
   802
                min_red_cost = -(*_red_cost)[ie];
kpeter@2577
   803
            }
kpeter@2581
   804
            (*_potential)[n] -= min_red_cost + _epsilon;
kpeter@2577
   805
            hyper[n] = false;
kpeter@2625
   806
kpeter@2625
   807
            // Reset the next edge maps
kpeter@2625
   808
            next_out[n] = OutEdgeIt(_graph, n);
kpeter@2625
   809
            next_in[n] = InEdgeIt(_graph, n);
kpeter@2625
   810
            next_dir[n] = true;
kpeter@2577
   811
          }
kpeter@2577
   812
kpeter@2625
   813
          // Remove nodes that are not active nor hyper
kpeter@2577
   814
          while ( active_nodes.size() > 0 &&
kpeter@2577
   815
                  _excess[active_nodes[0]] <= 0 &&
kpeter@2577
   816
                  !hyper[active_nodes[0]] ) {
kpeter@2577
   817
            active_nodes.pop_front();
kpeter@2577
   818
          }
kpeter@2577
   819
        }
kpeter@2577
   820
      }
kpeter@2577
   821
kpeter@2625
   822
      // Compute node potentials for the original costs
kpeter@2581
   823
      ResidualCostMap<CostMap> res_cost(_orig_cost);
kpeter@2581
   824
      BellmanFord< ResGraph, ResidualCostMap<CostMap> >
kpeter@2581
   825
        bf(*_res_graph, res_cost);
kpeter@2581
   826
      bf.init(0); bf.start();
kpeter@2581
   827
      for (NodeIt n(_graph); n != INVALID; ++n)
kpeter@2581
   828
        (*_potential)[n] = bf.dist(n);
kpeter@2581
   829
kpeter@2625
   830
      // Handle non-zero lower bounds
kpeter@2577
   831
      if (_lower) {
kpeter@2577
   832
        for (EdgeIt e(_graph); e != INVALID; ++e)
kpeter@2581
   833
          (*_flow)[e] += (*_lower)[e];
kpeter@2577
   834
      }
kpeter@2577
   835
      return true;
kpeter@2577
   836
    }
kpeter@2577
   837
kpeter@2577
   838
  }; //class CostScaling
kpeter@2577
   839
kpeter@2577
   840
  ///@}
kpeter@2577
   841
kpeter@2577
   842
} //namespace lemon
kpeter@2577
   843
kpeter@2577
   844
#endif //LEMON_COST_SCALING_H