lemon/network_simplex.h
author Peter Kovacs <kpeter@inf.elte.hu>
Fri, 03 Apr 2009 18:59:15 +0200
changeset 608 6ac5d9ae1d3d
parent 607 9ad8d2122b50
child 609 e6927fe719e6
permissions -rw-r--r--
Support real types + numerical stability fix in NS (#254)

- Real types are supported by appropriate inicialization.
- A feature of the XTI spanning tree structure is removed to ensure
numerical stability (could cause problems using integer types).
The node potentials are updated always on the lower subtree,
in order to prevent overflow problems.
The former method isn't notably faster during to our tests.
kpeter@601
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
kpeter@601
     2
 *
kpeter@601
     3
 * This file is a part of LEMON, a generic C++ optimization library.
kpeter@601
     4
 *
kpeter@601
     5
 * Copyright (C) 2003-2009
kpeter@601
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
kpeter@601
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
kpeter@601
     8
 *
kpeter@601
     9
 * Permission to use, modify and distribute this software is granted
kpeter@601
    10
 * provided that this copyright notice appears in all copies. For
kpeter@601
    11
 * precise terms see the accompanying LICENSE file.
kpeter@601
    12
 *
kpeter@601
    13
 * This software is provided "AS IS" with no warranty of any kind,
kpeter@601
    14
 * express or implied, and with no claim as to its suitability for any
kpeter@601
    15
 * purpose.
kpeter@601
    16
 *
kpeter@601
    17
 */
kpeter@601
    18
kpeter@601
    19
#ifndef LEMON_NETWORK_SIMPLEX_H
kpeter@601
    20
#define LEMON_NETWORK_SIMPLEX_H
kpeter@601
    21
kpeter@601
    22
/// \ingroup min_cost_flow
kpeter@601
    23
///
kpeter@601
    24
/// \file
kpeter@605
    25
/// \brief Network Simplex algorithm for finding a minimum cost flow.
kpeter@601
    26
kpeter@601
    27
#include <vector>
kpeter@601
    28
#include <limits>
kpeter@601
    29
#include <algorithm>
kpeter@601
    30
kpeter@603
    31
#include <lemon/core.h>
kpeter@601
    32
#include <lemon/math.h>
kpeter@601
    33
kpeter@601
    34
namespace lemon {
kpeter@601
    35
kpeter@601
    36
  /// \addtogroup min_cost_flow
kpeter@601
    37
  /// @{
kpeter@601
    38
kpeter@605
    39
  /// \brief Implementation of the primal Network Simplex algorithm
kpeter@601
    40
  /// for finding a \ref min_cost_flow "minimum cost flow".
kpeter@601
    41
  ///
kpeter@605
    42
  /// \ref NetworkSimplex implements the primal Network Simplex algorithm
kpeter@601
    43
  /// for finding a \ref min_cost_flow "minimum cost flow".
kpeter@606
    44
  /// This algorithm is a specialized version of the linear programming
kpeter@606
    45
  /// simplex method directly for the minimum cost flow problem.
kpeter@606
    46
  /// It is one of the most efficient solution methods.
kpeter@606
    47
  ///
kpeter@606
    48
  /// In general this class is the fastest implementation available
kpeter@606
    49
  /// in LEMON for the minimum cost flow problem.
kpeter@601
    50
  ///
kpeter@605
    51
  /// \tparam GR The digraph type the algorithm runs on.
kpeter@607
    52
  /// \tparam F The value type used for flow amounts, capacity bounds
kpeter@607
    53
  /// and supply values in the algorithm. By default it is \c int.
kpeter@607
    54
  /// \tparam C The value type used for costs and potentials in the
kpeter@607
    55
  /// algorithm. By default it is the same as \c F.
kpeter@601
    56
  ///
kpeter@608
    57
  /// \warning Both value types must be signed and all input data must
kpeter@608
    58
  /// be integer.
kpeter@601
    59
  ///
kpeter@605
    60
  /// \note %NetworkSimplex provides five different pivot rule
kpeter@605
    61
  /// implementations. For more information see \ref PivotRule.
kpeter@607
    62
  template <typename GR, typename F = int, typename C = F>
kpeter@601
    63
  class NetworkSimplex
kpeter@601
    64
  {
kpeter@605
    65
  public:
kpeter@601
    66
kpeter@607
    67
    /// The flow type of the algorithm
kpeter@607
    68
    typedef F Flow;
kpeter@607
    69
    /// The cost type of the algorithm
kpeter@607
    70
    typedef C Cost;
kpeter@605
    71
    /// The type of the flow map
kpeter@607
    72
    typedef typename GR::template ArcMap<Flow> FlowMap;
kpeter@605
    73
    /// The type of the potential map
kpeter@607
    74
    typedef typename GR::template NodeMap<Cost> PotentialMap;
kpeter@605
    75
kpeter@605
    76
  public:
kpeter@605
    77
kpeter@605
    78
    /// \brief Enum type for selecting the pivot rule.
kpeter@605
    79
    ///
kpeter@605
    80
    /// Enum type for selecting the pivot rule for the \ref run()
kpeter@605
    81
    /// function.
kpeter@605
    82
    ///
kpeter@605
    83
    /// \ref NetworkSimplex provides five different pivot rule
kpeter@605
    84
    /// implementations that significantly affect the running time
kpeter@605
    85
    /// of the algorithm.
kpeter@605
    86
    /// By default \ref BLOCK_SEARCH "Block Search" is used, which
kpeter@605
    87
    /// proved to be the most efficient and the most robust on various
kpeter@605
    88
    /// test inputs according to our benchmark tests.
kpeter@605
    89
    /// However another pivot rule can be selected using the \ref run()
kpeter@605
    90
    /// function with the proper parameter.
kpeter@605
    91
    enum PivotRule {
kpeter@605
    92
kpeter@605
    93
      /// The First Eligible pivot rule.
kpeter@605
    94
      /// The next eligible arc is selected in a wraparound fashion
kpeter@605
    95
      /// in every iteration.
kpeter@605
    96
      FIRST_ELIGIBLE,
kpeter@605
    97
kpeter@605
    98
      /// The Best Eligible pivot rule.
kpeter@605
    99
      /// The best eligible arc is selected in every iteration.
kpeter@605
   100
      BEST_ELIGIBLE,
kpeter@605
   101
kpeter@605
   102
      /// The Block Search pivot rule.
kpeter@605
   103
      /// A specified number of arcs are examined in every iteration
kpeter@605
   104
      /// in a wraparound fashion and the best eligible arc is selected
kpeter@605
   105
      /// from this block.
kpeter@605
   106
      BLOCK_SEARCH,
kpeter@605
   107
kpeter@605
   108
      /// The Candidate List pivot rule.
kpeter@605
   109
      /// In a major iteration a candidate list is built from eligible arcs
kpeter@605
   110
      /// in a wraparound fashion and in the following minor iterations
kpeter@605
   111
      /// the best eligible arc is selected from this list.
kpeter@605
   112
      CANDIDATE_LIST,
kpeter@605
   113
kpeter@605
   114
      /// The Altering Candidate List pivot rule.
kpeter@605
   115
      /// It is a modified version of the Candidate List method.
kpeter@605
   116
      /// It keeps only the several best eligible arcs from the former
kpeter@605
   117
      /// candidate list and extends this list in every iteration.
kpeter@605
   118
      ALTERING_LIST
kpeter@605
   119
    };
kpeter@605
   120
kpeter@605
   121
  private:
kpeter@605
   122
kpeter@605
   123
    TEMPLATE_DIGRAPH_TYPEDEFS(GR);
kpeter@605
   124
kpeter@607
   125
    typedef typename GR::template ArcMap<Flow> FlowArcMap;
kpeter@607
   126
    typedef typename GR::template ArcMap<Cost> CostArcMap;
kpeter@607
   127
    typedef typename GR::template NodeMap<Flow> FlowNodeMap;
kpeter@601
   128
kpeter@601
   129
    typedef std::vector<Arc> ArcVector;
kpeter@601
   130
    typedef std::vector<Node> NodeVector;
kpeter@601
   131
    typedef std::vector<int> IntVector;
kpeter@601
   132
    typedef std::vector<bool> BoolVector;
kpeter@607
   133
    typedef std::vector<Flow> FlowVector;
kpeter@607
   134
    typedef std::vector<Cost> CostVector;
kpeter@601
   135
kpeter@601
   136
    // State constants for arcs
kpeter@601
   137
    enum ArcStateEnum {
kpeter@601
   138
      STATE_UPPER = -1,
kpeter@601
   139
      STATE_TREE  =  0,
kpeter@601
   140
      STATE_LOWER =  1
kpeter@601
   141
    };
kpeter@601
   142
kpeter@601
   143
  private:
kpeter@601
   144
kpeter@605
   145
    // Data related to the underlying digraph
kpeter@605
   146
    const GR &_graph;
kpeter@605
   147
    int _node_num;
kpeter@605
   148
    int _arc_num;
kpeter@605
   149
kpeter@605
   150
    // Parameters of the problem
kpeter@607
   151
    FlowArcMap *_plower;
kpeter@607
   152
    FlowArcMap *_pupper;
kpeter@607
   153
    CostArcMap *_pcost;
kpeter@607
   154
    FlowNodeMap *_psupply;
kpeter@605
   155
    bool _pstsup;
kpeter@605
   156
    Node _psource, _ptarget;
kpeter@607
   157
    Flow _pstflow;
kpeter@601
   158
kpeter@601
   159
    // Result maps
kpeter@603
   160
    FlowMap *_flow_map;
kpeter@603
   161
    PotentialMap *_potential_map;
kpeter@601
   162
    bool _local_flow;
kpeter@601
   163
    bool _local_potential;
kpeter@601
   164
kpeter@605
   165
    // Data structures for storing the digraph
kpeter@603
   166
    IntNodeMap _node_id;
kpeter@603
   167
    ArcVector _arc_ref;
kpeter@603
   168
    IntVector _source;
kpeter@603
   169
    IntVector _target;
kpeter@603
   170
kpeter@605
   171
    // Node and arc data
kpeter@607
   172
    FlowVector _cap;
kpeter@607
   173
    CostVector _cost;
kpeter@607
   174
    FlowVector _supply;
kpeter@607
   175
    FlowVector _flow;
kpeter@607
   176
    CostVector _pi;
kpeter@601
   177
kpeter@603
   178
    // Data for storing the spanning tree structure
kpeter@601
   179
    IntVector _parent;
kpeter@601
   180
    IntVector _pred;
kpeter@601
   181
    IntVector _thread;
kpeter@604
   182
    IntVector _rev_thread;
kpeter@604
   183
    IntVector _succ_num;
kpeter@604
   184
    IntVector _last_succ;
kpeter@604
   185
    IntVector _dirty_revs;
kpeter@601
   186
    BoolVector _forward;
kpeter@601
   187
    IntVector _state;
kpeter@601
   188
    int _root;
kpeter@601
   189
kpeter@601
   190
    // Temporary data used in the current pivot iteration
kpeter@603
   191
    int in_arc, join, u_in, v_in, u_out, v_out;
kpeter@603
   192
    int first, second, right, last;
kpeter@601
   193
    int stem, par_stem, new_stem;
kpeter@607
   194
    Flow delta;
kpeter@601
   195
kpeter@601
   196
  private:
kpeter@601
   197
kpeter@605
   198
    // Implementation of the First Eligible pivot rule
kpeter@601
   199
    class FirstEligiblePivotRule
kpeter@601
   200
    {
kpeter@601
   201
    private:
kpeter@601
   202
kpeter@601
   203
      // References to the NetworkSimplex class
kpeter@601
   204
      const IntVector  &_source;
kpeter@601
   205
      const IntVector  &_target;
kpeter@607
   206
      const CostVector &_cost;
kpeter@601
   207
      const IntVector  &_state;
kpeter@607
   208
      const CostVector &_pi;
kpeter@601
   209
      int &_in_arc;
kpeter@601
   210
      int _arc_num;
kpeter@601
   211
kpeter@601
   212
      // Pivot rule data
kpeter@601
   213
      int _next_arc;
kpeter@601
   214
kpeter@601
   215
    public:
kpeter@601
   216
kpeter@605
   217
      // Constructor
kpeter@601
   218
      FirstEligiblePivotRule(NetworkSimplex &ns) :
kpeter@603
   219
        _source(ns._source), _target(ns._target),
kpeter@601
   220
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
kpeter@603
   221
        _in_arc(ns.in_arc), _arc_num(ns._arc_num), _next_arc(0)
kpeter@601
   222
      {}
kpeter@601
   223
kpeter@605
   224
      // Find next entering arc
kpeter@601
   225
      bool findEnteringArc() {
kpeter@607
   226
        Cost c;
kpeter@601
   227
        for (int e = _next_arc; e < _arc_num; ++e) {
kpeter@601
   228
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@601
   229
          if (c < 0) {
kpeter@601
   230
            _in_arc = e;
kpeter@601
   231
            _next_arc = e + 1;
kpeter@601
   232
            return true;
kpeter@601
   233
          }
kpeter@601
   234
        }
kpeter@601
   235
        for (int e = 0; e < _next_arc; ++e) {
kpeter@601
   236
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@601
   237
          if (c < 0) {
kpeter@601
   238
            _in_arc = e;
kpeter@601
   239
            _next_arc = e + 1;
kpeter@601
   240
            return true;
kpeter@601
   241
          }
kpeter@601
   242
        }
kpeter@601
   243
        return false;
kpeter@601
   244
      }
kpeter@601
   245
kpeter@601
   246
    }; //class FirstEligiblePivotRule
kpeter@601
   247
kpeter@601
   248
kpeter@605
   249
    // Implementation of the Best Eligible pivot rule
kpeter@601
   250
    class BestEligiblePivotRule
kpeter@601
   251
    {
kpeter@601
   252
    private:
kpeter@601
   253
kpeter@601
   254
      // References to the NetworkSimplex class
kpeter@601
   255
      const IntVector  &_source;
kpeter@601
   256
      const IntVector  &_target;
kpeter@607
   257
      const CostVector &_cost;
kpeter@601
   258
      const IntVector  &_state;
kpeter@607
   259
      const CostVector &_pi;
kpeter@601
   260
      int &_in_arc;
kpeter@601
   261
      int _arc_num;
kpeter@601
   262
kpeter@601
   263
    public:
kpeter@601
   264
kpeter@605
   265
      // Constructor
kpeter@601
   266
      BestEligiblePivotRule(NetworkSimplex &ns) :
kpeter@603
   267
        _source(ns._source), _target(ns._target),
kpeter@601
   268
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
kpeter@603
   269
        _in_arc(ns.in_arc), _arc_num(ns._arc_num)
kpeter@601
   270
      {}
kpeter@601
   271
kpeter@605
   272
      // Find next entering arc
kpeter@601
   273
      bool findEnteringArc() {
kpeter@607
   274
        Cost c, min = 0;
kpeter@601
   275
        for (int e = 0; e < _arc_num; ++e) {
kpeter@601
   276
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@601
   277
          if (c < min) {
kpeter@601
   278
            min = c;
kpeter@601
   279
            _in_arc = e;
kpeter@601
   280
          }
kpeter@601
   281
        }
kpeter@601
   282
        return min < 0;
kpeter@601
   283
      }
kpeter@601
   284
kpeter@601
   285
    }; //class BestEligiblePivotRule
kpeter@601
   286
kpeter@601
   287
kpeter@605
   288
    // Implementation of the Block Search pivot rule
kpeter@601
   289
    class BlockSearchPivotRule
kpeter@601
   290
    {
kpeter@601
   291
    private:
kpeter@601
   292
kpeter@601
   293
      // References to the NetworkSimplex class
kpeter@601
   294
      const IntVector  &_source;
kpeter@601
   295
      const IntVector  &_target;
kpeter@607
   296
      const CostVector &_cost;
kpeter@601
   297
      const IntVector  &_state;
kpeter@607
   298
      const CostVector &_pi;
kpeter@601
   299
      int &_in_arc;
kpeter@601
   300
      int _arc_num;
kpeter@601
   301
kpeter@601
   302
      // Pivot rule data
kpeter@601
   303
      int _block_size;
kpeter@601
   304
      int _next_arc;
kpeter@601
   305
kpeter@601
   306
    public:
kpeter@601
   307
kpeter@605
   308
      // Constructor
kpeter@601
   309
      BlockSearchPivotRule(NetworkSimplex &ns) :
kpeter@603
   310
        _source(ns._source), _target(ns._target),
kpeter@601
   311
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
kpeter@603
   312
        _in_arc(ns.in_arc), _arc_num(ns._arc_num), _next_arc(0)
kpeter@601
   313
      {
kpeter@601
   314
        // The main parameters of the pivot rule
kpeter@601
   315
        const double BLOCK_SIZE_FACTOR = 2.0;
kpeter@601
   316
        const int MIN_BLOCK_SIZE = 10;
kpeter@601
   317
kpeter@601
   318
        _block_size = std::max( int(BLOCK_SIZE_FACTOR * sqrt(_arc_num)),
kpeter@601
   319
                                MIN_BLOCK_SIZE );
kpeter@601
   320
      }
kpeter@601
   321
kpeter@605
   322
      // Find next entering arc
kpeter@601
   323
      bool findEnteringArc() {
kpeter@607
   324
        Cost c, min = 0;
kpeter@601
   325
        int cnt = _block_size;
kpeter@601
   326
        int e, min_arc = _next_arc;
kpeter@601
   327
        for (e = _next_arc; e < _arc_num; ++e) {
kpeter@601
   328
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@601
   329
          if (c < min) {
kpeter@601
   330
            min = c;
kpeter@601
   331
            min_arc = e;
kpeter@601
   332
          }
kpeter@601
   333
          if (--cnt == 0) {
kpeter@601
   334
            if (min < 0) break;
kpeter@601
   335
            cnt = _block_size;
kpeter@601
   336
          }
kpeter@601
   337
        }
kpeter@601
   338
        if (min == 0 || cnt > 0) {
kpeter@601
   339
          for (e = 0; e < _next_arc; ++e) {
kpeter@601
   340
            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@601
   341
            if (c < min) {
kpeter@601
   342
              min = c;
kpeter@601
   343
              min_arc = e;
kpeter@601
   344
            }
kpeter@601
   345
            if (--cnt == 0) {
kpeter@601
   346
              if (min < 0) break;
kpeter@601
   347
              cnt = _block_size;
kpeter@601
   348
            }
kpeter@601
   349
          }
kpeter@601
   350
        }
kpeter@601
   351
        if (min >= 0) return false;
kpeter@601
   352
        _in_arc = min_arc;
kpeter@601
   353
        _next_arc = e;
kpeter@601
   354
        return true;
kpeter@601
   355
      }
kpeter@601
   356
kpeter@601
   357
    }; //class BlockSearchPivotRule
kpeter@601
   358
kpeter@601
   359
kpeter@605
   360
    // Implementation of the Candidate List pivot rule
kpeter@601
   361
    class CandidateListPivotRule
kpeter@601
   362
    {
kpeter@601
   363
    private:
kpeter@601
   364
kpeter@601
   365
      // References to the NetworkSimplex class
kpeter@601
   366
      const IntVector  &_source;
kpeter@601
   367
      const IntVector  &_target;
kpeter@607
   368
      const CostVector &_cost;
kpeter@601
   369
      const IntVector  &_state;
kpeter@607
   370
      const CostVector &_pi;
kpeter@601
   371
      int &_in_arc;
kpeter@601
   372
      int _arc_num;
kpeter@601
   373
kpeter@601
   374
      // Pivot rule data
kpeter@601
   375
      IntVector _candidates;
kpeter@601
   376
      int _list_length, _minor_limit;
kpeter@601
   377
      int _curr_length, _minor_count;
kpeter@601
   378
      int _next_arc;
kpeter@601
   379
kpeter@601
   380
    public:
kpeter@601
   381
kpeter@601
   382
      /// Constructor
kpeter@601
   383
      CandidateListPivotRule(NetworkSimplex &ns) :
kpeter@603
   384
        _source(ns._source), _target(ns._target),
kpeter@601
   385
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
kpeter@603
   386
        _in_arc(ns.in_arc), _arc_num(ns._arc_num), _next_arc(0)
kpeter@601
   387
      {
kpeter@601
   388
        // The main parameters of the pivot rule
kpeter@601
   389
        const double LIST_LENGTH_FACTOR = 1.0;
kpeter@601
   390
        const int MIN_LIST_LENGTH = 10;
kpeter@601
   391
        const double MINOR_LIMIT_FACTOR = 0.1;
kpeter@601
   392
        const int MIN_MINOR_LIMIT = 3;
kpeter@601
   393
kpeter@601
   394
        _list_length = std::max( int(LIST_LENGTH_FACTOR * sqrt(_arc_num)),
kpeter@601
   395
                                 MIN_LIST_LENGTH );
kpeter@601
   396
        _minor_limit = std::max( int(MINOR_LIMIT_FACTOR * _list_length),
kpeter@601
   397
                                 MIN_MINOR_LIMIT );
kpeter@601
   398
        _curr_length = _minor_count = 0;
kpeter@601
   399
        _candidates.resize(_list_length);
kpeter@601
   400
      }
kpeter@601
   401
kpeter@601
   402
      /// Find next entering arc
kpeter@601
   403
      bool findEnteringArc() {
kpeter@607
   404
        Cost min, c;
kpeter@601
   405
        int e, min_arc = _next_arc;
kpeter@601
   406
        if (_curr_length > 0 && _minor_count < _minor_limit) {
kpeter@601
   407
          // Minor iteration: select the best eligible arc from the
kpeter@601
   408
          // current candidate list
kpeter@601
   409
          ++_minor_count;
kpeter@601
   410
          min = 0;
kpeter@601
   411
          for (int i = 0; i < _curr_length; ++i) {
kpeter@601
   412
            e = _candidates[i];
kpeter@601
   413
            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@601
   414
            if (c < min) {
kpeter@601
   415
              min = c;
kpeter@601
   416
              min_arc = e;
kpeter@601
   417
            }
kpeter@601
   418
            if (c >= 0) {
kpeter@601
   419
              _candidates[i--] = _candidates[--_curr_length];
kpeter@601
   420
            }
kpeter@601
   421
          }
kpeter@601
   422
          if (min < 0) {
kpeter@601
   423
            _in_arc = min_arc;
kpeter@601
   424
            return true;
kpeter@601
   425
          }
kpeter@601
   426
        }
kpeter@601
   427
kpeter@601
   428
        // Major iteration: build a new candidate list
kpeter@601
   429
        min = 0;
kpeter@601
   430
        _curr_length = 0;
kpeter@601
   431
        for (e = _next_arc; e < _arc_num; ++e) {
kpeter@601
   432
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@601
   433
          if (c < 0) {
kpeter@601
   434
            _candidates[_curr_length++] = e;
kpeter@601
   435
            if (c < min) {
kpeter@601
   436
              min = c;
kpeter@601
   437
              min_arc = e;
kpeter@601
   438
            }
kpeter@601
   439
            if (_curr_length == _list_length) break;
kpeter@601
   440
          }
kpeter@601
   441
        }
kpeter@601
   442
        if (_curr_length < _list_length) {
kpeter@601
   443
          for (e = 0; e < _next_arc; ++e) {
kpeter@601
   444
            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@601
   445
            if (c < 0) {
kpeter@601
   446
              _candidates[_curr_length++] = e;
kpeter@601
   447
              if (c < min) {
kpeter@601
   448
                min = c;
kpeter@601
   449
                min_arc = e;
kpeter@601
   450
              }
kpeter@601
   451
              if (_curr_length == _list_length) break;
kpeter@601
   452
            }
kpeter@601
   453
          }
kpeter@601
   454
        }
kpeter@601
   455
        if (_curr_length == 0) return false;
kpeter@601
   456
        _minor_count = 1;
kpeter@601
   457
        _in_arc = min_arc;
kpeter@601
   458
        _next_arc = e;
kpeter@601
   459
        return true;
kpeter@601
   460
      }
kpeter@601
   461
kpeter@601
   462
    }; //class CandidateListPivotRule
kpeter@601
   463
kpeter@601
   464
kpeter@605
   465
    // Implementation of the Altering Candidate List pivot rule
kpeter@601
   466
    class AlteringListPivotRule
kpeter@601
   467
    {
kpeter@601
   468
    private:
kpeter@601
   469
kpeter@601
   470
      // References to the NetworkSimplex class
kpeter@601
   471
      const IntVector  &_source;
kpeter@601
   472
      const IntVector  &_target;
kpeter@607
   473
      const CostVector &_cost;
kpeter@601
   474
      const IntVector  &_state;
kpeter@607
   475
      const CostVector &_pi;
kpeter@601
   476
      int &_in_arc;
kpeter@601
   477
      int _arc_num;
kpeter@601
   478
kpeter@601
   479
      // Pivot rule data
kpeter@601
   480
      int _block_size, _head_length, _curr_length;
kpeter@601
   481
      int _next_arc;
kpeter@601
   482
      IntVector _candidates;
kpeter@607
   483
      CostVector _cand_cost;
kpeter@601
   484
kpeter@601
   485
      // Functor class to compare arcs during sort of the candidate list
kpeter@601
   486
      class SortFunc
kpeter@601
   487
      {
kpeter@601
   488
      private:
kpeter@607
   489
        const CostVector &_map;
kpeter@601
   490
      public:
kpeter@607
   491
        SortFunc(const CostVector &map) : _map(map) {}
kpeter@601
   492
        bool operator()(int left, int right) {
kpeter@601
   493
          return _map[left] > _map[right];
kpeter@601
   494
        }
kpeter@601
   495
      };
kpeter@601
   496
kpeter@601
   497
      SortFunc _sort_func;
kpeter@601
   498
kpeter@601
   499
    public:
kpeter@601
   500
kpeter@605
   501
      // Constructor
kpeter@601
   502
      AlteringListPivotRule(NetworkSimplex &ns) :
kpeter@603
   503
        _source(ns._source), _target(ns._target),
kpeter@601
   504
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
kpeter@603
   505
        _in_arc(ns.in_arc), _arc_num(ns._arc_num),
kpeter@601
   506
        _next_arc(0), _cand_cost(ns._arc_num), _sort_func(_cand_cost)
kpeter@601
   507
      {
kpeter@601
   508
        // The main parameters of the pivot rule
kpeter@601
   509
        const double BLOCK_SIZE_FACTOR = 1.5;
kpeter@601
   510
        const int MIN_BLOCK_SIZE = 10;
kpeter@601
   511
        const double HEAD_LENGTH_FACTOR = 0.1;
kpeter@601
   512
        const int MIN_HEAD_LENGTH = 3;
kpeter@601
   513
kpeter@601
   514
        _block_size = std::max( int(BLOCK_SIZE_FACTOR * sqrt(_arc_num)),
kpeter@601
   515
                                MIN_BLOCK_SIZE );
kpeter@601
   516
        _head_length = std::max( int(HEAD_LENGTH_FACTOR * _block_size),
kpeter@601
   517
                                 MIN_HEAD_LENGTH );
kpeter@601
   518
        _candidates.resize(_head_length + _block_size);
kpeter@601
   519
        _curr_length = 0;
kpeter@601
   520
      }
kpeter@601
   521
kpeter@605
   522
      // Find next entering arc
kpeter@601
   523
      bool findEnteringArc() {
kpeter@601
   524
        // Check the current candidate list
kpeter@601
   525
        int e;
kpeter@601
   526
        for (int i = 0; i < _curr_length; ++i) {
kpeter@601
   527
          e = _candidates[i];
kpeter@601
   528
          _cand_cost[e] = _state[e] *
kpeter@601
   529
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@601
   530
          if (_cand_cost[e] >= 0) {
kpeter@601
   531
            _candidates[i--] = _candidates[--_curr_length];
kpeter@601
   532
          }
kpeter@601
   533
        }
kpeter@601
   534
kpeter@601
   535
        // Extend the list
kpeter@601
   536
        int cnt = _block_size;
kpeter@603
   537
        int last_arc = 0;
kpeter@601
   538
        int limit = _head_length;
kpeter@601
   539
kpeter@601
   540
        for (int e = _next_arc; e < _arc_num; ++e) {
kpeter@601
   541
          _cand_cost[e] = _state[e] *
kpeter@601
   542
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@601
   543
          if (_cand_cost[e] < 0) {
kpeter@601
   544
            _candidates[_curr_length++] = e;
kpeter@603
   545
            last_arc = e;
kpeter@601
   546
          }
kpeter@601
   547
          if (--cnt == 0) {
kpeter@601
   548
            if (_curr_length > limit) break;
kpeter@601
   549
            limit = 0;
kpeter@601
   550
            cnt = _block_size;
kpeter@601
   551
          }
kpeter@601
   552
        }
kpeter@601
   553
        if (_curr_length <= limit) {
kpeter@601
   554
          for (int e = 0; e < _next_arc; ++e) {
kpeter@601
   555
            _cand_cost[e] = _state[e] *
kpeter@601
   556
              (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@601
   557
            if (_cand_cost[e] < 0) {
kpeter@601
   558
              _candidates[_curr_length++] = e;
kpeter@603
   559
              last_arc = e;
kpeter@601
   560
            }
kpeter@601
   561
            if (--cnt == 0) {
kpeter@601
   562
              if (_curr_length > limit) break;
kpeter@601
   563
              limit = 0;
kpeter@601
   564
              cnt = _block_size;
kpeter@601
   565
            }
kpeter@601
   566
          }
kpeter@601
   567
        }
kpeter@601
   568
        if (_curr_length == 0) return false;
kpeter@603
   569
        _next_arc = last_arc + 1;
kpeter@601
   570
kpeter@601
   571
        // Make heap of the candidate list (approximating a partial sort)
kpeter@601
   572
        make_heap( _candidates.begin(), _candidates.begin() + _curr_length,
kpeter@601
   573
                   _sort_func );
kpeter@601
   574
kpeter@601
   575
        // Pop the first element of the heap
kpeter@601
   576
        _in_arc = _candidates[0];
kpeter@601
   577
        pop_heap( _candidates.begin(), _candidates.begin() + _curr_length,
kpeter@601
   578
                  _sort_func );
kpeter@601
   579
        _curr_length = std::min(_head_length, _curr_length - 1);
kpeter@601
   580
        return true;
kpeter@601
   581
      }
kpeter@601
   582
kpeter@601
   583
    }; //class AlteringListPivotRule
kpeter@601
   584
kpeter@601
   585
  public:
kpeter@601
   586
kpeter@605
   587
    /// \brief Constructor.
kpeter@601
   588
    ///
kpeter@605
   589
    /// Constructor.
kpeter@601
   590
    ///
kpeter@603
   591
    /// \param graph The digraph the algorithm runs on.
kpeter@605
   592
    NetworkSimplex(const GR& graph) :
kpeter@605
   593
      _graph(graph),
kpeter@605
   594
      _plower(NULL), _pupper(NULL), _pcost(NULL),
kpeter@605
   595
      _psupply(NULL), _pstsup(false),
kpeter@603
   596
      _flow_map(NULL), _potential_map(NULL),
kpeter@601
   597
      _local_flow(false), _local_potential(false),
kpeter@603
   598
      _node_id(graph)
kpeter@605
   599
    {
kpeter@607
   600
      LEMON_ASSERT(std::numeric_limits<Flow>::is_integer &&
kpeter@607
   601
                   std::numeric_limits<Flow>::is_signed,
kpeter@607
   602
        "The flow type of NetworkSimplex must be signed integer");
kpeter@607
   603
      LEMON_ASSERT(std::numeric_limits<Cost>::is_integer &&
kpeter@607
   604
                   std::numeric_limits<Cost>::is_signed,
kpeter@607
   605
        "The cost type of NetworkSimplex must be signed integer");
kpeter@605
   606
    }
kpeter@601
   607
kpeter@601
   608
    /// Destructor.
kpeter@601
   609
    ~NetworkSimplex() {
kpeter@603
   610
      if (_local_flow) delete _flow_map;
kpeter@603
   611
      if (_local_potential) delete _potential_map;
kpeter@601
   612
    }
kpeter@601
   613
kpeter@605
   614
    /// \brief Set the lower bounds on the arcs.
kpeter@605
   615
    ///
kpeter@605
   616
    /// This function sets the lower bounds on the arcs.
kpeter@605
   617
    /// If neither this function nor \ref boundMaps() is used before
kpeter@605
   618
    /// calling \ref run(), the lower bounds will be set to zero
kpeter@605
   619
    /// on all arcs.
kpeter@605
   620
    ///
kpeter@605
   621
    /// \param map An arc map storing the lower bounds.
kpeter@607
   622
    /// Its \c Value type must be convertible to the \c Flow type
kpeter@605
   623
    /// of the algorithm.
kpeter@605
   624
    ///
kpeter@605
   625
    /// \return <tt>(*this)</tt>
kpeter@605
   626
    template <typename LOWER>
kpeter@605
   627
    NetworkSimplex& lowerMap(const LOWER& map) {
kpeter@605
   628
      delete _plower;
kpeter@607
   629
      _plower = new FlowArcMap(_graph);
kpeter@605
   630
      for (ArcIt a(_graph); a != INVALID; ++a) {
kpeter@605
   631
        (*_plower)[a] = map[a];
kpeter@605
   632
      }
kpeter@605
   633
      return *this;
kpeter@605
   634
    }
kpeter@605
   635
kpeter@605
   636
    /// \brief Set the upper bounds (capacities) on the arcs.
kpeter@605
   637
    ///
kpeter@605
   638
    /// This function sets the upper bounds (capacities) on the arcs.
kpeter@605
   639
    /// If none of the functions \ref upperMap(), \ref capacityMap()
kpeter@605
   640
    /// and \ref boundMaps() is used before calling \ref run(),
kpeter@605
   641
    /// the upper bounds (capacities) will be set to
kpeter@607
   642
    /// \c std::numeric_limits<Flow>::max() on all arcs.
kpeter@605
   643
    ///
kpeter@605
   644
    /// \param map An arc map storing the upper bounds.
kpeter@607
   645
    /// Its \c Value type must be convertible to the \c Flow type
kpeter@605
   646
    /// of the algorithm.
kpeter@605
   647
    ///
kpeter@605
   648
    /// \return <tt>(*this)</tt>
kpeter@605
   649
    template<typename UPPER>
kpeter@605
   650
    NetworkSimplex& upperMap(const UPPER& map) {
kpeter@605
   651
      delete _pupper;
kpeter@607
   652
      _pupper = new FlowArcMap(_graph);
kpeter@605
   653
      for (ArcIt a(_graph); a != INVALID; ++a) {
kpeter@605
   654
        (*_pupper)[a] = map[a];
kpeter@605
   655
      }
kpeter@605
   656
      return *this;
kpeter@605
   657
    }
kpeter@605
   658
kpeter@605
   659
    /// \brief Set the upper bounds (capacities) on the arcs.
kpeter@605
   660
    ///
kpeter@605
   661
    /// This function sets the upper bounds (capacities) on the arcs.
kpeter@605
   662
    /// It is just an alias for \ref upperMap().
kpeter@605
   663
    ///
kpeter@605
   664
    /// \return <tt>(*this)</tt>
kpeter@605
   665
    template<typename CAP>
kpeter@605
   666
    NetworkSimplex& capacityMap(const CAP& map) {
kpeter@605
   667
      return upperMap(map);
kpeter@605
   668
    }
kpeter@605
   669
kpeter@605
   670
    /// \brief Set the lower and upper bounds on the arcs.
kpeter@605
   671
    ///
kpeter@605
   672
    /// This function sets the lower and upper bounds on the arcs.
kpeter@605
   673
    /// If neither this function nor \ref lowerMap() is used before
kpeter@605
   674
    /// calling \ref run(), the lower bounds will be set to zero
kpeter@605
   675
    /// on all arcs.
kpeter@605
   676
    /// If none of the functions \ref upperMap(), \ref capacityMap()
kpeter@605
   677
    /// and \ref boundMaps() is used before calling \ref run(),
kpeter@605
   678
    /// the upper bounds (capacities) will be set to
kpeter@607
   679
    /// \c std::numeric_limits<Flow>::max() on all arcs.
kpeter@605
   680
    ///
kpeter@605
   681
    /// \param lower An arc map storing the lower bounds.
kpeter@605
   682
    /// \param upper An arc map storing the upper bounds.
kpeter@605
   683
    ///
kpeter@605
   684
    /// The \c Value type of the maps must be convertible to the
kpeter@607
   685
    /// \c Flow type of the algorithm.
kpeter@605
   686
    ///
kpeter@605
   687
    /// \note This function is just a shortcut of calling \ref lowerMap()
kpeter@605
   688
    /// and \ref upperMap() separately.
kpeter@605
   689
    ///
kpeter@605
   690
    /// \return <tt>(*this)</tt>
kpeter@605
   691
    template <typename LOWER, typename UPPER>
kpeter@605
   692
    NetworkSimplex& boundMaps(const LOWER& lower, const UPPER& upper) {
kpeter@605
   693
      return lowerMap(lower).upperMap(upper);
kpeter@605
   694
    }
kpeter@605
   695
kpeter@605
   696
    /// \brief Set the costs of the arcs.
kpeter@605
   697
    ///
kpeter@605
   698
    /// This function sets the costs of the arcs.
kpeter@605
   699
    /// If it is not used before calling \ref run(), the costs
kpeter@605
   700
    /// will be set to \c 1 on all arcs.
kpeter@605
   701
    ///
kpeter@605
   702
    /// \param map An arc map storing the costs.
kpeter@607
   703
    /// Its \c Value type must be convertible to the \c Cost type
kpeter@605
   704
    /// of the algorithm.
kpeter@605
   705
    ///
kpeter@605
   706
    /// \return <tt>(*this)</tt>
kpeter@605
   707
    template<typename COST>
kpeter@605
   708
    NetworkSimplex& costMap(const COST& map) {
kpeter@605
   709
      delete _pcost;
kpeter@607
   710
      _pcost = new CostArcMap(_graph);
kpeter@605
   711
      for (ArcIt a(_graph); a != INVALID; ++a) {
kpeter@605
   712
        (*_pcost)[a] = map[a];
kpeter@605
   713
      }
kpeter@605
   714
      return *this;
kpeter@605
   715
    }
kpeter@605
   716
kpeter@605
   717
    /// \brief Set the supply values of the nodes.
kpeter@605
   718
    ///
kpeter@605
   719
    /// This function sets the supply values of the nodes.
kpeter@605
   720
    /// If neither this function nor \ref stSupply() is used before
kpeter@605
   721
    /// calling \ref run(), the supply of each node will be set to zero.
kpeter@605
   722
    /// (It makes sense only if non-zero lower bounds are given.)
kpeter@605
   723
    ///
kpeter@605
   724
    /// \param map A node map storing the supply values.
kpeter@607
   725
    /// Its \c Value type must be convertible to the \c Flow type
kpeter@605
   726
    /// of the algorithm.
kpeter@605
   727
    ///
kpeter@605
   728
    /// \return <tt>(*this)</tt>
kpeter@605
   729
    template<typename SUP>
kpeter@605
   730
    NetworkSimplex& supplyMap(const SUP& map) {
kpeter@605
   731
      delete _psupply;
kpeter@605
   732
      _pstsup = false;
kpeter@607
   733
      _psupply = new FlowNodeMap(_graph);
kpeter@605
   734
      for (NodeIt n(_graph); n != INVALID; ++n) {
kpeter@605
   735
        (*_psupply)[n] = map[n];
kpeter@605
   736
      }
kpeter@605
   737
      return *this;
kpeter@605
   738
    }
kpeter@605
   739
kpeter@605
   740
    /// \brief Set single source and target nodes and a supply value.
kpeter@605
   741
    ///
kpeter@605
   742
    /// This function sets a single source node and a single target node
kpeter@605
   743
    /// and the required flow value.
kpeter@605
   744
    /// If neither this function nor \ref supplyMap() is used before
kpeter@605
   745
    /// calling \ref run(), the supply of each node will be set to zero.
kpeter@605
   746
    /// (It makes sense only if non-zero lower bounds are given.)
kpeter@605
   747
    ///
kpeter@605
   748
    /// \param s The source node.
kpeter@605
   749
    /// \param t The target node.
kpeter@605
   750
    /// \param k The required amount of flow from node \c s to node \c t
kpeter@605
   751
    /// (i.e. the supply of \c s and the demand of \c t).
kpeter@605
   752
    ///
kpeter@605
   753
    /// \return <tt>(*this)</tt>
kpeter@607
   754
    NetworkSimplex& stSupply(const Node& s, const Node& t, Flow k) {
kpeter@605
   755
      delete _psupply;
kpeter@605
   756
      _psupply = NULL;
kpeter@605
   757
      _pstsup = true;
kpeter@605
   758
      _psource = s;
kpeter@605
   759
      _ptarget = t;
kpeter@605
   760
      _pstflow = k;
kpeter@605
   761
      return *this;
kpeter@605
   762
    }
kpeter@605
   763
kpeter@601
   764
    /// \brief Set the flow map.
kpeter@601
   765
    ///
kpeter@601
   766
    /// This function sets the flow map.
kpeter@605
   767
    /// If it is not used before calling \ref run(), an instance will
kpeter@605
   768
    /// be allocated automatically. The destructor deallocates this
kpeter@605
   769
    /// automatically allocated map, of course.
kpeter@601
   770
    ///
kpeter@601
   771
    /// \return <tt>(*this)</tt>
kpeter@605
   772
    NetworkSimplex& flowMap(FlowMap& map) {
kpeter@601
   773
      if (_local_flow) {
kpeter@603
   774
        delete _flow_map;
kpeter@601
   775
        _local_flow = false;
kpeter@601
   776
      }
kpeter@603
   777
      _flow_map = &map;
kpeter@601
   778
      return *this;
kpeter@601
   779
    }
kpeter@601
   780
kpeter@601
   781
    /// \brief Set the potential map.
kpeter@601
   782
    ///
kpeter@605
   783
    /// This function sets the potential map, which is used for storing
kpeter@605
   784
    /// the dual solution.
kpeter@605
   785
    /// If it is not used before calling \ref run(), an instance will
kpeter@605
   786
    /// be allocated automatically. The destructor deallocates this
kpeter@605
   787
    /// automatically allocated map, of course.
kpeter@601
   788
    ///
kpeter@601
   789
    /// \return <tt>(*this)</tt>
kpeter@605
   790
    NetworkSimplex& potentialMap(PotentialMap& map) {
kpeter@601
   791
      if (_local_potential) {
kpeter@603
   792
        delete _potential_map;
kpeter@601
   793
        _local_potential = false;
kpeter@601
   794
      }
kpeter@603
   795
      _potential_map = &map;
kpeter@601
   796
      return *this;
kpeter@601
   797
    }
kpeter@601
   798
kpeter@605
   799
    /// \name Execution Control
kpeter@605
   800
    /// The algorithm can be executed using \ref run().
kpeter@605
   801
kpeter@601
   802
    /// @{
kpeter@601
   803
kpeter@601
   804
    /// \brief Run the algorithm.
kpeter@601
   805
    ///
kpeter@601
   806
    /// This function runs the algorithm.
kpeter@605
   807
    /// The paramters can be specified using \ref lowerMap(),
kpeter@606
   808
    /// \ref upperMap(), \ref capacityMap(), \ref boundMaps(),
kpeter@605
   809
    /// \ref costMap(), \ref supplyMap() and \ref stSupply()
kpeter@605
   810
    /// functions. For example,
kpeter@605
   811
    /// \code
kpeter@605
   812
    ///   NetworkSimplex<ListDigraph> ns(graph);
kpeter@605
   813
    ///   ns.boundMaps(lower, upper).costMap(cost)
kpeter@605
   814
    ///     .supplyMap(sup).run();
kpeter@605
   815
    /// \endcode
kpeter@601
   816
    ///
kpeter@606
   817
    /// This function can be called more than once. All the parameters
kpeter@606
   818
    /// that have been given are kept for the next call, unless
kpeter@606
   819
    /// \ref reset() is called, thus only the modified parameters
kpeter@606
   820
    /// have to be set again. See \ref reset() for examples.
kpeter@606
   821
    ///
kpeter@605
   822
    /// \param pivot_rule The pivot rule that will be used during the
kpeter@605
   823
    /// algorithm. For more information see \ref PivotRule.
kpeter@601
   824
    ///
kpeter@601
   825
    /// \return \c true if a feasible flow can be found.
kpeter@605
   826
    bool run(PivotRule pivot_rule = BLOCK_SEARCH) {
kpeter@601
   827
      return init() && start(pivot_rule);
kpeter@601
   828
    }
kpeter@601
   829
kpeter@606
   830
    /// \brief Reset all the parameters that have been given before.
kpeter@606
   831
    ///
kpeter@606
   832
    /// This function resets all the paramaters that have been given
kpeter@606
   833
    /// using \ref lowerMap(), \ref upperMap(), \ref capacityMap(),
kpeter@606
   834
    /// \ref boundMaps(), \ref costMap(), \ref supplyMap() and
kpeter@606
   835
    /// \ref stSupply() functions before.
kpeter@606
   836
    ///
kpeter@606
   837
    /// It is useful for multiple run() calls. If this function is not
kpeter@606
   838
    /// used, all the parameters given before are kept for the next
kpeter@606
   839
    /// \ref run() call.
kpeter@606
   840
    ///
kpeter@606
   841
    /// For example,
kpeter@606
   842
    /// \code
kpeter@606
   843
    ///   NetworkSimplex<ListDigraph> ns(graph);
kpeter@606
   844
    ///
kpeter@606
   845
    ///   // First run
kpeter@606
   846
    ///   ns.lowerMap(lower).capacityMap(cap).costMap(cost)
kpeter@606
   847
    ///     .supplyMap(sup).run();
kpeter@606
   848
    ///
kpeter@606
   849
    ///   // Run again with modified cost map (reset() is not called,
kpeter@606
   850
    ///   // so only the cost map have to be set again)
kpeter@606
   851
    ///   cost[e] += 100;
kpeter@606
   852
    ///   ns.costMap(cost).run();
kpeter@606
   853
    ///
kpeter@606
   854
    ///   // Run again from scratch using reset()
kpeter@606
   855
    ///   // (the lower bounds will be set to zero on all arcs)
kpeter@606
   856
    ///   ns.reset();
kpeter@606
   857
    ///   ns.capacityMap(cap).costMap(cost)
kpeter@606
   858
    ///     .supplyMap(sup).run();
kpeter@606
   859
    /// \endcode
kpeter@606
   860
    ///
kpeter@606
   861
    /// \return <tt>(*this)</tt>
kpeter@606
   862
    NetworkSimplex& reset() {
kpeter@606
   863
      delete _plower;
kpeter@606
   864
      delete _pupper;
kpeter@606
   865
      delete _pcost;
kpeter@606
   866
      delete _psupply;
kpeter@606
   867
      _plower = NULL;
kpeter@606
   868
      _pupper = NULL;
kpeter@606
   869
      _pcost = NULL;
kpeter@606
   870
      _psupply = NULL;
kpeter@606
   871
      _pstsup = false;
kpeter@606
   872
      return *this;
kpeter@606
   873
    }
kpeter@606
   874
kpeter@601
   875
    /// @}
kpeter@601
   876
kpeter@601
   877
    /// \name Query Functions
kpeter@601
   878
    /// The results of the algorithm can be obtained using these
kpeter@601
   879
    /// functions.\n
kpeter@605
   880
    /// The \ref run() function must be called before using them.
kpeter@605
   881
kpeter@601
   882
    /// @{
kpeter@601
   883
kpeter@605
   884
    /// \brief Return the total cost of the found flow.
kpeter@605
   885
    ///
kpeter@605
   886
    /// This function returns the total cost of the found flow.
kpeter@607
   887
    /// The complexity of the function is O(e).
kpeter@605
   888
    ///
kpeter@605
   889
    /// \note The return type of the function can be specified as a
kpeter@605
   890
    /// template parameter. For example,
kpeter@605
   891
    /// \code
kpeter@605
   892
    ///   ns.totalCost<double>();
kpeter@605
   893
    /// \endcode
kpeter@607
   894
    /// It is useful if the total cost cannot be stored in the \c Cost
kpeter@605
   895
    /// type of the algorithm, which is the default return type of the
kpeter@605
   896
    /// function.
kpeter@605
   897
    ///
kpeter@605
   898
    /// \pre \ref run() must be called before using this function.
kpeter@605
   899
    template <typename Num>
kpeter@605
   900
    Num totalCost() const {
kpeter@605
   901
      Num c = 0;
kpeter@605
   902
      if (_pcost) {
kpeter@605
   903
        for (ArcIt e(_graph); e != INVALID; ++e)
kpeter@605
   904
          c += (*_flow_map)[e] * (*_pcost)[e];
kpeter@605
   905
      } else {
kpeter@605
   906
        for (ArcIt e(_graph); e != INVALID; ++e)
kpeter@605
   907
          c += (*_flow_map)[e];
kpeter@605
   908
      }
kpeter@605
   909
      return c;
kpeter@605
   910
    }
kpeter@605
   911
kpeter@605
   912
#ifndef DOXYGEN
kpeter@607
   913
    Cost totalCost() const {
kpeter@607
   914
      return totalCost<Cost>();
kpeter@605
   915
    }
kpeter@605
   916
#endif
kpeter@605
   917
kpeter@605
   918
    /// \brief Return the flow on the given arc.
kpeter@605
   919
    ///
kpeter@605
   920
    /// This function returns the flow on the given arc.
kpeter@605
   921
    ///
kpeter@605
   922
    /// \pre \ref run() must be called before using this function.
kpeter@607
   923
    Flow flow(const Arc& a) const {
kpeter@605
   924
      return (*_flow_map)[a];
kpeter@605
   925
    }
kpeter@605
   926
kpeter@601
   927
    /// \brief Return a const reference to the flow map.
kpeter@601
   928
    ///
kpeter@601
   929
    /// This function returns a const reference to an arc map storing
kpeter@601
   930
    /// the found flow.
kpeter@601
   931
    ///
kpeter@601
   932
    /// \pre \ref run() must be called before using this function.
kpeter@601
   933
    const FlowMap& flowMap() const {
kpeter@603
   934
      return *_flow_map;
kpeter@601
   935
    }
kpeter@601
   936
kpeter@605
   937
    /// \brief Return the potential (dual value) of the given node.
kpeter@605
   938
    ///
kpeter@605
   939
    /// This function returns the potential (dual value) of the
kpeter@605
   940
    /// given node.
kpeter@605
   941
    ///
kpeter@605
   942
    /// \pre \ref run() must be called before using this function.
kpeter@607
   943
    Cost potential(const Node& n) const {
kpeter@605
   944
      return (*_potential_map)[n];
kpeter@605
   945
    }
kpeter@605
   946
kpeter@601
   947
    /// \brief Return a const reference to the potential map
kpeter@601
   948
    /// (the dual solution).
kpeter@601
   949
    ///
kpeter@601
   950
    /// This function returns a const reference to a node map storing
kpeter@605
   951
    /// the found potentials, which form the dual solution of the
kpeter@605
   952
    /// \ref min_cost_flow "minimum cost flow" problem.
kpeter@601
   953
    ///
kpeter@601
   954
    /// \pre \ref run() must be called before using this function.
kpeter@601
   955
    const PotentialMap& potentialMap() const {
kpeter@603
   956
      return *_potential_map;
kpeter@601
   957
    }
kpeter@601
   958
kpeter@601
   959
    /// @}
kpeter@601
   960
kpeter@601
   961
  private:
kpeter@601
   962
kpeter@601
   963
    // Initialize internal data structures
kpeter@601
   964
    bool init() {
kpeter@601
   965
      // Initialize result maps
kpeter@603
   966
      if (!_flow_map) {
kpeter@603
   967
        _flow_map = new FlowMap(_graph);
kpeter@601
   968
        _local_flow = true;
kpeter@601
   969
      }
kpeter@603
   970
      if (!_potential_map) {
kpeter@603
   971
        _potential_map = new PotentialMap(_graph);
kpeter@601
   972
        _local_potential = true;
kpeter@601
   973
      }
kpeter@601
   974
kpeter@601
   975
      // Initialize vectors
kpeter@603
   976
      _node_num = countNodes(_graph);
kpeter@603
   977
      _arc_num = countArcs(_graph);
kpeter@601
   978
      int all_node_num = _node_num + 1;
kpeter@603
   979
      int all_arc_num = _arc_num + _node_num;
kpeter@605
   980
      if (_node_num == 0) return false;
kpeter@601
   981
kpeter@603
   982
      _arc_ref.resize(_arc_num);
kpeter@603
   983
      _source.resize(all_arc_num);
kpeter@603
   984
      _target.resize(all_arc_num);
kpeter@601
   985
kpeter@603
   986
      _cap.resize(all_arc_num);
kpeter@603
   987
      _cost.resize(all_arc_num);
kpeter@601
   988
      _supply.resize(all_node_num);
kpeter@606
   989
      _flow.resize(all_arc_num);
kpeter@606
   990
      _pi.resize(all_node_num);
kpeter@601
   991
kpeter@601
   992
      _parent.resize(all_node_num);
kpeter@601
   993
      _pred.resize(all_node_num);
kpeter@603
   994
      _forward.resize(all_node_num);
kpeter@601
   995
      _thread.resize(all_node_num);
kpeter@604
   996
      _rev_thread.resize(all_node_num);
kpeter@604
   997
      _succ_num.resize(all_node_num);
kpeter@604
   998
      _last_succ.resize(all_node_num);
kpeter@606
   999
      _state.resize(all_arc_num);
kpeter@601
  1000
kpeter@601
  1001
      // Initialize node related data
kpeter@601
  1002
      bool valid_supply = true;
kpeter@605
  1003
      if (!_pstsup && !_psupply) {
kpeter@605
  1004
        _pstsup = true;
kpeter@605
  1005
        _psource = _ptarget = NodeIt(_graph);
kpeter@605
  1006
        _pstflow = 0;
kpeter@605
  1007
      }
kpeter@605
  1008
      if (_psupply) {
kpeter@607
  1009
        Flow sum = 0;
kpeter@601
  1010
        int i = 0;
kpeter@603
  1011
        for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
kpeter@601
  1012
          _node_id[n] = i;
kpeter@605
  1013
          _supply[i] = (*_psupply)[n];
kpeter@601
  1014
          sum += _supply[i];
kpeter@601
  1015
        }
kpeter@601
  1016
        valid_supply = (sum == 0);
kpeter@601
  1017
      } else {
kpeter@601
  1018
        int i = 0;
kpeter@603
  1019
        for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
kpeter@601
  1020
          _node_id[n] = i;
kpeter@601
  1021
          _supply[i] = 0;
kpeter@601
  1022
        }
kpeter@605
  1023
        _supply[_node_id[_psource]] =  _pstflow;
kpeter@605
  1024
        _supply[_node_id[_ptarget]]   = -_pstflow;
kpeter@601
  1025
      }
kpeter@601
  1026
      if (!valid_supply) return false;
kpeter@601
  1027
kpeter@601
  1028
      // Set data for the artificial root node
kpeter@601
  1029
      _root = _node_num;
kpeter@601
  1030
      _parent[_root] = -1;
kpeter@601
  1031
      _pred[_root] = -1;
kpeter@601
  1032
      _thread[_root] = 0;
kpeter@604
  1033
      _rev_thread[0] = _root;
kpeter@604
  1034
      _succ_num[_root] = all_node_num;
kpeter@604
  1035
      _last_succ[_root] = _root - 1;
kpeter@601
  1036
      _supply[_root] = 0;
kpeter@601
  1037
      _pi[_root] = 0;
kpeter@601
  1038
kpeter@601
  1039
      // Store the arcs in a mixed order
kpeter@601
  1040
      int k = std::max(int(sqrt(_arc_num)), 10);
kpeter@601
  1041
      int i = 0;
kpeter@603
  1042
      for (ArcIt e(_graph); e != INVALID; ++e) {
kpeter@603
  1043
        _arc_ref[i] = e;
kpeter@601
  1044
        if ((i += k) >= _arc_num) i = (i % k) + 1;
kpeter@601
  1045
      }
kpeter@601
  1046
kpeter@601
  1047
      // Initialize arc maps
kpeter@608
  1048
      Flow inf_cap =
kpeter@608
  1049
        std::numeric_limits<Flow>::has_infinity ?
kpeter@608
  1050
        std::numeric_limits<Flow>::infinity() :
kpeter@608
  1051
        std::numeric_limits<Flow>::max();
kpeter@605
  1052
      if (_pupper && _pcost) {
kpeter@605
  1053
        for (int i = 0; i != _arc_num; ++i) {
kpeter@605
  1054
          Arc e = _arc_ref[i];
kpeter@605
  1055
          _source[i] = _node_id[_graph.source(e)];
kpeter@605
  1056
          _target[i] = _node_id[_graph.target(e)];
kpeter@605
  1057
          _cap[i] = (*_pupper)[e];
kpeter@605
  1058
          _cost[i] = (*_pcost)[e];
kpeter@606
  1059
          _flow[i] = 0;
kpeter@606
  1060
          _state[i] = STATE_LOWER;
kpeter@605
  1061
        }
kpeter@605
  1062
      } else {
kpeter@605
  1063
        for (int i = 0; i != _arc_num; ++i) {
kpeter@605
  1064
          Arc e = _arc_ref[i];
kpeter@605
  1065
          _source[i] = _node_id[_graph.source(e)];
kpeter@605
  1066
          _target[i] = _node_id[_graph.target(e)];
kpeter@606
  1067
          _flow[i] = 0;
kpeter@606
  1068
          _state[i] = STATE_LOWER;
kpeter@605
  1069
        }
kpeter@605
  1070
        if (_pupper) {
kpeter@605
  1071
          for (int i = 0; i != _arc_num; ++i)
kpeter@605
  1072
            _cap[i] = (*_pupper)[_arc_ref[i]];
kpeter@605
  1073
        } else {
kpeter@605
  1074
          for (int i = 0; i != _arc_num; ++i)
kpeter@608
  1075
            _cap[i] = inf_cap;
kpeter@605
  1076
        }
kpeter@605
  1077
        if (_pcost) {
kpeter@605
  1078
          for (int i = 0; i != _arc_num; ++i)
kpeter@605
  1079
            _cost[i] = (*_pcost)[_arc_ref[i]];
kpeter@605
  1080
        } else {
kpeter@605
  1081
          for (int i = 0; i != _arc_num; ++i)
kpeter@605
  1082
            _cost[i] = 1;
kpeter@605
  1083
        }
kpeter@601
  1084
      }
kpeter@608
  1085
      
kpeter@608
  1086
      // Initialize artifical cost
kpeter@608
  1087
      Cost art_cost;
kpeter@608
  1088
      if (std::numeric_limits<Cost>::is_exact) {
kpeter@608
  1089
        art_cost = std::numeric_limits<Cost>::max() / 4 + 1;
kpeter@608
  1090
      } else {
kpeter@608
  1091
        art_cost = std::numeric_limits<Cost>::min();
kpeter@608
  1092
        for (int i = 0; i != _arc_num; ++i) {
kpeter@608
  1093
          if (_cost[i] > art_cost) art_cost = _cost[i];
kpeter@608
  1094
        }
kpeter@608
  1095
        art_cost = (art_cost + 1) * _node_num;
kpeter@608
  1096
      }
kpeter@601
  1097
kpeter@601
  1098
      // Remove non-zero lower bounds
kpeter@605
  1099
      if (_plower) {
kpeter@601
  1100
        for (int i = 0; i != _arc_num; ++i) {
kpeter@607
  1101
          Flow c = (*_plower)[_arc_ref[i]];
kpeter@601
  1102
          if (c != 0) {
kpeter@601
  1103
            _cap[i] -= c;
kpeter@601
  1104
            _supply[_source[i]] -= c;
kpeter@601
  1105
            _supply[_target[i]] += c;
kpeter@601
  1106
          }
kpeter@601
  1107
        }
kpeter@601
  1108
      }
kpeter@601
  1109
kpeter@601
  1110
      // Add artificial arcs and initialize the spanning tree data structure
kpeter@601
  1111
      for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) {
kpeter@601
  1112
        _thread[u] = u + 1;
kpeter@604
  1113
        _rev_thread[u + 1] = u;
kpeter@604
  1114
        _succ_num[u] = 1;
kpeter@604
  1115
        _last_succ[u] = u;
kpeter@601
  1116
        _parent[u] = _root;
kpeter@601
  1117
        _pred[u] = e;
kpeter@608
  1118
        _cost[e] = art_cost;
kpeter@608
  1119
        _cap[e] = inf_cap;
kpeter@606
  1120
        _state[e] = STATE_TREE;
kpeter@601
  1121
        if (_supply[u] >= 0) {
kpeter@601
  1122
          _flow[e] = _supply[u];
kpeter@601
  1123
          _forward[u] = true;
kpeter@608
  1124
          _pi[u] = -art_cost;
kpeter@601
  1125
        } else {
kpeter@601
  1126
          _flow[e] = -_supply[u];
kpeter@601
  1127
          _forward[u] = false;
kpeter@608
  1128
          _pi[u] = art_cost;
kpeter@601
  1129
        }
kpeter@601
  1130
      }
kpeter@601
  1131
kpeter@601
  1132
      return true;
kpeter@601
  1133
    }
kpeter@601
  1134
kpeter@601
  1135
    // Find the join node
kpeter@601
  1136
    void findJoinNode() {
kpeter@603
  1137
      int u = _source[in_arc];
kpeter@603
  1138
      int v = _target[in_arc];
kpeter@601
  1139
      while (u != v) {
kpeter@604
  1140
        if (_succ_num[u] < _succ_num[v]) {
kpeter@604
  1141
          u = _parent[u];
kpeter@604
  1142
        } else {
kpeter@604
  1143
          v = _parent[v];
kpeter@604
  1144
        }
kpeter@601
  1145
      }
kpeter@601
  1146
      join = u;
kpeter@601
  1147
    }
kpeter@601
  1148
kpeter@601
  1149
    // Find the leaving arc of the cycle and returns true if the
kpeter@601
  1150
    // leaving arc is not the same as the entering arc
kpeter@601
  1151
    bool findLeavingArc() {
kpeter@601
  1152
      // Initialize first and second nodes according to the direction
kpeter@601
  1153
      // of the cycle
kpeter@603
  1154
      if (_state[in_arc] == STATE_LOWER) {
kpeter@603
  1155
        first  = _source[in_arc];
kpeter@603
  1156
        second = _target[in_arc];
kpeter@601
  1157
      } else {
kpeter@603
  1158
        first  = _target[in_arc];
kpeter@603
  1159
        second = _source[in_arc];
kpeter@601
  1160
      }
kpeter@603
  1161
      delta = _cap[in_arc];
kpeter@601
  1162
      int result = 0;
kpeter@607
  1163
      Flow d;
kpeter@601
  1164
      int e;
kpeter@601
  1165
kpeter@601
  1166
      // Search the cycle along the path form the first node to the root
kpeter@601
  1167
      for (int u = first; u != join; u = _parent[u]) {
kpeter@601
  1168
        e = _pred[u];
kpeter@601
  1169
        d = _forward[u] ? _flow[e] : _cap[e] - _flow[e];
kpeter@601
  1170
        if (d < delta) {
kpeter@601
  1171
          delta = d;
kpeter@601
  1172
          u_out = u;
kpeter@601
  1173
          result = 1;
kpeter@601
  1174
        }
kpeter@601
  1175
      }
kpeter@601
  1176
      // Search the cycle along the path form the second node to the root
kpeter@601
  1177
      for (int u = second; u != join; u = _parent[u]) {
kpeter@601
  1178
        e = _pred[u];
kpeter@601
  1179
        d = _forward[u] ? _cap[e] - _flow[e] : _flow[e];
kpeter@601
  1180
        if (d <= delta) {
kpeter@601
  1181
          delta = d;
kpeter@601
  1182
          u_out = u;
kpeter@601
  1183
          result = 2;
kpeter@601
  1184
        }
kpeter@601
  1185
      }
kpeter@601
  1186
kpeter@601
  1187
      if (result == 1) {
kpeter@601
  1188
        u_in = first;
kpeter@601
  1189
        v_in = second;
kpeter@601
  1190
      } else {
kpeter@601
  1191
        u_in = second;
kpeter@601
  1192
        v_in = first;
kpeter@601
  1193
      }
kpeter@601
  1194
      return result != 0;
kpeter@601
  1195
    }
kpeter@601
  1196
kpeter@601
  1197
    // Change _flow and _state vectors
kpeter@601
  1198
    void changeFlow(bool change) {
kpeter@601
  1199
      // Augment along the cycle
kpeter@601
  1200
      if (delta > 0) {
kpeter@607
  1201
        Flow val = _state[in_arc] * delta;
kpeter@603
  1202
        _flow[in_arc] += val;
kpeter@603
  1203
        for (int u = _source[in_arc]; u != join; u = _parent[u]) {
kpeter@601
  1204
          _flow[_pred[u]] += _forward[u] ? -val : val;
kpeter@601
  1205
        }
kpeter@603
  1206
        for (int u = _target[in_arc]; u != join; u = _parent[u]) {
kpeter@601
  1207
          _flow[_pred[u]] += _forward[u] ? val : -val;
kpeter@601
  1208
        }
kpeter@601
  1209
      }
kpeter@601
  1210
      // Update the state of the entering and leaving arcs
kpeter@601
  1211
      if (change) {
kpeter@603
  1212
        _state[in_arc] = STATE_TREE;
kpeter@601
  1213
        _state[_pred[u_out]] =
kpeter@601
  1214
          (_flow[_pred[u_out]] == 0) ? STATE_LOWER : STATE_UPPER;
kpeter@601
  1215
      } else {
kpeter@603
  1216
        _state[in_arc] = -_state[in_arc];
kpeter@601
  1217
      }
kpeter@601
  1218
    }
kpeter@601
  1219
kpeter@604
  1220
    // Update the tree structure
kpeter@604
  1221
    void updateTreeStructure() {
kpeter@604
  1222
      int u, w;
kpeter@604
  1223
      int old_rev_thread = _rev_thread[u_out];
kpeter@604
  1224
      int old_succ_num = _succ_num[u_out];
kpeter@604
  1225
      int old_last_succ = _last_succ[u_out];
kpeter@601
  1226
      v_out = _parent[u_out];
kpeter@601
  1227
kpeter@604
  1228
      u = _last_succ[u_in];  // the last successor of u_in
kpeter@604
  1229
      right = _thread[u];    // the node after it
kpeter@604
  1230
kpeter@604
  1231
      // Handle the case when old_rev_thread equals to v_in
kpeter@604
  1232
      // (it also means that join and v_out coincide)
kpeter@604
  1233
      if (old_rev_thread == v_in) {
kpeter@604
  1234
        last = _thread[_last_succ[u_out]];
kpeter@604
  1235
      } else {
kpeter@604
  1236
        last = _thread[v_in];
kpeter@601
  1237
      }
kpeter@601
  1238
kpeter@604
  1239
      // Update _thread and _parent along the stem nodes (i.e. the nodes
kpeter@604
  1240
      // between u_in and u_out, whose parent have to be changed)
kpeter@601
  1241
      _thread[v_in] = stem = u_in;
kpeter@604
  1242
      _dirty_revs.clear();
kpeter@604
  1243
      _dirty_revs.push_back(v_in);
kpeter@601
  1244
      par_stem = v_in;
kpeter@601
  1245
      while (stem != u_out) {
kpeter@604
  1246
        // Insert the next stem node into the thread list
kpeter@604
  1247
        new_stem = _parent[stem];
kpeter@604
  1248
        _thread[u] = new_stem;
kpeter@604
  1249
        _dirty_revs.push_back(u);
kpeter@601
  1250
kpeter@604
  1251
        // Remove the subtree of stem from the thread list
kpeter@604
  1252
        w = _rev_thread[stem];
kpeter@604
  1253
        _thread[w] = right;
kpeter@604
  1254
        _rev_thread[right] = w;
kpeter@601
  1255
kpeter@604
  1256
        // Change the parent node and shift stem nodes
kpeter@601
  1257
        _parent[stem] = par_stem;
kpeter@601
  1258
        par_stem = stem;
kpeter@601
  1259
        stem = new_stem;
kpeter@601
  1260
kpeter@604
  1261
        // Update u and right
kpeter@604
  1262
        u = _last_succ[stem] == _last_succ[par_stem] ?
kpeter@604
  1263
          _rev_thread[par_stem] : _last_succ[stem];
kpeter@601
  1264
        right = _thread[u];
kpeter@601
  1265
      }
kpeter@601
  1266
      _parent[u_out] = par_stem;
kpeter@601
  1267
      _thread[u] = last;
kpeter@604
  1268
      _rev_thread[last] = u;
kpeter@604
  1269
      _last_succ[u_out] = u;
kpeter@601
  1270
kpeter@604
  1271
      // Remove the subtree of u_out from the thread list except for
kpeter@604
  1272
      // the case when old_rev_thread equals to v_in
kpeter@604
  1273
      // (it also means that join and v_out coincide)
kpeter@604
  1274
      if (old_rev_thread != v_in) {
kpeter@604
  1275
        _thread[old_rev_thread] = right;
kpeter@604
  1276
        _rev_thread[right] = old_rev_thread;
kpeter@604
  1277
      }
kpeter@604
  1278
kpeter@604
  1279
      // Update _rev_thread using the new _thread values
kpeter@604
  1280
      for (int i = 0; i < int(_dirty_revs.size()); ++i) {
kpeter@604
  1281
        u = _dirty_revs[i];
kpeter@604
  1282
        _rev_thread[_thread[u]] = u;
kpeter@604
  1283
      }
kpeter@604
  1284
kpeter@604
  1285
      // Update _pred, _forward, _last_succ and _succ_num for the
kpeter@604
  1286
      // stem nodes from u_out to u_in
kpeter@604
  1287
      int tmp_sc = 0, tmp_ls = _last_succ[u_out];
kpeter@604
  1288
      u = u_out;
kpeter@604
  1289
      while (u != u_in) {
kpeter@604
  1290
        w = _parent[u];
kpeter@604
  1291
        _pred[u] = _pred[w];
kpeter@604
  1292
        _forward[u] = !_forward[w];
kpeter@604
  1293
        tmp_sc += _succ_num[u] - _succ_num[w];
kpeter@604
  1294
        _succ_num[u] = tmp_sc;
kpeter@604
  1295
        _last_succ[w] = tmp_ls;
kpeter@604
  1296
        u = w;
kpeter@604
  1297
      }
kpeter@604
  1298
      _pred[u_in] = in_arc;
kpeter@604
  1299
      _forward[u_in] = (u_in == _source[in_arc]);
kpeter@604
  1300
      _succ_num[u_in] = old_succ_num;
kpeter@604
  1301
kpeter@604
  1302
      // Set limits for updating _last_succ form v_in and v_out
kpeter@604
  1303
      // towards the root
kpeter@604
  1304
      int up_limit_in = -1;
kpeter@604
  1305
      int up_limit_out = -1;
kpeter@604
  1306
      if (_last_succ[join] == v_in) {
kpeter@604
  1307
        up_limit_out = join;
kpeter@601
  1308
      } else {
kpeter@604
  1309
        up_limit_in = join;
kpeter@604
  1310
      }
kpeter@604
  1311
kpeter@604
  1312
      // Update _last_succ from v_in towards the root
kpeter@604
  1313
      for (u = v_in; u != up_limit_in && _last_succ[u] == v_in;
kpeter@604
  1314
           u = _parent[u]) {
kpeter@604
  1315
        _last_succ[u] = _last_succ[u_out];
kpeter@604
  1316
      }
kpeter@604
  1317
      // Update _last_succ from v_out towards the root
kpeter@604
  1318
      if (join != old_rev_thread && v_in != old_rev_thread) {
kpeter@604
  1319
        for (u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
kpeter@604
  1320
             u = _parent[u]) {
kpeter@604
  1321
          _last_succ[u] = old_rev_thread;
kpeter@604
  1322
        }
kpeter@604
  1323
      } else {
kpeter@604
  1324
        for (u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
kpeter@604
  1325
             u = _parent[u]) {
kpeter@604
  1326
          _last_succ[u] = _last_succ[u_out];
kpeter@604
  1327
        }
kpeter@604
  1328
      }
kpeter@604
  1329
kpeter@604
  1330
      // Update _succ_num from v_in to join
kpeter@604
  1331
      for (u = v_in; u != join; u = _parent[u]) {
kpeter@604
  1332
        _succ_num[u] += old_succ_num;
kpeter@604
  1333
      }
kpeter@604
  1334
      // Update _succ_num from v_out to join
kpeter@604
  1335
      for (u = v_out; u != join; u = _parent[u]) {
kpeter@604
  1336
        _succ_num[u] -= old_succ_num;
kpeter@601
  1337
      }
kpeter@601
  1338
    }
kpeter@601
  1339
kpeter@604
  1340
    // Update potentials
kpeter@604
  1341
    void updatePotential() {
kpeter@607
  1342
      Cost sigma = _forward[u_in] ?
kpeter@601
  1343
        _pi[v_in] - _pi[u_in] - _cost[_pred[u_in]] :
kpeter@601
  1344
        _pi[v_in] - _pi[u_in] + _cost[_pred[u_in]];
kpeter@608
  1345
      // Update potentials in the subtree, which has been moved
kpeter@608
  1346
      int end = _thread[_last_succ[u_in]];
kpeter@608
  1347
      for (int u = u_in; u != end; u = _thread[u]) {
kpeter@608
  1348
        _pi[u] += sigma;
kpeter@601
  1349
      }
kpeter@601
  1350
    }
kpeter@601
  1351
kpeter@601
  1352
    // Execute the algorithm
kpeter@605
  1353
    bool start(PivotRule pivot_rule) {
kpeter@601
  1354
      // Select the pivot rule implementation
kpeter@601
  1355
      switch (pivot_rule) {
kpeter@605
  1356
        case FIRST_ELIGIBLE:
kpeter@601
  1357
          return start<FirstEligiblePivotRule>();
kpeter@605
  1358
        case BEST_ELIGIBLE:
kpeter@601
  1359
          return start<BestEligiblePivotRule>();
kpeter@605
  1360
        case BLOCK_SEARCH:
kpeter@601
  1361
          return start<BlockSearchPivotRule>();
kpeter@605
  1362
        case CANDIDATE_LIST:
kpeter@601
  1363
          return start<CandidateListPivotRule>();
kpeter@605
  1364
        case ALTERING_LIST:
kpeter@601
  1365
          return start<AlteringListPivotRule>();
kpeter@601
  1366
      }
kpeter@601
  1367
      return false;
kpeter@601
  1368
    }
kpeter@601
  1369
kpeter@605
  1370
    template <typename PivotRuleImpl>
kpeter@601
  1371
    bool start() {
kpeter@605
  1372
      PivotRuleImpl pivot(*this);
kpeter@601
  1373
kpeter@605
  1374
      // Execute the Network Simplex algorithm
kpeter@601
  1375
      while (pivot.findEnteringArc()) {
kpeter@601
  1376
        findJoinNode();
kpeter@601
  1377
        bool change = findLeavingArc();
kpeter@601
  1378
        changeFlow(change);
kpeter@601
  1379
        if (change) {
kpeter@604
  1380
          updateTreeStructure();
kpeter@604
  1381
          updatePotential();
kpeter@601
  1382
        }
kpeter@601
  1383
      }
kpeter@601
  1384
kpeter@601
  1385
      // Check if the flow amount equals zero on all the artificial arcs
kpeter@601
  1386
      for (int e = _arc_num; e != _arc_num + _node_num; ++e) {
kpeter@601
  1387
        if (_flow[e] > 0) return false;
kpeter@601
  1388
      }
kpeter@601
  1389
kpeter@603
  1390
      // Copy flow values to _flow_map
kpeter@605
  1391
      if (_plower) {
kpeter@601
  1392
        for (int i = 0; i != _arc_num; ++i) {
kpeter@603
  1393
          Arc e = _arc_ref[i];
kpeter@605
  1394
          _flow_map->set(e, (*_plower)[e] + _flow[i]);
kpeter@601
  1395
        }
kpeter@601
  1396
      } else {
kpeter@601
  1397
        for (int i = 0; i != _arc_num; ++i) {
kpeter@603
  1398
          _flow_map->set(_arc_ref[i], _flow[i]);
kpeter@601
  1399
        }
kpeter@601
  1400
      }
kpeter@603
  1401
      // Copy potential values to _potential_map
kpeter@603
  1402
      for (NodeIt n(_graph); n != INVALID; ++n) {
kpeter@603
  1403
        _potential_map->set(n, _pi[_node_id[n]]);
kpeter@601
  1404
      }
kpeter@601
  1405
kpeter@601
  1406
      return true;
kpeter@601
  1407
    }
kpeter@601
  1408
kpeter@601
  1409
  }; //class NetworkSimplex
kpeter@601
  1410
kpeter@601
  1411
  ///@}
kpeter@601
  1412
kpeter@601
  1413
} //namespace lemon
kpeter@601
  1414
kpeter@601
  1415
#endif //LEMON_NETWORK_SIMPLEX_H