lemon/network_simplex.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 24 Feb 2009 09:46:02 +0100
changeset 593 e8349c6f12ca
child 595 425cc8328c0e
permissions -rw-r--r--
Port NetworkSimplex from SVN -r3520 (#234)
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@593
    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@593
    31
#include <lemon/math.h>
kpeter@593
    32
kpeter@593
    33
namespace lemon {
kpeter@593
    34
kpeter@593
    35
  /// \addtogroup min_cost_flow
kpeter@593
    36
  /// @{
kpeter@593
    37
kpeter@593
    38
  /// \brief Implementation of the primal network simplex algorithm
kpeter@593
    39
  /// for finding a \ref min_cost_flow "minimum cost flow".
kpeter@593
    40
  ///
kpeter@593
    41
  /// \ref NetworkSimplex implements the primal network simplex algorithm
kpeter@593
    42
  /// for finding a \ref min_cost_flow "minimum cost flow".
kpeter@593
    43
  ///
kpeter@593
    44
  /// \tparam Digraph The digraph type the algorithm runs on.
kpeter@593
    45
  /// \tparam LowerMap The type of the lower bound map.
kpeter@593
    46
  /// \tparam CapacityMap The type of the capacity (upper bound) map.
kpeter@593
    47
  /// \tparam CostMap The type of the cost (length) map.
kpeter@593
    48
  /// \tparam SupplyMap The type of the supply map.
kpeter@593
    49
  ///
kpeter@593
    50
  /// \warning
kpeter@593
    51
  /// - Arc capacities and costs should be \e non-negative \e integers.
kpeter@593
    52
  /// - Supply values should be \e signed \e integers.
kpeter@593
    53
  /// - The value types of the maps should be convertible to each other.
kpeter@593
    54
  /// - \c CostMap::Value must be signed type.
kpeter@593
    55
  ///
kpeter@593
    56
  /// \note \ref NetworkSimplex provides five different pivot rule
kpeter@593
    57
  /// implementations that significantly affect the efficiency of the
kpeter@593
    58
  /// algorithm.
kpeter@593
    59
  /// By default "Block Search" pivot rule is used, which proved to be
kpeter@593
    60
  /// by far the most efficient according to our benchmark tests.
kpeter@593
    61
  /// However another pivot rule can be selected using \ref run()
kpeter@593
    62
  /// function with the proper parameter.
kpeter@593
    63
#ifdef DOXYGEN
kpeter@593
    64
  template < typename Digraph,
kpeter@593
    65
             typename LowerMap,
kpeter@593
    66
             typename CapacityMap,
kpeter@593
    67
             typename CostMap,
kpeter@593
    68
             typename SupplyMap >
kpeter@593
    69
kpeter@593
    70
#else
kpeter@593
    71
  template < typename Digraph,
kpeter@593
    72
             typename LowerMap = typename Digraph::template ArcMap<int>,
kpeter@593
    73
             typename CapacityMap = typename Digraph::template ArcMap<int>,
kpeter@593
    74
             typename CostMap = typename Digraph::template ArcMap<int>,
kpeter@593
    75
             typename SupplyMap = typename Digraph::template NodeMap<int> >
kpeter@593
    76
#endif
kpeter@593
    77
  class NetworkSimplex
kpeter@593
    78
  {
kpeter@593
    79
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
kpeter@593
    80
kpeter@593
    81
    typedef typename CapacityMap::Value Capacity;
kpeter@593
    82
    typedef typename CostMap::Value Cost;
kpeter@593
    83
    typedef typename SupplyMap::Value Supply;
kpeter@593
    84
kpeter@593
    85
    typedef std::vector<Arc> ArcVector;
kpeter@593
    86
    typedef std::vector<Node> NodeVector;
kpeter@593
    87
    typedef std::vector<int> IntVector;
kpeter@593
    88
    typedef std::vector<bool> BoolVector;
kpeter@593
    89
    typedef std::vector<Capacity> CapacityVector;
kpeter@593
    90
    typedef std::vector<Cost> CostVector;
kpeter@593
    91
    typedef std::vector<Supply> SupplyVector;
kpeter@593
    92
kpeter@593
    93
  public:
kpeter@593
    94
kpeter@593
    95
    /// The type of the flow map
kpeter@593
    96
    typedef typename Digraph::template ArcMap<Capacity> FlowMap;
kpeter@593
    97
    /// The type of the potential map
kpeter@593
    98
    typedef typename Digraph::template NodeMap<Cost> PotentialMap;
kpeter@593
    99
kpeter@593
   100
  public:
kpeter@593
   101
kpeter@593
   102
    /// Enum type for selecting the pivot rule used by \ref run()
kpeter@593
   103
    enum PivotRuleEnum {
kpeter@593
   104
      FIRST_ELIGIBLE_PIVOT,
kpeter@593
   105
      BEST_ELIGIBLE_PIVOT,
kpeter@593
   106
      BLOCK_SEARCH_PIVOT,
kpeter@593
   107
      CANDIDATE_LIST_PIVOT,
kpeter@593
   108
      ALTERING_LIST_PIVOT
kpeter@593
   109
    };
kpeter@593
   110
kpeter@593
   111
  private:
kpeter@593
   112
kpeter@593
   113
    // State constants for arcs
kpeter@593
   114
    enum ArcStateEnum {
kpeter@593
   115
      STATE_UPPER = -1,
kpeter@593
   116
      STATE_TREE  =  0,
kpeter@593
   117
      STATE_LOWER =  1
kpeter@593
   118
    };
kpeter@593
   119
kpeter@593
   120
  private:
kpeter@593
   121
kpeter@593
   122
    // References for the original data
kpeter@593
   123
    const Digraph &_orig_graph;
kpeter@593
   124
    const LowerMap *_orig_lower;
kpeter@593
   125
    const CapacityMap &_orig_cap;
kpeter@593
   126
    const CostMap &_orig_cost;
kpeter@593
   127
    const SupplyMap *_orig_supply;
kpeter@593
   128
    Node _orig_source;
kpeter@593
   129
    Node _orig_target;
kpeter@593
   130
    Capacity _orig_flow_value;
kpeter@593
   131
kpeter@593
   132
    // Result maps
kpeter@593
   133
    FlowMap *_flow_result;
kpeter@593
   134
    PotentialMap *_potential_result;
kpeter@593
   135
    bool _local_flow;
kpeter@593
   136
    bool _local_potential;
kpeter@593
   137
kpeter@593
   138
    // Data structures for storing the graph
kpeter@593
   139
    ArcVector _arc;
kpeter@593
   140
    NodeVector _node;
kpeter@593
   141
    IntNodeMap _node_id;
kpeter@593
   142
    IntVector _source;
kpeter@593
   143
    IntVector _target;
kpeter@593
   144
kpeter@593
   145
    // The number of nodes and arcs in the original graph
kpeter@593
   146
    int _node_num;
kpeter@593
   147
    int _arc_num;
kpeter@593
   148
kpeter@593
   149
    // Node and arc maps
kpeter@593
   150
    CapacityVector _cap;
kpeter@593
   151
    CostVector _cost;
kpeter@593
   152
    CostVector _supply;
kpeter@593
   153
    CapacityVector _flow;
kpeter@593
   154
    CostVector _pi;
kpeter@593
   155
kpeter@593
   156
    // Node and arc maps for the spanning tree structure
kpeter@593
   157
    IntVector _depth;
kpeter@593
   158
    IntVector _parent;
kpeter@593
   159
    IntVector _pred;
kpeter@593
   160
    IntVector _thread;
kpeter@593
   161
    BoolVector _forward;
kpeter@593
   162
    IntVector _state;
kpeter@593
   163
kpeter@593
   164
    // The root node
kpeter@593
   165
    int _root;
kpeter@593
   166
kpeter@593
   167
    // The entering arc in the current pivot iteration
kpeter@593
   168
    int _in_arc;
kpeter@593
   169
kpeter@593
   170
    // Temporary data used in the current pivot iteration
kpeter@593
   171
    int join, u_in, v_in, u_out, v_out;
kpeter@593
   172
    int right, first, second, last;
kpeter@593
   173
    int stem, par_stem, new_stem;
kpeter@593
   174
    Capacity delta;
kpeter@593
   175
kpeter@593
   176
  private:
kpeter@593
   177
kpeter@593
   178
    /// \brief Implementation of the "First Eligible" pivot rule for the
kpeter@593
   179
    /// \ref NetworkSimplex "network simplex" algorithm.
kpeter@593
   180
    ///
kpeter@593
   181
    /// This class implements the "First Eligible" pivot rule
kpeter@593
   182
    /// for the \ref NetworkSimplex "network simplex" algorithm.
kpeter@593
   183
    ///
kpeter@593
   184
    /// For more information see \ref NetworkSimplex::run().
kpeter@593
   185
    class FirstEligiblePivotRule
kpeter@593
   186
    {
kpeter@593
   187
    private:
kpeter@593
   188
kpeter@593
   189
      // References to the NetworkSimplex class
kpeter@593
   190
      const ArcVector &_arc;
kpeter@593
   191
      const IntVector  &_source;
kpeter@593
   192
      const IntVector  &_target;
kpeter@593
   193
      const CostVector &_cost;
kpeter@593
   194
      const IntVector  &_state;
kpeter@593
   195
      const CostVector &_pi;
kpeter@593
   196
      int &_in_arc;
kpeter@593
   197
      int _arc_num;
kpeter@593
   198
kpeter@593
   199
      // Pivot rule data
kpeter@593
   200
      int _next_arc;
kpeter@593
   201
kpeter@593
   202
    public:
kpeter@593
   203
kpeter@593
   204
      /// Constructor
kpeter@593
   205
      FirstEligiblePivotRule(NetworkSimplex &ns) :
kpeter@593
   206
        _arc(ns._arc), _source(ns._source), _target(ns._target),
kpeter@593
   207
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
kpeter@593
   208
        _in_arc(ns._in_arc), _arc_num(ns._arc_num), _next_arc(0)
kpeter@593
   209
      {}
kpeter@593
   210
kpeter@593
   211
      /// Find next entering arc
kpeter@593
   212
      bool findEnteringArc() {
kpeter@593
   213
        Cost c;
kpeter@593
   214
        for (int e = _next_arc; e < _arc_num; ++e) {
kpeter@593
   215
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@593
   216
          if (c < 0) {
kpeter@593
   217
            _in_arc = e;
kpeter@593
   218
            _next_arc = e + 1;
kpeter@593
   219
            return true;
kpeter@593
   220
          }
kpeter@593
   221
        }
kpeter@593
   222
        for (int e = 0; e < _next_arc; ++e) {
kpeter@593
   223
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@593
   224
          if (c < 0) {
kpeter@593
   225
            _in_arc = e;
kpeter@593
   226
            _next_arc = e + 1;
kpeter@593
   227
            return true;
kpeter@593
   228
          }
kpeter@593
   229
        }
kpeter@593
   230
        return false;
kpeter@593
   231
      }
kpeter@593
   232
kpeter@593
   233
    }; //class FirstEligiblePivotRule
kpeter@593
   234
kpeter@593
   235
kpeter@593
   236
    /// \brief Implementation of the "Best Eligible" pivot rule for the
kpeter@593
   237
    /// \ref NetworkSimplex "network simplex" algorithm.
kpeter@593
   238
    ///
kpeter@593
   239
    /// This class implements the "Best Eligible" pivot rule
kpeter@593
   240
    /// for the \ref NetworkSimplex "network simplex" algorithm.
kpeter@593
   241
    ///
kpeter@593
   242
    /// For more information see \ref NetworkSimplex::run().
kpeter@593
   243
    class BestEligiblePivotRule
kpeter@593
   244
    {
kpeter@593
   245
    private:
kpeter@593
   246
kpeter@593
   247
      // References to the NetworkSimplex class
kpeter@593
   248
      const ArcVector &_arc;
kpeter@593
   249
      const IntVector  &_source;
kpeter@593
   250
      const IntVector  &_target;
kpeter@593
   251
      const CostVector &_cost;
kpeter@593
   252
      const IntVector  &_state;
kpeter@593
   253
      const CostVector &_pi;
kpeter@593
   254
      int &_in_arc;
kpeter@593
   255
      int _arc_num;
kpeter@593
   256
kpeter@593
   257
    public:
kpeter@593
   258
kpeter@593
   259
      /// Constructor
kpeter@593
   260
      BestEligiblePivotRule(NetworkSimplex &ns) :
kpeter@593
   261
        _arc(ns._arc), _source(ns._source), _target(ns._target),
kpeter@593
   262
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
kpeter@593
   263
        _in_arc(ns._in_arc), _arc_num(ns._arc_num)
kpeter@593
   264
      {}
kpeter@593
   265
kpeter@593
   266
      /// Find next entering arc
kpeter@593
   267
      bool findEnteringArc() {
kpeter@593
   268
        Cost c, min = 0;
kpeter@593
   269
        for (int e = 0; e < _arc_num; ++e) {
kpeter@593
   270
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@593
   271
          if (c < min) {
kpeter@593
   272
            min = c;
kpeter@593
   273
            _in_arc = e;
kpeter@593
   274
          }
kpeter@593
   275
        }
kpeter@593
   276
        return min < 0;
kpeter@593
   277
      }
kpeter@593
   278
kpeter@593
   279
    }; //class BestEligiblePivotRule
kpeter@593
   280
kpeter@593
   281
kpeter@593
   282
    /// \brief Implementation of the "Block Search" pivot rule for the
kpeter@593
   283
    /// \ref NetworkSimplex "network simplex" algorithm.
kpeter@593
   284
    ///
kpeter@593
   285
    /// This class implements the "Block Search" pivot rule
kpeter@593
   286
    /// for the \ref NetworkSimplex "network simplex" algorithm.
kpeter@593
   287
    ///
kpeter@593
   288
    /// For more information see \ref NetworkSimplex::run().
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 ArcVector &_arc;
kpeter@593
   295
      const IntVector  &_source;
kpeter@593
   296
      const IntVector  &_target;
kpeter@593
   297
      const CostVector &_cost;
kpeter@593
   298
      const IntVector  &_state;
kpeter@593
   299
      const CostVector &_pi;
kpeter@593
   300
      int &_in_arc;
kpeter@593
   301
      int _arc_num;
kpeter@593
   302
kpeter@593
   303
      // Pivot rule data
kpeter@593
   304
      int _block_size;
kpeter@593
   305
      int _next_arc;
kpeter@593
   306
kpeter@593
   307
    public:
kpeter@593
   308
kpeter@593
   309
      /// Constructor
kpeter@593
   310
      BlockSearchPivotRule(NetworkSimplex &ns) :
kpeter@593
   311
        _arc(ns._arc), _source(ns._source), _target(ns._target),
kpeter@593
   312
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
kpeter@593
   313
        _in_arc(ns._in_arc), _arc_num(ns._arc_num), _next_arc(0)
kpeter@593
   314
      {
kpeter@593
   315
        // The main parameters of the pivot rule
kpeter@593
   316
        const double BLOCK_SIZE_FACTOR = 2.0;
kpeter@593
   317
        const int MIN_BLOCK_SIZE = 10;
kpeter@593
   318
kpeter@593
   319
        _block_size = std::max( int(BLOCK_SIZE_FACTOR * sqrt(_arc_num)),
kpeter@593
   320
                                MIN_BLOCK_SIZE );
kpeter@593
   321
      }
kpeter@593
   322
kpeter@593
   323
      /// Find next entering arc
kpeter@593
   324
      bool findEnteringArc() {
kpeter@593
   325
        Cost c, min = 0;
kpeter@593
   326
        int cnt = _block_size;
kpeter@593
   327
        int e, min_arc = _next_arc;
kpeter@593
   328
        for (e = _next_arc; e < _arc_num; ++e) {
kpeter@593
   329
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@593
   330
          if (c < min) {
kpeter@593
   331
            min = c;
kpeter@593
   332
            min_arc = e;
kpeter@593
   333
          }
kpeter@593
   334
          if (--cnt == 0) {
kpeter@593
   335
            if (min < 0) break;
kpeter@593
   336
            cnt = _block_size;
kpeter@593
   337
          }
kpeter@593
   338
        }
kpeter@593
   339
        if (min == 0 || cnt > 0) {
kpeter@593
   340
          for (e = 0; e < _next_arc; ++e) {
kpeter@593
   341
            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@593
   342
            if (c < min) {
kpeter@593
   343
              min = c;
kpeter@593
   344
              min_arc = e;
kpeter@593
   345
            }
kpeter@593
   346
            if (--cnt == 0) {
kpeter@593
   347
              if (min < 0) break;
kpeter@593
   348
              cnt = _block_size;
kpeter@593
   349
            }
kpeter@593
   350
          }
kpeter@593
   351
        }
kpeter@593
   352
        if (min >= 0) return false;
kpeter@593
   353
        _in_arc = min_arc;
kpeter@593
   354
        _next_arc = e;
kpeter@593
   355
        return true;
kpeter@593
   356
      }
kpeter@593
   357
kpeter@593
   358
    }; //class BlockSearchPivotRule
kpeter@593
   359
kpeter@593
   360
kpeter@593
   361
    /// \brief Implementation of the "Candidate List" pivot rule for the
kpeter@593
   362
    /// \ref NetworkSimplex "network simplex" algorithm.
kpeter@593
   363
    ///
kpeter@593
   364
    /// This class implements the "Candidate List" pivot rule
kpeter@593
   365
    /// for the \ref NetworkSimplex "network simplex" algorithm.
kpeter@593
   366
    ///
kpeter@593
   367
    /// For more information see \ref NetworkSimplex::run().
kpeter@593
   368
    class CandidateListPivotRule
kpeter@593
   369
    {
kpeter@593
   370
    private:
kpeter@593
   371
kpeter@593
   372
      // References to the NetworkSimplex class
kpeter@593
   373
      const ArcVector &_arc;
kpeter@593
   374
      const IntVector  &_source;
kpeter@593
   375
      const IntVector  &_target;
kpeter@593
   376
      const CostVector &_cost;
kpeter@593
   377
      const IntVector  &_state;
kpeter@593
   378
      const CostVector &_pi;
kpeter@593
   379
      int &_in_arc;
kpeter@593
   380
      int _arc_num;
kpeter@593
   381
kpeter@593
   382
      // Pivot rule data
kpeter@593
   383
      IntVector _candidates;
kpeter@593
   384
      int _list_length, _minor_limit;
kpeter@593
   385
      int _curr_length, _minor_count;
kpeter@593
   386
      int _next_arc;
kpeter@593
   387
kpeter@593
   388
    public:
kpeter@593
   389
kpeter@593
   390
      /// Constructor
kpeter@593
   391
      CandidateListPivotRule(NetworkSimplex &ns) :
kpeter@593
   392
        _arc(ns._arc), _source(ns._source), _target(ns._target),
kpeter@593
   393
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
kpeter@593
   394
        _in_arc(ns._in_arc), _arc_num(ns._arc_num), _next_arc(0)
kpeter@593
   395
      {
kpeter@593
   396
        // The main parameters of the pivot rule
kpeter@593
   397
        const double LIST_LENGTH_FACTOR = 1.0;
kpeter@593
   398
        const int MIN_LIST_LENGTH = 10;
kpeter@593
   399
        const double MINOR_LIMIT_FACTOR = 0.1;
kpeter@593
   400
        const int MIN_MINOR_LIMIT = 3;
kpeter@593
   401
kpeter@593
   402
        _list_length = std::max( int(LIST_LENGTH_FACTOR * sqrt(_arc_num)),
kpeter@593
   403
                                 MIN_LIST_LENGTH );
kpeter@593
   404
        _minor_limit = std::max( int(MINOR_LIMIT_FACTOR * _list_length),
kpeter@593
   405
                                 MIN_MINOR_LIMIT );
kpeter@593
   406
        _curr_length = _minor_count = 0;
kpeter@593
   407
        _candidates.resize(_list_length);
kpeter@593
   408
      }
kpeter@593
   409
kpeter@593
   410
      /// Find next entering arc
kpeter@593
   411
      bool findEnteringArc() {
kpeter@593
   412
        Cost min, c;
kpeter@593
   413
        int e, min_arc = _next_arc;
kpeter@593
   414
        if (_curr_length > 0 && _minor_count < _minor_limit) {
kpeter@593
   415
          // Minor iteration: select the best eligible arc from the
kpeter@593
   416
          // current candidate list
kpeter@593
   417
          ++_minor_count;
kpeter@593
   418
          min = 0;
kpeter@593
   419
          for (int i = 0; i < _curr_length; ++i) {
kpeter@593
   420
            e = _candidates[i];
kpeter@593
   421
            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@593
   422
            if (c < min) {
kpeter@593
   423
              min = c;
kpeter@593
   424
              min_arc = e;
kpeter@593
   425
            }
kpeter@593
   426
            if (c >= 0) {
kpeter@593
   427
              _candidates[i--] = _candidates[--_curr_length];
kpeter@593
   428
            }
kpeter@593
   429
          }
kpeter@593
   430
          if (min < 0) {
kpeter@593
   431
            _in_arc = min_arc;
kpeter@593
   432
            return true;
kpeter@593
   433
          }
kpeter@593
   434
        }
kpeter@593
   435
kpeter@593
   436
        // Major iteration: build a new candidate list
kpeter@593
   437
        min = 0;
kpeter@593
   438
        _curr_length = 0;
kpeter@593
   439
        for (e = _next_arc; e < _arc_num; ++e) {
kpeter@593
   440
          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@593
   441
          if (c < 0) {
kpeter@593
   442
            _candidates[_curr_length++] = e;
kpeter@593
   443
            if (c < min) {
kpeter@593
   444
              min = c;
kpeter@593
   445
              min_arc = e;
kpeter@593
   446
            }
kpeter@593
   447
            if (_curr_length == _list_length) break;
kpeter@593
   448
          }
kpeter@593
   449
        }
kpeter@593
   450
        if (_curr_length < _list_length) {
kpeter@593
   451
          for (e = 0; e < _next_arc; ++e) {
kpeter@593
   452
            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@593
   453
            if (c < 0) {
kpeter@593
   454
              _candidates[_curr_length++] = e;
kpeter@593
   455
              if (c < min) {
kpeter@593
   456
                min = c;
kpeter@593
   457
                min_arc = e;
kpeter@593
   458
              }
kpeter@593
   459
              if (_curr_length == _list_length) break;
kpeter@593
   460
            }
kpeter@593
   461
          }
kpeter@593
   462
        }
kpeter@593
   463
        if (_curr_length == 0) return false;
kpeter@593
   464
        _minor_count = 1;
kpeter@593
   465
        _in_arc = min_arc;
kpeter@593
   466
        _next_arc = e;
kpeter@593
   467
        return true;
kpeter@593
   468
      }
kpeter@593
   469
kpeter@593
   470
    }; //class CandidateListPivotRule
kpeter@593
   471
kpeter@593
   472
kpeter@593
   473
    /// \brief Implementation of the "Altering Candidate List" pivot rule
kpeter@593
   474
    /// for the \ref NetworkSimplex "network simplex" algorithm.
kpeter@593
   475
    ///
kpeter@593
   476
    /// This class implements the "Altering Candidate List" pivot rule
kpeter@593
   477
    /// for the \ref NetworkSimplex "network simplex" algorithm.
kpeter@593
   478
    ///
kpeter@593
   479
    /// For more information see \ref NetworkSimplex::run().
kpeter@593
   480
    class AlteringListPivotRule
kpeter@593
   481
    {
kpeter@593
   482
    private:
kpeter@593
   483
kpeter@593
   484
      // References to the NetworkSimplex class
kpeter@593
   485
      const ArcVector &_arc;
kpeter@593
   486
      const IntVector  &_source;
kpeter@593
   487
      const IntVector  &_target;
kpeter@593
   488
      const CostVector &_cost;
kpeter@593
   489
      const IntVector  &_state;
kpeter@593
   490
      const CostVector &_pi;
kpeter@593
   491
      int &_in_arc;
kpeter@593
   492
      int _arc_num;
kpeter@593
   493
kpeter@593
   494
      // Pivot rule data
kpeter@593
   495
      int _block_size, _head_length, _curr_length;
kpeter@593
   496
      int _next_arc;
kpeter@593
   497
      IntVector _candidates;
kpeter@593
   498
      CostVector _cand_cost;
kpeter@593
   499
kpeter@593
   500
      // Functor class to compare arcs during sort of the candidate list
kpeter@593
   501
      class SortFunc
kpeter@593
   502
      {
kpeter@593
   503
      private:
kpeter@593
   504
        const CostVector &_map;
kpeter@593
   505
      public:
kpeter@593
   506
        SortFunc(const CostVector &map) : _map(map) {}
kpeter@593
   507
        bool operator()(int left, int right) {
kpeter@593
   508
          return _map[left] > _map[right];
kpeter@593
   509
        }
kpeter@593
   510
      };
kpeter@593
   511
kpeter@593
   512
      SortFunc _sort_func;
kpeter@593
   513
kpeter@593
   514
    public:
kpeter@593
   515
kpeter@593
   516
      /// Constructor
kpeter@593
   517
      AlteringListPivotRule(NetworkSimplex &ns) :
kpeter@593
   518
        _arc(ns._arc), _source(ns._source), _target(ns._target),
kpeter@593
   519
        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
kpeter@593
   520
        _in_arc(ns._in_arc), _arc_num(ns._arc_num),
kpeter@593
   521
        _next_arc(0), _cand_cost(ns._arc_num), _sort_func(_cand_cost)
kpeter@593
   522
      {
kpeter@593
   523
        // The main parameters of the pivot rule
kpeter@593
   524
        const double BLOCK_SIZE_FACTOR = 1.5;
kpeter@593
   525
        const int MIN_BLOCK_SIZE = 10;
kpeter@593
   526
        const double HEAD_LENGTH_FACTOR = 0.1;
kpeter@593
   527
        const int MIN_HEAD_LENGTH = 3;
kpeter@593
   528
kpeter@593
   529
        _block_size = std::max( int(BLOCK_SIZE_FACTOR * sqrt(_arc_num)),
kpeter@593
   530
                                MIN_BLOCK_SIZE );
kpeter@593
   531
        _head_length = std::max( int(HEAD_LENGTH_FACTOR * _block_size),
kpeter@593
   532
                                 MIN_HEAD_LENGTH );
kpeter@593
   533
        _candidates.resize(_head_length + _block_size);
kpeter@593
   534
        _curr_length = 0;
kpeter@593
   535
      }
kpeter@593
   536
kpeter@593
   537
      /// Find next entering arc
kpeter@593
   538
      bool findEnteringArc() {
kpeter@593
   539
        // Check the current candidate list
kpeter@593
   540
        int e;
kpeter@593
   541
        for (int i = 0; i < _curr_length; ++i) {
kpeter@593
   542
          e = _candidates[i];
kpeter@593
   543
          _cand_cost[e] = _state[e] *
kpeter@593
   544
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@593
   545
          if (_cand_cost[e] >= 0) {
kpeter@593
   546
            _candidates[i--] = _candidates[--_curr_length];
kpeter@593
   547
          }
kpeter@593
   548
        }
kpeter@593
   549
kpeter@593
   550
        // Extend the list
kpeter@593
   551
        int cnt = _block_size;
kpeter@593
   552
        int last_edge = 0;
kpeter@593
   553
        int limit = _head_length;
kpeter@593
   554
kpeter@593
   555
        for (int e = _next_arc; e < _arc_num; ++e) {
kpeter@593
   556
          _cand_cost[e] = _state[e] *
kpeter@593
   557
            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@593
   558
          if (_cand_cost[e] < 0) {
kpeter@593
   559
            _candidates[_curr_length++] = e;
kpeter@593
   560
            last_edge = e;
kpeter@593
   561
          }
kpeter@593
   562
          if (--cnt == 0) {
kpeter@593
   563
            if (_curr_length > limit) break;
kpeter@593
   564
            limit = 0;
kpeter@593
   565
            cnt = _block_size;
kpeter@593
   566
          }
kpeter@593
   567
        }
kpeter@593
   568
        if (_curr_length <= limit) {
kpeter@593
   569
          for (int e = 0; e < _next_arc; ++e) {
kpeter@593
   570
            _cand_cost[e] = _state[e] *
kpeter@593
   571
              (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
kpeter@593
   572
            if (_cand_cost[e] < 0) {
kpeter@593
   573
              _candidates[_curr_length++] = e;
kpeter@593
   574
              last_edge = e;
kpeter@593
   575
            }
kpeter@593
   576
            if (--cnt == 0) {
kpeter@593
   577
              if (_curr_length > limit) break;
kpeter@593
   578
              limit = 0;
kpeter@593
   579
              cnt = _block_size;
kpeter@593
   580
            }
kpeter@593
   581
          }
kpeter@593
   582
        }
kpeter@593
   583
        if (_curr_length == 0) return false;
kpeter@593
   584
        _next_arc = last_edge + 1;
kpeter@593
   585
kpeter@593
   586
        // Make heap of the candidate list (approximating a partial sort)
kpeter@593
   587
        make_heap( _candidates.begin(), _candidates.begin() + _curr_length,
kpeter@593
   588
                   _sort_func );
kpeter@593
   589
kpeter@593
   590
        // Pop the first element of the heap
kpeter@593
   591
        _in_arc = _candidates[0];
kpeter@593
   592
        pop_heap( _candidates.begin(), _candidates.begin() + _curr_length,
kpeter@593
   593
                  _sort_func );
kpeter@593
   594
        _curr_length = std::min(_head_length, _curr_length - 1);
kpeter@593
   595
        return true;
kpeter@593
   596
      }
kpeter@593
   597
kpeter@593
   598
    }; //class AlteringListPivotRule
kpeter@593
   599
kpeter@593
   600
  public:
kpeter@593
   601
kpeter@593
   602
    /// \brief General constructor (with lower bounds).
kpeter@593
   603
    ///
kpeter@593
   604
    /// General constructor (with lower bounds).
kpeter@593
   605
    ///
kpeter@593
   606
    /// \param digraph The digraph the algorithm runs on.
kpeter@593
   607
    /// \param lower The lower bounds of the arcs.
kpeter@593
   608
    /// \param capacity The capacities (upper bounds) of the arcs.
kpeter@593
   609
    /// \param cost The cost (length) values of the arcs.
kpeter@593
   610
    /// \param supply The supply values of the nodes (signed).
kpeter@593
   611
    NetworkSimplex( const Digraph &digraph,
kpeter@593
   612
                    const LowerMap &lower,
kpeter@593
   613
                    const CapacityMap &capacity,
kpeter@593
   614
                    const CostMap &cost,
kpeter@593
   615
                    const SupplyMap &supply ) :
kpeter@593
   616
      _orig_graph(digraph), _orig_lower(&lower), _orig_cap(capacity),
kpeter@593
   617
      _orig_cost(cost), _orig_supply(&supply),
kpeter@593
   618
      _flow_result(NULL), _potential_result(NULL),
kpeter@593
   619
      _local_flow(false), _local_potential(false),
kpeter@593
   620
      _node_id(digraph)
kpeter@593
   621
    {}
kpeter@593
   622
kpeter@593
   623
    /// \brief General constructor (without lower bounds).
kpeter@593
   624
    ///
kpeter@593
   625
    /// General constructor (without lower bounds).
kpeter@593
   626
    ///
kpeter@593
   627
    /// \param digraph The digraph the algorithm runs on.
kpeter@593
   628
    /// \param capacity The capacities (upper bounds) of the arcs.
kpeter@593
   629
    /// \param cost The cost (length) values of the arcs.
kpeter@593
   630
    /// \param supply The supply values of the nodes (signed).
kpeter@593
   631
    NetworkSimplex( const Digraph &digraph,
kpeter@593
   632
                    const CapacityMap &capacity,
kpeter@593
   633
                    const CostMap &cost,
kpeter@593
   634
                    const SupplyMap &supply ) :
kpeter@593
   635
      _orig_graph(digraph), _orig_lower(NULL), _orig_cap(capacity),
kpeter@593
   636
      _orig_cost(cost), _orig_supply(&supply),
kpeter@593
   637
      _flow_result(NULL), _potential_result(NULL),
kpeter@593
   638
      _local_flow(false), _local_potential(false),
kpeter@593
   639
      _node_id(digraph)
kpeter@593
   640
    {}
kpeter@593
   641
kpeter@593
   642
    /// \brief Simple constructor (with lower bounds).
kpeter@593
   643
    ///
kpeter@593
   644
    /// Simple constructor (with lower bounds).
kpeter@593
   645
    ///
kpeter@593
   646
    /// \param digraph The digraph the algorithm runs on.
kpeter@593
   647
    /// \param lower The lower bounds of the arcs.
kpeter@593
   648
    /// \param capacity The capacities (upper bounds) of the arcs.
kpeter@593
   649
    /// \param cost The cost (length) values of the arcs.
kpeter@593
   650
    /// \param s The source node.
kpeter@593
   651
    /// \param t The target node.
kpeter@593
   652
    /// \param flow_value The required amount of flow from node \c s
kpeter@593
   653
    /// to node \c t (i.e. the supply of \c s and the demand of \c t).
kpeter@593
   654
    NetworkSimplex( const Digraph &digraph,
kpeter@593
   655
                    const LowerMap &lower,
kpeter@593
   656
                    const CapacityMap &capacity,
kpeter@593
   657
                    const CostMap &cost,
kpeter@593
   658
                    Node s, Node t,
kpeter@593
   659
                    Capacity flow_value ) :
kpeter@593
   660
      _orig_graph(digraph), _orig_lower(&lower), _orig_cap(capacity),
kpeter@593
   661
      _orig_cost(cost), _orig_supply(NULL),
kpeter@593
   662
      _orig_source(s), _orig_target(t), _orig_flow_value(flow_value),
kpeter@593
   663
      _flow_result(NULL), _potential_result(NULL),
kpeter@593
   664
      _local_flow(false), _local_potential(false),
kpeter@593
   665
      _node_id(digraph)
kpeter@593
   666
    {}
kpeter@593
   667
kpeter@593
   668
    /// \brief Simple constructor (without lower bounds).
kpeter@593
   669
    ///
kpeter@593
   670
    /// Simple constructor (without lower bounds).
kpeter@593
   671
    ///
kpeter@593
   672
    /// \param digraph The digraph the algorithm runs on.
kpeter@593
   673
    /// \param capacity The capacities (upper bounds) of the arcs.
kpeter@593
   674
    /// \param cost The cost (length) values of the arcs.
kpeter@593
   675
    /// \param s The source node.
kpeter@593
   676
    /// \param t The target node.
kpeter@593
   677
    /// \param flow_value The required amount of flow from node \c s
kpeter@593
   678
    /// to node \c t (i.e. the supply of \c s and the demand of \c t).
kpeter@593
   679
    NetworkSimplex( const Digraph &digraph,
kpeter@593
   680
                    const CapacityMap &capacity,
kpeter@593
   681
                    const CostMap &cost,
kpeter@593
   682
                    Node s, Node t,
kpeter@593
   683
                    Capacity flow_value ) :
kpeter@593
   684
      _orig_graph(digraph), _orig_lower(NULL), _orig_cap(capacity),
kpeter@593
   685
      _orig_cost(cost), _orig_supply(NULL),
kpeter@593
   686
      _orig_source(s), _orig_target(t), _orig_flow_value(flow_value),
kpeter@593
   687
      _flow_result(NULL), _potential_result(NULL),
kpeter@593
   688
      _local_flow(false), _local_potential(false),
kpeter@593
   689
      _node_id(digraph)
kpeter@593
   690
    {}
kpeter@593
   691
kpeter@593
   692
    /// Destructor.
kpeter@593
   693
    ~NetworkSimplex() {
kpeter@593
   694
      if (_local_flow) delete _flow_result;
kpeter@593
   695
      if (_local_potential) delete _potential_result;
kpeter@593
   696
    }
kpeter@593
   697
kpeter@593
   698
    /// \brief Set the flow map.
kpeter@593
   699
    ///
kpeter@593
   700
    /// This function sets the flow map.
kpeter@593
   701
    ///
kpeter@593
   702
    /// \return <tt>(*this)</tt>
kpeter@593
   703
    NetworkSimplex& flowMap(FlowMap &map) {
kpeter@593
   704
      if (_local_flow) {
kpeter@593
   705
        delete _flow_result;
kpeter@593
   706
        _local_flow = false;
kpeter@593
   707
      }
kpeter@593
   708
      _flow_result = &map;
kpeter@593
   709
      return *this;
kpeter@593
   710
    }
kpeter@593
   711
kpeter@593
   712
    /// \brief Set the potential map.
kpeter@593
   713
    ///
kpeter@593
   714
    /// This function sets the potential map.
kpeter@593
   715
    ///
kpeter@593
   716
    /// \return <tt>(*this)</tt>
kpeter@593
   717
    NetworkSimplex& potentialMap(PotentialMap &map) {
kpeter@593
   718
      if (_local_potential) {
kpeter@593
   719
        delete _potential_result;
kpeter@593
   720
        _local_potential = false;
kpeter@593
   721
      }
kpeter@593
   722
      _potential_result = &map;
kpeter@593
   723
      return *this;
kpeter@593
   724
    }
kpeter@593
   725
kpeter@593
   726
    /// \name Execution control
kpeter@593
   727
    /// The algorithm can be executed using the
kpeter@593
   728
    /// \ref lemon::NetworkSimplex::run() "run()" function.
kpeter@593
   729
    /// @{
kpeter@593
   730
kpeter@593
   731
    /// \brief Run the algorithm.
kpeter@593
   732
    ///
kpeter@593
   733
    /// This function runs the algorithm.
kpeter@593
   734
    ///
kpeter@593
   735
    /// \param pivot_rule The pivot rule that is used during the
kpeter@593
   736
    /// algorithm.
kpeter@593
   737
    ///
kpeter@593
   738
    /// The available pivot rules:
kpeter@593
   739
    ///
kpeter@593
   740
    /// - FIRST_ELIGIBLE_PIVOT The next eligible arc is selected in
kpeter@593
   741
    /// a wraparound fashion in every iteration
kpeter@593
   742
    /// (\ref FirstEligiblePivotRule).
kpeter@593
   743
    ///
kpeter@593
   744
    /// - BEST_ELIGIBLE_PIVOT The best eligible arc is selected in
kpeter@593
   745
    /// every iteration (\ref BestEligiblePivotRule).
kpeter@593
   746
    ///
kpeter@593
   747
    /// - BLOCK_SEARCH_PIVOT A specified number of arcs are examined in
kpeter@593
   748
    /// every iteration in a wraparound fashion and the best eligible
kpeter@593
   749
    /// arc is selected from this block (\ref BlockSearchPivotRule).
kpeter@593
   750
    ///
kpeter@593
   751
    /// - CANDIDATE_LIST_PIVOT In a major iteration a candidate list is
kpeter@593
   752
    /// built from eligible arcs in a wraparound fashion and in the
kpeter@593
   753
    /// following minor iterations the best eligible arc is selected
kpeter@593
   754
    /// from this list (\ref CandidateListPivotRule).
kpeter@593
   755
    ///
kpeter@593
   756
    /// - ALTERING_LIST_PIVOT It is a modified version of the
kpeter@593
   757
    /// "Candidate List" pivot rule. It keeps only the several best
kpeter@593
   758
    /// eligible arcs from the former candidate list and extends this
kpeter@593
   759
    /// list in every iteration (\ref AlteringListPivotRule).
kpeter@593
   760
    ///
kpeter@593
   761
    /// According to our comprehensive benchmark tests the "Block Search"
kpeter@593
   762
    /// pivot rule proved to be the fastest and the most robust on
kpeter@593
   763
    /// various test inputs. Thus it is the default option.
kpeter@593
   764
    ///
kpeter@593
   765
    /// \return \c true if a feasible flow can be found.
kpeter@593
   766
    bool run(PivotRuleEnum pivot_rule = BLOCK_SEARCH_PIVOT) {
kpeter@593
   767
      return init() && start(pivot_rule);
kpeter@593
   768
    }
kpeter@593
   769
kpeter@593
   770
    /// @}
kpeter@593
   771
kpeter@593
   772
    /// \name Query Functions
kpeter@593
   773
    /// The results of the algorithm can be obtained using these
kpeter@593
   774
    /// functions.\n
kpeter@593
   775
    /// \ref lemon::NetworkSimplex::run() "run()" must be called before
kpeter@593
   776
    /// using them.
kpeter@593
   777
    /// @{
kpeter@593
   778
kpeter@593
   779
    /// \brief Return a const reference to the flow map.
kpeter@593
   780
    ///
kpeter@593
   781
    /// This function returns a const reference to an arc map storing
kpeter@593
   782
    /// the found flow.
kpeter@593
   783
    ///
kpeter@593
   784
    /// \pre \ref run() must be called before using this function.
kpeter@593
   785
    const FlowMap& flowMap() const {
kpeter@593
   786
      return *_flow_result;
kpeter@593
   787
    }
kpeter@593
   788
kpeter@593
   789
    /// \brief Return a const reference to the potential map
kpeter@593
   790
    /// (the dual solution).
kpeter@593
   791
    ///
kpeter@593
   792
    /// This function returns a const reference to a node map storing
kpeter@593
   793
    /// the found potentials (the dual solution).
kpeter@593
   794
    ///
kpeter@593
   795
    /// \pre \ref run() must be called before using this function.
kpeter@593
   796
    const PotentialMap& potentialMap() const {
kpeter@593
   797
      return *_potential_result;
kpeter@593
   798
    }
kpeter@593
   799
kpeter@593
   800
    /// \brief Return the flow on the given arc.
kpeter@593
   801
    ///
kpeter@593
   802
    /// This function returns the flow on the given arc.
kpeter@593
   803
    ///
kpeter@593
   804
    /// \pre \ref run() must be called before using this function.
kpeter@593
   805
    Capacity flow(const Arc& arc) const {
kpeter@593
   806
      return (*_flow_result)[arc];
kpeter@593
   807
    }
kpeter@593
   808
kpeter@593
   809
    /// \brief Return the potential of the given node.
kpeter@593
   810
    ///
kpeter@593
   811
    /// This function returns the potential of the given node.
kpeter@593
   812
    ///
kpeter@593
   813
    /// \pre \ref run() must be called before using this function.
kpeter@593
   814
    Cost potential(const Node& node) const {
kpeter@593
   815
      return (*_potential_result)[node];
kpeter@593
   816
    }
kpeter@593
   817
kpeter@593
   818
    /// \brief Return the total cost of the found flow.
kpeter@593
   819
    ///
kpeter@593
   820
    /// This function returns the total cost of the found flow.
kpeter@593
   821
    /// The complexity of the function is \f$ O(e) \f$.
kpeter@593
   822
    ///
kpeter@593
   823
    /// \pre \ref run() must be called before using this function.
kpeter@593
   824
    Cost totalCost() const {
kpeter@593
   825
      Cost c = 0;
kpeter@593
   826
      for (ArcIt e(_orig_graph); e != INVALID; ++e)
kpeter@593
   827
        c += (*_flow_result)[e] * _orig_cost[e];
kpeter@593
   828
      return c;
kpeter@593
   829
    }
kpeter@593
   830
kpeter@593
   831
    /// @}
kpeter@593
   832
kpeter@593
   833
  private:
kpeter@593
   834
kpeter@593
   835
    // Initialize internal data structures
kpeter@593
   836
    bool init() {
kpeter@593
   837
      // Initialize result maps
kpeter@593
   838
      if (!_flow_result) {
kpeter@593
   839
        _flow_result = new FlowMap(_orig_graph);
kpeter@593
   840
        _local_flow = true;
kpeter@593
   841
      }
kpeter@593
   842
      if (!_potential_result) {
kpeter@593
   843
        _potential_result = new PotentialMap(_orig_graph);
kpeter@593
   844
        _local_potential = true;
kpeter@593
   845
      }
kpeter@593
   846
kpeter@593
   847
      // Initialize vectors
kpeter@593
   848
      _node_num = countNodes(_orig_graph);
kpeter@593
   849
      _arc_num = countArcs(_orig_graph);
kpeter@593
   850
      int all_node_num = _node_num + 1;
kpeter@593
   851
      int all_edge_num = _arc_num + _node_num;
kpeter@593
   852
kpeter@593
   853
      _arc.resize(_arc_num);
kpeter@593
   854
      _node.reserve(_node_num);
kpeter@593
   855
      _source.resize(all_edge_num);
kpeter@593
   856
      _target.resize(all_edge_num);
kpeter@593
   857
kpeter@593
   858
      _cap.resize(all_edge_num);
kpeter@593
   859
      _cost.resize(all_edge_num);
kpeter@593
   860
      _supply.resize(all_node_num);
kpeter@593
   861
      _flow.resize(all_edge_num, 0);
kpeter@593
   862
      _pi.resize(all_node_num, 0);
kpeter@593
   863
kpeter@593
   864
      _depth.resize(all_node_num);
kpeter@593
   865
      _parent.resize(all_node_num);
kpeter@593
   866
      _pred.resize(all_node_num);
kpeter@593
   867
      _thread.resize(all_node_num);
kpeter@593
   868
      _forward.resize(all_node_num);
kpeter@593
   869
      _state.resize(all_edge_num, STATE_LOWER);
kpeter@593
   870
kpeter@593
   871
      // Initialize node related data
kpeter@593
   872
      bool valid_supply = true;
kpeter@593
   873
      if (_orig_supply) {
kpeter@593
   874
        Supply sum = 0;
kpeter@593
   875
        int i = 0;
kpeter@593
   876
        for (NodeIt n(_orig_graph); n != INVALID; ++n, ++i) {
kpeter@593
   877
          _node.push_back(n);
kpeter@593
   878
          _node_id[n] = i;
kpeter@593
   879
          _supply[i] = (*_orig_supply)[n];
kpeter@593
   880
          sum += _supply[i];
kpeter@593
   881
        }
kpeter@593
   882
        valid_supply = (sum == 0);
kpeter@593
   883
      } else {
kpeter@593
   884
        int i = 0;
kpeter@593
   885
        for (NodeIt n(_orig_graph); n != INVALID; ++n, ++i) {
kpeter@593
   886
          _node.push_back(n);
kpeter@593
   887
          _node_id[n] = i;
kpeter@593
   888
          _supply[i] = 0;
kpeter@593
   889
        }
kpeter@593
   890
        _supply[_node_id[_orig_source]] =  _orig_flow_value;
kpeter@593
   891
        _supply[_node_id[_orig_target]] = -_orig_flow_value;
kpeter@593
   892
      }
kpeter@593
   893
      if (!valid_supply) return false;
kpeter@593
   894
kpeter@593
   895
      // Set data for the artificial root node
kpeter@593
   896
      _root = _node_num;
kpeter@593
   897
      _depth[_root] = 0;
kpeter@593
   898
      _parent[_root] = -1;
kpeter@593
   899
      _pred[_root] = -1;
kpeter@593
   900
      _thread[_root] = 0;
kpeter@593
   901
      _supply[_root] = 0;
kpeter@593
   902
      _pi[_root] = 0;
kpeter@593
   903
kpeter@593
   904
      // Store the arcs in a mixed order
kpeter@593
   905
      int k = std::max(int(sqrt(_arc_num)), 10);
kpeter@593
   906
      int i = 0;
kpeter@593
   907
      for (ArcIt e(_orig_graph); e != INVALID; ++e) {
kpeter@593
   908
        _arc[i] = e;
kpeter@593
   909
        if ((i += k) >= _arc_num) i = (i % k) + 1;
kpeter@593
   910
      }
kpeter@593
   911
kpeter@593
   912
      // Initialize arc maps
kpeter@593
   913
      for (int i = 0; i != _arc_num; ++i) {
kpeter@593
   914
        Arc e = _arc[i];
kpeter@593
   915
        _source[i] = _node_id[_orig_graph.source(e)];
kpeter@593
   916
        _target[i] = _node_id[_orig_graph.target(e)];
kpeter@593
   917
        _cost[i] = _orig_cost[e];
kpeter@593
   918
        _cap[i] = _orig_cap[e];
kpeter@593
   919
      }
kpeter@593
   920
kpeter@593
   921
      // Remove non-zero lower bounds
kpeter@593
   922
      if (_orig_lower) {
kpeter@593
   923
        for (int i = 0; i != _arc_num; ++i) {
kpeter@593
   924
          Capacity c = (*_orig_lower)[_arc[i]];
kpeter@593
   925
          if (c != 0) {
kpeter@593
   926
            _cap[i] -= c;
kpeter@593
   927
            _supply[_source[i]] -= c;
kpeter@593
   928
            _supply[_target[i]] += c;
kpeter@593
   929
          }
kpeter@593
   930
        }
kpeter@593
   931
      }
kpeter@593
   932
kpeter@593
   933
      // Add artificial arcs and initialize the spanning tree data structure
kpeter@593
   934
      Cost max_cost = std::numeric_limits<Cost>::max() / 4;
kpeter@593
   935
      Capacity max_cap = std::numeric_limits<Capacity>::max();
kpeter@593
   936
      for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) {
kpeter@593
   937
        _thread[u] = u + 1;
kpeter@593
   938
        _depth[u] = 1;
kpeter@593
   939
        _parent[u] = _root;
kpeter@593
   940
        _pred[u] = e;
kpeter@593
   941
        if (_supply[u] >= 0) {
kpeter@593
   942
          _flow[e] = _supply[u];
kpeter@593
   943
          _forward[u] = true;
kpeter@593
   944
          _pi[u] = -max_cost;
kpeter@593
   945
        } else {
kpeter@593
   946
          _flow[e] = -_supply[u];
kpeter@593
   947
          _forward[u] = false;
kpeter@593
   948
          _pi[u] = max_cost;
kpeter@593
   949
        }
kpeter@593
   950
        _cost[e] = max_cost;
kpeter@593
   951
        _cap[e] = max_cap;
kpeter@593
   952
        _state[e] = STATE_TREE;
kpeter@593
   953
      }
kpeter@593
   954
kpeter@593
   955
      return true;
kpeter@593
   956
    }
kpeter@593
   957
kpeter@593
   958
    // Find the join node
kpeter@593
   959
    void findJoinNode() {
kpeter@593
   960
      int u = _source[_in_arc];
kpeter@593
   961
      int v = _target[_in_arc];
kpeter@593
   962
      while (_depth[u] > _depth[v]) u = _parent[u];
kpeter@593
   963
      while (_depth[v] > _depth[u]) v = _parent[v];
kpeter@593
   964
      while (u != v) {
kpeter@593
   965
        u = _parent[u];
kpeter@593
   966
        v = _parent[v];
kpeter@593
   967
      }
kpeter@593
   968
      join = u;
kpeter@593
   969
    }
kpeter@593
   970
kpeter@593
   971
    // Find the leaving arc of the cycle and returns true if the
kpeter@593
   972
    // leaving arc is not the same as the entering arc
kpeter@593
   973
    bool findLeavingArc() {
kpeter@593
   974
      // Initialize first and second nodes according to the direction
kpeter@593
   975
      // of the cycle
kpeter@593
   976
      if (_state[_in_arc] == STATE_LOWER) {
kpeter@593
   977
        first  = _source[_in_arc];
kpeter@593
   978
        second = _target[_in_arc];
kpeter@593
   979
      } else {
kpeter@593
   980
        first  = _target[_in_arc];
kpeter@593
   981
        second = _source[_in_arc];
kpeter@593
   982
      }
kpeter@593
   983
      delta = _cap[_in_arc];
kpeter@593
   984
      int result = 0;
kpeter@593
   985
      Capacity d;
kpeter@593
   986
      int e;
kpeter@593
   987
kpeter@593
   988
      // Search the cycle along the path form the first node to the root
kpeter@593
   989
      for (int u = first; u != join; u = _parent[u]) {
kpeter@593
   990
        e = _pred[u];
kpeter@593
   991
        d = _forward[u] ? _flow[e] : _cap[e] - _flow[e];
kpeter@593
   992
        if (d < delta) {
kpeter@593
   993
          delta = d;
kpeter@593
   994
          u_out = u;
kpeter@593
   995
          result = 1;
kpeter@593
   996
        }
kpeter@593
   997
      }
kpeter@593
   998
      // Search the cycle along the path form the second node to the root
kpeter@593
   999
      for (int u = second; u != join; u = _parent[u]) {
kpeter@593
  1000
        e = _pred[u];
kpeter@593
  1001
        d = _forward[u] ? _cap[e] - _flow[e] : _flow[e];
kpeter@593
  1002
        if (d <= delta) {
kpeter@593
  1003
          delta = d;
kpeter@593
  1004
          u_out = u;
kpeter@593
  1005
          result = 2;
kpeter@593
  1006
        }
kpeter@593
  1007
      }
kpeter@593
  1008
kpeter@593
  1009
      if (result == 1) {
kpeter@593
  1010
        u_in = first;
kpeter@593
  1011
        v_in = second;
kpeter@593
  1012
      } else {
kpeter@593
  1013
        u_in = second;
kpeter@593
  1014
        v_in = first;
kpeter@593
  1015
      }
kpeter@593
  1016
      return result != 0;
kpeter@593
  1017
    }
kpeter@593
  1018
kpeter@593
  1019
    // Change _flow and _state vectors
kpeter@593
  1020
    void changeFlow(bool change) {
kpeter@593
  1021
      // Augment along the cycle
kpeter@593
  1022
      if (delta > 0) {
kpeter@593
  1023
        Capacity val = _state[_in_arc] * delta;
kpeter@593
  1024
        _flow[_in_arc] += val;
kpeter@593
  1025
        for (int u = _source[_in_arc]; u != join; u = _parent[u]) {
kpeter@593
  1026
          _flow[_pred[u]] += _forward[u] ? -val : val;
kpeter@593
  1027
        }
kpeter@593
  1028
        for (int u = _target[_in_arc]; u != join; u = _parent[u]) {
kpeter@593
  1029
          _flow[_pred[u]] += _forward[u] ? val : -val;
kpeter@593
  1030
        }
kpeter@593
  1031
      }
kpeter@593
  1032
      // Update the state of the entering and leaving arcs
kpeter@593
  1033
      if (change) {
kpeter@593
  1034
        _state[_in_arc] = STATE_TREE;
kpeter@593
  1035
        _state[_pred[u_out]] =
kpeter@593
  1036
          (_flow[_pred[u_out]] == 0) ? STATE_LOWER : STATE_UPPER;
kpeter@593
  1037
      } else {
kpeter@593
  1038
        _state[_in_arc] = -_state[_in_arc];
kpeter@593
  1039
      }
kpeter@593
  1040
    }
kpeter@593
  1041
kpeter@593
  1042
    // Update _thread and _parent vectors
kpeter@593
  1043
    void updateThreadParent() {
kpeter@593
  1044
      int u;
kpeter@593
  1045
      v_out = _parent[u_out];
kpeter@593
  1046
kpeter@593
  1047
      // Handle the case when join and v_out coincide
kpeter@593
  1048
      bool par_first = false;
kpeter@593
  1049
      if (join == v_out) {
kpeter@593
  1050
        for (u = join; u != u_in && u != v_in; u = _thread[u]) ;
kpeter@593
  1051
        if (u == v_in) {
kpeter@593
  1052
          par_first = true;
kpeter@593
  1053
          while (_thread[u] != u_out) u = _thread[u];
kpeter@593
  1054
          first = u;
kpeter@593
  1055
        }
kpeter@593
  1056
      }
kpeter@593
  1057
kpeter@593
  1058
      // Find the last successor of u_in (u) and the node after it (right)
kpeter@593
  1059
      // according to the thread index
kpeter@593
  1060
      for (u = u_in; _depth[_thread[u]] > _depth[u_in]; u = _thread[u]) ;
kpeter@593
  1061
      right = _thread[u];
kpeter@593
  1062
      if (_thread[v_in] == u_out) {
kpeter@593
  1063
        for (last = u; _depth[last] > _depth[u_out]; last = _thread[last]) ;
kpeter@593
  1064
        if (last == u_out) last = _thread[last];
kpeter@593
  1065
      }
kpeter@593
  1066
      else last = _thread[v_in];
kpeter@593
  1067
kpeter@593
  1068
      // Update stem nodes
kpeter@593
  1069
      _thread[v_in] = stem = u_in;
kpeter@593
  1070
      par_stem = v_in;
kpeter@593
  1071
      while (stem != u_out) {
kpeter@593
  1072
        _thread[u] = new_stem = _parent[stem];
kpeter@593
  1073
kpeter@593
  1074
        // Find the node just before the stem node (u) according to
kpeter@593
  1075
        // the original thread index
kpeter@593
  1076
        for (u = new_stem; _thread[u] != stem; u = _thread[u]) ;
kpeter@593
  1077
        _thread[u] = right;
kpeter@593
  1078
kpeter@593
  1079
        // Change the parent node of stem and shift stem and par_stem nodes
kpeter@593
  1080
        _parent[stem] = par_stem;
kpeter@593
  1081
        par_stem = stem;
kpeter@593
  1082
        stem = new_stem;
kpeter@593
  1083
kpeter@593
  1084
        // Find the last successor of stem (u) and the node after it (right)
kpeter@593
  1085
        // according to the thread index
kpeter@593
  1086
        for (u = stem; _depth[_thread[u]] > _depth[stem]; u = _thread[u]) ;
kpeter@593
  1087
        right = _thread[u];
kpeter@593
  1088
      }
kpeter@593
  1089
      _parent[u_out] = par_stem;
kpeter@593
  1090
      _thread[u] = last;
kpeter@593
  1091
kpeter@593
  1092
      if (join == v_out && par_first) {
kpeter@593
  1093
        if (first != v_in) _thread[first] = right;
kpeter@593
  1094
      } else {
kpeter@593
  1095
        for (u = v_out; _thread[u] != u_out; u = _thread[u]) ;
kpeter@593
  1096
        _thread[u] = right;
kpeter@593
  1097
      }
kpeter@593
  1098
    }
kpeter@593
  1099
kpeter@593
  1100
    // Update _pred and _forward vectors
kpeter@593
  1101
    void updatePredArc() {
kpeter@593
  1102
      int u = u_out, v;
kpeter@593
  1103
      while (u != u_in) {
kpeter@593
  1104
        v = _parent[u];
kpeter@593
  1105
        _pred[u] = _pred[v];
kpeter@593
  1106
        _forward[u] = !_forward[v];
kpeter@593
  1107
        u = v;
kpeter@593
  1108
      }
kpeter@593
  1109
      _pred[u_in] = _in_arc;
kpeter@593
  1110
      _forward[u_in] = (u_in == _source[_in_arc]);
kpeter@593
  1111
    }
kpeter@593
  1112
kpeter@593
  1113
    // Update _depth and _potential vectors
kpeter@593
  1114
    void updateDepthPotential() {
kpeter@593
  1115
      _depth[u_in] = _depth[v_in] + 1;
kpeter@593
  1116
      Cost sigma = _forward[u_in] ?
kpeter@593
  1117
        _pi[v_in] - _pi[u_in] - _cost[_pred[u_in]] :
kpeter@593
  1118
        _pi[v_in] - _pi[u_in] + _cost[_pred[u_in]];
kpeter@593
  1119
      _pi[u_in] += sigma;
kpeter@593
  1120
      for(int u = _thread[u_in]; _parent[u] != -1; u = _thread[u]) {
kpeter@593
  1121
        _depth[u] = _depth[_parent[u]] + 1;
kpeter@593
  1122
        if (_depth[u] <= _depth[u_in]) break;
kpeter@593
  1123
        _pi[u] += sigma;
kpeter@593
  1124
      }
kpeter@593
  1125
    }
kpeter@593
  1126
kpeter@593
  1127
    // Execute the algorithm
kpeter@593
  1128
    bool start(PivotRuleEnum pivot_rule) {
kpeter@593
  1129
      // Select the pivot rule implementation
kpeter@593
  1130
      switch (pivot_rule) {
kpeter@593
  1131
        case FIRST_ELIGIBLE_PIVOT:
kpeter@593
  1132
          return start<FirstEligiblePivotRule>();
kpeter@593
  1133
        case BEST_ELIGIBLE_PIVOT:
kpeter@593
  1134
          return start<BestEligiblePivotRule>();
kpeter@593
  1135
        case BLOCK_SEARCH_PIVOT:
kpeter@593
  1136
          return start<BlockSearchPivotRule>();
kpeter@593
  1137
        case CANDIDATE_LIST_PIVOT:
kpeter@593
  1138
          return start<CandidateListPivotRule>();
kpeter@593
  1139
        case ALTERING_LIST_PIVOT:
kpeter@593
  1140
          return start<AlteringListPivotRule>();
kpeter@593
  1141
      }
kpeter@593
  1142
      return false;
kpeter@593
  1143
    }
kpeter@593
  1144
kpeter@593
  1145
    template<class PivotRuleImplementation>
kpeter@593
  1146
    bool start() {
kpeter@593
  1147
      PivotRuleImplementation pivot(*this);
kpeter@593
  1148
kpeter@593
  1149
      // Execute the network simplex algorithm
kpeter@593
  1150
      while (pivot.findEnteringArc()) {
kpeter@593
  1151
        findJoinNode();
kpeter@593
  1152
        bool change = findLeavingArc();
kpeter@593
  1153
        changeFlow(change);
kpeter@593
  1154
        if (change) {
kpeter@593
  1155
          updateThreadParent();
kpeter@593
  1156
          updatePredArc();
kpeter@593
  1157
          updateDepthPotential();
kpeter@593
  1158
        }
kpeter@593
  1159
      }
kpeter@593
  1160
kpeter@593
  1161
      // Check if the flow amount equals zero on all the artificial arcs
kpeter@593
  1162
      for (int e = _arc_num; e != _arc_num + _node_num; ++e) {
kpeter@593
  1163
        if (_flow[e] > 0) return false;
kpeter@593
  1164
      }
kpeter@593
  1165
kpeter@593
  1166
      // Copy flow values to _flow_result
kpeter@593
  1167
      if (_orig_lower) {
kpeter@593
  1168
        for (int i = 0; i != _arc_num; ++i) {
kpeter@593
  1169
          Arc e = _arc[i];
kpeter@593
  1170
          (*_flow_result)[e] = (*_orig_lower)[e] + _flow[i];
kpeter@593
  1171
        }
kpeter@593
  1172
      } else {
kpeter@593
  1173
        for (int i = 0; i != _arc_num; ++i) {
kpeter@593
  1174
          (*_flow_result)[_arc[i]] = _flow[i];
kpeter@593
  1175
        }
kpeter@593
  1176
      }
kpeter@593
  1177
      // Copy potential values to _potential_result
kpeter@593
  1178
      for (int i = 0; i != _node_num; ++i) {
kpeter@593
  1179
        (*_potential_result)[_node[i]] = _pi[i];
kpeter@593
  1180
      }
kpeter@593
  1181
kpeter@593
  1182
      return true;
kpeter@593
  1183
    }
kpeter@593
  1184
kpeter@593
  1185
  }; //class NetworkSimplex
kpeter@593
  1186
kpeter@593
  1187
  ///@}
kpeter@593
  1188
kpeter@593
  1189
} //namespace lemon
kpeter@593
  1190
kpeter@593
  1191
#endif //LEMON_NETWORK_SIMPLEX_H