lemon/network_simplex.h
author Peter Kovacs <kpeter@inf.elte.hu>
Thu, 12 Nov 2009 23:26:13 +0100
changeset 806 fa6f37d7a25b
parent 755 134852d7fb0a
parent 786 e20173729589
child 811 fe80a8145653
permissions -rw-r--r--
Entirely rework CapacityScaling (#180)

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