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