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