lemon/network_simplex.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 24 Mar 2009 00:18:25 +0100
changeset 604 8c3112a66878
parent 603 425cc8328c0e
child 605 5232721b3f14
permissions -rw-r--r--
Use XTI implementation instead of ATI in NetworkSimplex (#234)

XTI (eXtended Threaded Index) is an imporved version of the widely
known ATI (Augmented Threaded Index) method for storing and updating
the spanning tree structure in Network Simplex algorithms.

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