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