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