lemon/network_simplex.h
author Peter Kovacs <kpeter@inf.elte.hu>
Fri, 17 Apr 2009 18:04:36 +0200
changeset 601 e6927fe719e6
parent 600 6ac5d9ae1d3d
child 604 0c8e5c688440
child 605 b1811c363299
permissions -rw-r--r--
Support >= and <= constraints in NetworkSimplex (#219, #234)

By default the same inequality constraints are supported as by
Circulation (the GEQ form), but the LEQ form can also be selected
using the problemType() function.

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