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