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