lemon/network_simplex.h
author Balazs Dezso <deba@inf.elte.hu>
Thu, 24 Jun 2010 09:27:53 +0200
changeset 982 bb70ad62c95f
parent 710 8b0df68370a4
child 978 cbf32bf95954
child 1081 f1398882a928
permissions -rw-r--r--
Fix critical bug in preflow (#372)

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