lemon/network_simplex.h
author kpeter
Thu, 13 Nov 2008 10:54:42 +0000
changeset 2628 74520139e388
parent 2623 90defb96ee61
child 2629 84354c78b068
permissions -rw-r--r--
Improve tree update procedure in NetworkSimplex
The new method updates a smaller subtree (fixing a bug) and shifting the
potentials with a costant value.
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
    {
deba@2440
   614
      // Checking 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@2575
   620
      // Copying _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@2575
   624
        .edgeMap(_cost, cost)
kpeter@2575
   625
        .nodeRef(_node_ref)
kpeter@2575
   626
        .edgeRef(_edge_ref)
kpeter@2556
   627
        .run();
deba@2440
   628
kpeter@2556
   629
      // Removing non-zero lower bounds
kpeter@2575
   630
      for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e) {
kpeter@2575
   631
        _capacity[_edge_ref[e]] = capacity[e] - lower[e];
deba@2440
   632
      }
kpeter@2575
   633
      for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n) {
kpeter@2575
   634
        Supply s = supply[n];
kpeter@2575
   635
        for (typename Graph::InEdgeIt e(_graph_ref, n); e != INVALID; ++e)
kpeter@2575
   636
          s += lower[e];
kpeter@2575
   637
        for (typename Graph::OutEdgeIt e(_graph_ref, n); e != INVALID; ++e)
kpeter@2575
   638
          s -= lower[e];
kpeter@2575
   639
        _supply[_node_ref[n]] = s;
deba@2440
   640
      }
deba@2440
   641
    }
deba@2440
   642
kpeter@2581
   643
    /// \brief General constructor (without lower bounds).
deba@2440
   644
    ///
kpeter@2581
   645
    /// General constructor (without lower bounds).
deba@2440
   646
    ///
kpeter@2575
   647
    /// \param graph The directed graph the algorithm runs on.
kpeter@2575
   648
    /// \param capacity The capacities (upper bounds) of the edges.
kpeter@2575
   649
    /// \param cost The cost (length) values of the edges.
kpeter@2575
   650
    /// \param supply The supply values of the nodes (signed).
kpeter@2575
   651
    NetworkSimplex( const Graph &graph,
kpeter@2575
   652
                    const CapacityMap &capacity,
kpeter@2575
   653
                    const CostMap &cost,
kpeter@2575
   654
                    const SupplyMap &supply ) :
kpeter@2575
   655
      _graph(), _graph_ref(graph), _lower(NULL), _capacity(_graph),
kpeter@2575
   656
      _cost(_graph), _supply(_graph), _flow(_graph),
kpeter@2575
   657
      _potential(_graph), _depth(_graph), _parent(_graph),
kpeter@2575
   658
      _pred_edge(_graph), _thread(_graph), _forward(_graph),
kpeter@2575
   659
      _state(_graph), _red_cost(_graph, _cost, _potential),
kpeter@2623
   660
      _flow_result(NULL), _potential_result(NULL),
kpeter@2581
   661
      _local_flow(false), _local_potential(false),
kpeter@2575
   662
      _node_ref(graph), _edge_ref(graph)
deba@2440
   663
    {
deba@2440
   664
      // Checking the sum of supply values
deba@2440
   665
      Supply sum = 0;
kpeter@2575
   666
      for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n)
kpeter@2575
   667
        sum += supply[n];
kpeter@2575
   668
      if (!(_valid_supply = sum == 0)) return;
deba@2440
   669
kpeter@2575
   670
      // Copying _graph_ref to graph
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@2575
   700
      _cost(_graph), _supply(_graph), _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@2575
   708
      // Copying _graph_ref to graph
kpeter@2575
   709
      copyGraph(_graph, _graph_ref)
kpeter@2575
   710
        .edgeMap(_cost, cost)
kpeter@2575
   711
        .nodeRef(_node_ref)
kpeter@2575
   712
        .edgeRef(_edge_ref)
kpeter@2556
   713
        .run();
deba@2440
   714
kpeter@2556
   715
      // Removing non-zero lower bounds
kpeter@2575
   716
      for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e) {
kpeter@2575
   717
        _capacity[_edge_ref[e]] = capacity[e] - lower[e];
deba@2440
   718
      }
kpeter@2575
   719
      for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n) {
kpeter@2575
   720
        Supply sum = 0;
kpeter@2575
   721
        if (n == s) sum =  flow_value;
kpeter@2575
   722
        if (n == t) sum = -flow_value;
kpeter@2575
   723
        for (typename Graph::InEdgeIt e(_graph_ref, n); e != INVALID; ++e)
kpeter@2575
   724
          sum += lower[e];
kpeter@2575
   725
        for (typename Graph::OutEdgeIt e(_graph_ref, n); e != INVALID; ++e)
kpeter@2575
   726
          sum -= lower[e];
kpeter@2575
   727
        _supply[_node_ref[n]] = sum;
deba@2440
   728
      }
kpeter@2575
   729
      _valid_supply = true;
deba@2440
   730
    }
deba@2440
   731
kpeter@2581
   732
    /// \brief Simple constructor (without lower bounds).
deba@2440
   733
    ///
kpeter@2581
   734
    /// Simple constructor (without lower bounds).
deba@2440
   735
    ///
kpeter@2575
   736
    /// \param graph The directed graph the algorithm runs on.
kpeter@2575
   737
    /// \param capacity The capacities (upper bounds) of the edges.
kpeter@2575
   738
    /// \param cost The cost (length) values of the edges.
kpeter@2575
   739
    /// \param s The source node.
kpeter@2575
   740
    /// \param t The target node.
kpeter@2575
   741
    /// \param flow_value The required amount of flow from node \c s
kpeter@2575
   742
    /// to node \c t (i.e. the supply of \c s and the demand of \c t).
kpeter@2575
   743
    NetworkSimplex( const Graph &graph,
kpeter@2575
   744
                    const CapacityMap &capacity,
kpeter@2575
   745
                    const CostMap &cost,
kpeter@2575
   746
                    typename Graph::Node s,
kpeter@2575
   747
                    typename Graph::Node t,
kpeter@2575
   748
                    typename SupplyMap::Value flow_value ) :
kpeter@2575
   749
      _graph(), _graph_ref(graph), _lower(NULL), _capacity(_graph),
kpeter@2575
   750
      _cost(_graph), _supply(_graph, 0), _flow(_graph),
kpeter@2575
   751
      _potential(_graph), _depth(_graph), _parent(_graph),
kpeter@2575
   752
      _pred_edge(_graph), _thread(_graph), _forward(_graph),
kpeter@2575
   753
      _state(_graph), _red_cost(_graph, _cost, _potential),
kpeter@2623
   754
      _flow_result(NULL), _potential_result(NULL),
kpeter@2581
   755
      _local_flow(false), _local_potential(false),
kpeter@2575
   756
      _node_ref(graph), _edge_ref(graph)
deba@2440
   757
    {
kpeter@2575
   758
      // Copying _graph_ref to graph
kpeter@2575
   759
      copyGraph(_graph, _graph_ref)
kpeter@2575
   760
        .edgeMap(_capacity, capacity)
kpeter@2575
   761
        .edgeMap(_cost, cost)
kpeter@2575
   762
        .nodeRef(_node_ref)
kpeter@2575
   763
        .edgeRef(_edge_ref)
kpeter@2556
   764
        .run();
kpeter@2575
   765
      _supply[_node_ref[s]] =  flow_value;
kpeter@2575
   766
      _supply[_node_ref[t]] = -flow_value;
kpeter@2575
   767
      _valid_supply = true;
deba@2440
   768
    }
deba@2440
   769
kpeter@2581
   770
    /// Destructor.
kpeter@2581
   771
    ~NetworkSimplex() {
kpeter@2581
   772
      if (_local_flow) delete _flow_result;
kpeter@2581
   773
      if (_local_potential) delete _potential_result;
kpeter@2581
   774
    }
kpeter@2581
   775
kpeter@2619
   776
    /// \brief Set the flow map.
kpeter@2581
   777
    ///
kpeter@2619
   778
    /// Set the flow map.
kpeter@2581
   779
    ///
kpeter@2581
   780
    /// \return \c (*this)
kpeter@2581
   781
    NetworkSimplex& flowMap(FlowMap &map) {
kpeter@2581
   782
      if (_local_flow) {
kpeter@2581
   783
        delete _flow_result;
kpeter@2581
   784
        _local_flow = false;
kpeter@2581
   785
      }
kpeter@2581
   786
      _flow_result = &map;
kpeter@2581
   787
      return *this;
kpeter@2581
   788
    }
kpeter@2581
   789
kpeter@2619
   790
    /// \brief Set the potential map.
kpeter@2581
   791
    ///
kpeter@2619
   792
    /// Set the potential map.
kpeter@2581
   793
    ///
kpeter@2581
   794
    /// \return \c (*this)
kpeter@2581
   795
    NetworkSimplex& potentialMap(PotentialMap &map) {
kpeter@2581
   796
      if (_local_potential) {
kpeter@2581
   797
        delete _potential_result;
kpeter@2581
   798
        _local_potential = false;
kpeter@2581
   799
      }
kpeter@2581
   800
      _potential_result = &map;
kpeter@2581
   801
      return *this;
kpeter@2581
   802
    }
kpeter@2581
   803
kpeter@2581
   804
    /// \name Execution control
kpeter@2581
   805
kpeter@2581
   806
    /// @{
kpeter@2581
   807
kpeter@2556
   808
    /// \brief Runs the algorithm.
kpeter@2556
   809
    ///
kpeter@2556
   810
    /// Runs the algorithm.
kpeter@2556
   811
    ///
kpeter@2575
   812
    /// \param pivot_rule The pivot rule that is used during the
kpeter@2575
   813
    /// algorithm.
kpeter@2575
   814
    ///
kpeter@2575
   815
    /// The available pivot rules:
kpeter@2575
   816
    ///
kpeter@2575
   817
    /// - FIRST_ELIGIBLE_PIVOT The next eligible edge is selected in
kpeter@2575
   818
    /// a wraparound fashion in every iteration
kpeter@2575
   819
    /// (\ref FirstEligiblePivotRule).
kpeter@2575
   820
    ///
kpeter@2575
   821
    /// - BEST_ELIGIBLE_PIVOT The best eligible edge is selected in
kpeter@2575
   822
    /// every iteration (\ref BestEligiblePivotRule).
kpeter@2575
   823
    ///
kpeter@2575
   824
    /// - BLOCK_SEARCH_PIVOT A specified number of edges are examined in
kpeter@2575
   825
    /// every iteration in a wraparound fashion and the best eligible
kpeter@2575
   826
    /// edge is selected from this block (\ref BlockSearchPivotRule).
kpeter@2575
   827
    ///
kpeter@2619
   828
    /// - CANDIDATE_LIST_PIVOT In a major iteration a candidate list is
kpeter@2619
   829
    /// built from eligible edges in a wraparound fashion and in the
kpeter@2619
   830
    /// following minor iterations the best eligible edge is selected
kpeter@2619
   831
    /// from this list (\ref CandidateListPivotRule).
kpeter@2575
   832
    ///
kpeter@2619
   833
    /// - ALTERING_LIST_PIVOT It is a modified version of the
kpeter@2619
   834
    /// "Candidate List" pivot rule. It keeps only the several best
kpeter@2619
   835
    /// eligible edges from the former candidate list and extends this
kpeter@2619
   836
    /// list in every iteration (\ref AlteringListPivotRule).
kpeter@2575
   837
    ///
kpeter@2619
   838
    /// According to our comprehensive benchmark tests the "Block Search"
kpeter@2619
   839
    /// pivot rule proved to be by far the fastest and the most robust
kpeter@2619
   840
    /// on various test inputs. Thus it is the default option.
kpeter@2575
   841
    ///
kpeter@2556
   842
    /// \return \c true if a feasible flow can be found.
kpeter@2619
   843
    bool run(PivotRuleEnum pivot_rule = BLOCK_SEARCH_PIVOT) {
kpeter@2575
   844
      return init() && start(pivot_rule);
kpeter@2556
   845
    }
kpeter@2556
   846
kpeter@2581
   847
    /// @}
kpeter@2581
   848
kpeter@2581
   849
    /// \name Query Functions
kpeter@2619
   850
    /// The results of the algorithm can be obtained using these
kpeter@2619
   851
    /// functions.\n
kpeter@2619
   852
    /// \ref lemon::NetworkSimplex::run() "run()" must be called before
kpeter@2619
   853
    /// using them.
kpeter@2581
   854
kpeter@2581
   855
    /// @{
kpeter@2581
   856
kpeter@2619
   857
    /// \brief Return a const reference to the edge map storing the
kpeter@2575
   858
    /// found flow.
deba@2440
   859
    ///
kpeter@2619
   860
    /// Return a const reference to the edge map storing the found flow.
deba@2440
   861
    ///
deba@2440
   862
    /// \pre \ref run() must be called before using this function.
deba@2440
   863
    const FlowMap& flowMap() const {
kpeter@2581
   864
      return *_flow_result;
deba@2440
   865
    }
deba@2440
   866
kpeter@2619
   867
    /// \brief Return a const reference to the node map storing the
kpeter@2575
   868
    /// found potentials (the dual solution).
deba@2440
   869
    ///
kpeter@2619
   870
    /// Return a const reference to the node map storing the found
kpeter@2575
   871
    /// potentials (the dual solution).
deba@2440
   872
    ///
deba@2440
   873
    /// \pre \ref run() must be called before using this function.
deba@2440
   874
    const PotentialMap& potentialMap() const {
kpeter@2581
   875
      return *_potential_result;
kpeter@2581
   876
    }
kpeter@2581
   877
kpeter@2619
   878
    /// \brief Return the flow on the given edge.
kpeter@2581
   879
    ///
kpeter@2619
   880
    /// Return the flow on the given edge.
kpeter@2581
   881
    ///
kpeter@2581
   882
    /// \pre \ref run() must be called before using this function.
kpeter@2581
   883
    Capacity flow(const typename Graph::Edge& edge) const {
kpeter@2581
   884
      return (*_flow_result)[edge];
kpeter@2581
   885
    }
kpeter@2581
   886
kpeter@2619
   887
    /// \brief Return the potential of the given node.
kpeter@2581
   888
    ///
kpeter@2619
   889
    /// Return the potential of the given node.
kpeter@2581
   890
    ///
kpeter@2581
   891
    /// \pre \ref run() must be called before using this function.
kpeter@2581
   892
    Cost potential(const typename Graph::Node& node) const {
kpeter@2581
   893
      return (*_potential_result)[node];
deba@2440
   894
    }
deba@2440
   895
kpeter@2619
   896
    /// \brief Return the total cost of the found flow.
deba@2440
   897
    ///
kpeter@2619
   898
    /// Return the total cost of the found flow. The complexity of the
deba@2440
   899
    /// function is \f$ O(e) \f$.
deba@2440
   900
    ///
deba@2440
   901
    /// \pre \ref run() must be called before using this function.
deba@2440
   902
    Cost totalCost() const {
deba@2440
   903
      Cost c = 0;
kpeter@2575
   904
      for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e)
kpeter@2581
   905
        c += (*_flow_result)[e] * _cost[_edge_ref[e]];
deba@2440
   906
      return c;
deba@2440
   907
    }
deba@2440
   908
kpeter@2581
   909
    /// @}
kpeter@2581
   910
kpeter@2575
   911
  private:
deba@2440
   912
kpeter@2619
   913
    /// \brief Extend the underlying graph and initialize all the
deba@2440
   914
    /// node and edge maps.
deba@2440
   915
    bool init() {
kpeter@2575
   916
      if (!_valid_supply) return false;
deba@2440
   917
kpeter@2581
   918
      // Initializing result maps
kpeter@2581
   919
      if (!_flow_result) {
kpeter@2581
   920
        _flow_result = new FlowMap(_graph_ref);
kpeter@2581
   921
        _local_flow = true;
kpeter@2581
   922
      }
kpeter@2581
   923
      if (!_potential_result) {
kpeter@2581
   924
        _potential_result = new PotentialMap(_graph_ref);
kpeter@2581
   925
        _local_potential = true;
kpeter@2581
   926
      }
kpeter@2581
   927
kpeter@2619
   928
      // Initializing the edge vector and the edge maps
kpeter@2619
   929
      _edges.reserve(countEdges(_graph));
kpeter@2575
   930
      for (EdgeIt e(_graph); e != INVALID; ++e) {
kpeter@2619
   931
        _edges.push_back(e);
kpeter@2575
   932
        _flow[e] = 0;
kpeter@2575
   933
        _state[e] = STATE_LOWER;
deba@2440
   934
      }
deba@2440
   935
deba@2440
   936
      // Adding an artificial root node to the graph
kpeter@2575
   937
      _root = _graph.addNode();
kpeter@2575
   938
      _parent[_root] = INVALID;
kpeter@2575
   939
      _pred_edge[_root] = INVALID;
kpeter@2575
   940
      _depth[_root] = 0;
kpeter@2575
   941
      _supply[_root] = 0;
kpeter@2575
   942
      _potential[_root] = 0;
deba@2440
   943
deba@2440
   944
      // Adding artificial edges to the graph and initializing the node
deba@2440
   945
      // maps of the spanning tree data structure
kpeter@2575
   946
      Node last = _root;
deba@2440
   947
      Edge e;
deba@2440
   948
      Cost max_cost = std::numeric_limits<Cost>::max() / 4;
kpeter@2575
   949
      for (NodeIt u(_graph); u != INVALID; ++u) {
kpeter@2575
   950
        if (u == _root) continue;
kpeter@2575
   951
        _thread[last] = u;
kpeter@2556
   952
        last = u;
kpeter@2575
   953
        _parent[u] = _root;
kpeter@2575
   954
        _depth[u] = 1;
kpeter@2575
   955
        if (_supply[u] >= 0) {
kpeter@2575
   956
          e = _graph.addEdge(u, _root);
kpeter@2575
   957
          _flow[e] = _supply[u];
kpeter@2575
   958
          _forward[u] = true;
kpeter@2575
   959
          _potential[u] = -max_cost;
kpeter@2556
   960
        } else {
kpeter@2575
   961
          e = _graph.addEdge(_root, u);
kpeter@2575
   962
          _flow[e] = -_supply[u];
kpeter@2575
   963
          _forward[u] = false;
kpeter@2575
   964
          _potential[u] = max_cost;
kpeter@2556
   965
        }
kpeter@2575
   966
        _cost[e] = max_cost;
kpeter@2575
   967
        _capacity[e] = std::numeric_limits<Capacity>::max();
kpeter@2575
   968
        _state[e] = STATE_TREE;
kpeter@2575
   969
        _pred_edge[u] = e;
deba@2440
   970
      }
kpeter@2575
   971
      _thread[last] = _root;
deba@2440
   972
kpeter@2575
   973
      return true;
deba@2440
   974
    }
deba@2440
   975
kpeter@2619
   976
    /// Find the join node.
kpeter@2619
   977
    inline Node findJoinNode() {
kpeter@2575
   978
      Node u = _graph.source(_in_edge);
kpeter@2575
   979
      Node v = _graph.target(_in_edge);
kpeter@2575
   980
      while (u != v) {
kpeter@2575
   981
        if (_depth[u] == _depth[v]) {
kpeter@2575
   982
          u = _parent[u];
kpeter@2575
   983
          v = _parent[v];
kpeter@2556
   984
        }
kpeter@2575
   985
        else if (_depth[u] > _depth[v]) u = _parent[u];
kpeter@2575
   986
        else v = _parent[v];
deba@2440
   987
      }
deba@2440
   988
      return u;
deba@2440
   989
    }
deba@2440
   990
kpeter@2619
   991
    /// \brief Find the leaving edge of the cycle.
kpeter@2619
   992
    /// \return \c true if the leaving edge is not the same as the
kpeter@2619
   993
    /// entering edge.
kpeter@2619
   994
    inline bool findLeavingEdge() {
deba@2440
   995
      // Initializing first and second nodes according to the direction
deba@2440
   996
      // of the cycle
kpeter@2575
   997
      if (_state[_in_edge] == STATE_LOWER) {
kpeter@2575
   998
        first  = _graph.source(_in_edge);
kpeter@2575
   999
        second = _graph.target(_in_edge);
deba@2440
  1000
      } else {
kpeter@2575
  1001
        first  = _graph.target(_in_edge);
kpeter@2575
  1002
        second = _graph.source(_in_edge);
deba@2440
  1003
      }
kpeter@2575
  1004
      delta = _capacity[_in_edge];
deba@2440
  1005
      bool result = false;
deba@2440
  1006
      Capacity d;
deba@2440
  1007
      Edge e;
deba@2440
  1008
deba@2440
  1009
      // Searching the cycle along the path form the first node to the
deba@2440
  1010
      // root node
kpeter@2575
  1011
      for (Node u = first; u != join; u = _parent[u]) {
kpeter@2575
  1012
        e = _pred_edge[u];
kpeter@2575
  1013
        d = _forward[u] ? _flow[e] : _capacity[e] - _flow[e];
kpeter@2556
  1014
        if (d < delta) {
kpeter@2556
  1015
          delta = d;
kpeter@2556
  1016
          u_out = u;
kpeter@2556
  1017
          u_in = first;
kpeter@2556
  1018
          v_in = second;
kpeter@2556
  1019
          result = true;
kpeter@2556
  1020
        }
deba@2440
  1021
      }
deba@2440
  1022
      // Searching the cycle along the path form the second node to the
deba@2440
  1023
      // root node
kpeter@2575
  1024
      for (Node u = second; u != join; u = _parent[u]) {
kpeter@2575
  1025
        e = _pred_edge[u];
kpeter@2575
  1026
        d = _forward[u] ? _capacity[e] - _flow[e] : _flow[e];
kpeter@2556
  1027
        if (d <= delta) {
kpeter@2556
  1028
          delta = d;
kpeter@2556
  1029
          u_out = u;
kpeter@2556
  1030
          u_in = second;
kpeter@2556
  1031
          v_in = first;
kpeter@2556
  1032
          result = true;
kpeter@2556
  1033
        }
deba@2440
  1034
      }
deba@2440
  1035
      return result;
deba@2440
  1036
    }
deba@2440
  1037
kpeter@2619
  1038
    /// Change \c flow and \c state edge maps.
kpeter@2619
  1039
    inline void changeFlows(bool change) {
deba@2440
  1040
      // Augmenting along the cycle
deba@2440
  1041
      if (delta > 0) {
kpeter@2575
  1042
        Capacity val = _state[_in_edge] * delta;
kpeter@2575
  1043
        _flow[_in_edge] += val;
kpeter@2575
  1044
        for (Node u = _graph.source(_in_edge); u != join; u = _parent[u]) {
kpeter@2575
  1045
          _flow[_pred_edge[u]] += _forward[u] ? -val : val;
kpeter@2556
  1046
        }
kpeter@2575
  1047
        for (Node u = _graph.target(_in_edge); u != join; u = _parent[u]) {
kpeter@2575
  1048
          _flow[_pred_edge[u]] += _forward[u] ? val : -val;
kpeter@2556
  1049
        }
deba@2440
  1050
      }
deba@2440
  1051
      // Updating the state of the entering and leaving edges
deba@2440
  1052
      if (change) {
kpeter@2575
  1053
        _state[_in_edge] = STATE_TREE;
kpeter@2575
  1054
        _state[_pred_edge[u_out]] =
kpeter@2575
  1055
          (_flow[_pred_edge[u_out]] == 0) ? STATE_LOWER : STATE_UPPER;
deba@2440
  1056
      } else {
kpeter@2575
  1057
        _state[_in_edge] = -_state[_in_edge];
deba@2440
  1058
      }
deba@2440
  1059
    }
deba@2440
  1060
kpeter@2619
  1061
    /// Update \c thread and \c parent node maps.
kpeter@2619
  1062
    inline void updateThreadParent() {
deba@2440
  1063
      Node u;
kpeter@2575
  1064
      v_out = _parent[u_out];
deba@2440
  1065
deba@2440
  1066
      // Handling the case when join and v_out coincide
deba@2440
  1067
      bool par_first = false;
deba@2440
  1068
      if (join == v_out) {
kpeter@2575
  1069
        for (u = join; u != u_in && u != v_in; u = _thread[u]) ;
kpeter@2556
  1070
        if (u == v_in) {
kpeter@2556
  1071
          par_first = true;
kpeter@2575
  1072
          while (_thread[u] != u_out) u = _thread[u];
kpeter@2556
  1073
          first = u;
kpeter@2556
  1074
        }
deba@2440
  1075
      }
deba@2440
  1076
deba@2440
  1077
      // Finding the last successor of u_in (u) and the node after it
deba@2440
  1078
      // (right) according to the thread index
kpeter@2575
  1079
      for (u = u_in; _depth[_thread[u]] > _depth[u_in]; u = _thread[u]) ;
kpeter@2575
  1080
      right = _thread[u];
kpeter@2575
  1081
      if (_thread[v_in] == u_out) {
kpeter@2575
  1082
        for (last = u; _depth[last] > _depth[u_out]; last = _thread[last]) ;
kpeter@2575
  1083
        if (last == u_out) last = _thread[last];
deba@2440
  1084
      }
kpeter@2575
  1085
      else last = _thread[v_in];
deba@2440
  1086
deba@2440
  1087
      // Updating stem nodes
kpeter@2575
  1088
      _thread[v_in] = stem = u_in;
deba@2440
  1089
      par_stem = v_in;
deba@2440
  1090
      while (stem != u_out) {
kpeter@2575
  1091
        _thread[u] = new_stem = _parent[stem];
deba@2440
  1092
kpeter@2556
  1093
        // Finding the node just before the stem node (u) according to
kpeter@2556
  1094
        // the original thread index
kpeter@2575
  1095
        for (u = new_stem; _thread[u] != stem; u = _thread[u]) ;
kpeter@2575
  1096
        _thread[u] = right;
deba@2440
  1097
kpeter@2556
  1098
        // Changing the parent node of stem and shifting stem and
kpeter@2556
  1099
        // par_stem nodes
kpeter@2575
  1100
        _parent[stem] = par_stem;
kpeter@2556
  1101
        par_stem = stem;
kpeter@2556
  1102
        stem = new_stem;
deba@2440
  1103
kpeter@2556
  1104
        // Finding the last successor of stem (u) and the node after it
kpeter@2556
  1105
        // (right) according to the thread index
kpeter@2575
  1106
        for (u = stem; _depth[_thread[u]] > _depth[stem]; u = _thread[u]) ;
kpeter@2575
  1107
        right = _thread[u];
deba@2440
  1108
      }
kpeter@2575
  1109
      _parent[u_out] = par_stem;
kpeter@2575
  1110
      _thread[u] = last;
deba@2440
  1111
deba@2440
  1112
      if (join == v_out && par_first) {
kpeter@2575
  1113
        if (first != v_in) _thread[first] = right;
deba@2440
  1114
      } else {
kpeter@2575
  1115
        for (u = v_out; _thread[u] != u_out; u = _thread[u]) ;
kpeter@2575
  1116
        _thread[u] = right;
deba@2440
  1117
      }
deba@2440
  1118
    }
deba@2440
  1119
kpeter@2619
  1120
    /// Update \c pred_edge and \c forward node maps.
kpeter@2619
  1121
    inline void updatePredEdge() {
deba@2440
  1122
      Node u = u_out, v;
deba@2440
  1123
      while (u != u_in) {
kpeter@2575
  1124
        v = _parent[u];
kpeter@2575
  1125
        _pred_edge[u] = _pred_edge[v];
kpeter@2575
  1126
        _forward[u] = !_forward[v];
kpeter@2556
  1127
        u = v;
deba@2440
  1128
      }
kpeter@2575
  1129
      _pred_edge[u_in] = _in_edge;
kpeter@2575
  1130
      _forward[u_in] = (u_in == _graph.source(_in_edge));
deba@2440
  1131
    }
deba@2440
  1132
kpeter@2619
  1133
    /// Update \c depth and \c potential node maps.
kpeter@2619
  1134
    inline void updateDepthPotential() {
kpeter@2575
  1135
      _depth[u_in] = _depth[v_in] + 1;
kpeter@2628
  1136
      Cost sigma = _forward[u_in] ?
kpeter@2628
  1137
        _potential[v_in] - _potential[u_in] - _cost[_pred_edge[u_in]] :
kpeter@2628
  1138
        _potential[v_in] - _potential[u_in] + _cost[_pred_edge[u_in]];
kpeter@2628
  1139
      _potential[u_in] += sigma;
kpeter@2628
  1140
      for(Node u = _thread[u_in]; _parent[u] != INVALID; u = _thread[u]) {
kpeter@2628
  1141
        _depth[u] = _depth[_parent[u]] + 1;
kpeter@2628
  1142
        if (_depth[u] <= _depth[u_in]) break;
kpeter@2628
  1143
        _potential[u] += sigma;
deba@2440
  1144
      }
deba@2440
  1145
    }
deba@2440
  1146
kpeter@2619
  1147
    /// Execute the algorithm.
kpeter@2575
  1148
    bool start(PivotRuleEnum pivot_rule) {
kpeter@2619
  1149
      // Selecting the pivot rule implementation
kpeter@2575
  1150
      switch (pivot_rule) {
kpeter@2575
  1151
        case FIRST_ELIGIBLE_PIVOT:
kpeter@2575
  1152
          return start<FirstEligiblePivotRule>();
kpeter@2575
  1153
        case BEST_ELIGIBLE_PIVOT:
kpeter@2575
  1154
          return start<BestEligiblePivotRule>();
kpeter@2575
  1155
        case BLOCK_SEARCH_PIVOT:
kpeter@2575
  1156
          return start<BlockSearchPivotRule>();
kpeter@2575
  1157
        case CANDIDATE_LIST_PIVOT:
kpeter@2575
  1158
          return start<CandidateListPivotRule>();
kpeter@2619
  1159
        case ALTERING_LIST_PIVOT:
kpeter@2619
  1160
          return start<AlteringListPivotRule>();
kpeter@2575
  1161
      }
kpeter@2575
  1162
      return false;
kpeter@2575
  1163
    }
kpeter@2575
  1164
kpeter@2575
  1165
    template<class PivotRuleImplementation>
deba@2440
  1166
    bool start() {
kpeter@2619
  1167
      PivotRuleImplementation pivot(*this, _edges);
kpeter@2575
  1168
kpeter@2575
  1169
      // Executing the network simplex algorithm
kpeter@2575
  1170
      while (pivot.findEnteringEdge()) {
kpeter@2556
  1171
        join = findJoinNode();
kpeter@2556
  1172
        bool change = findLeavingEdge();
kpeter@2556
  1173
        changeFlows(change);
kpeter@2556
  1174
        if (change) {
kpeter@2556
  1175
          updateThreadParent();
kpeter@2556
  1176
          updatePredEdge();
kpeter@2556
  1177
          updateDepthPotential();
kpeter@2556
  1178
        }
deba@2440
  1179
      }
deba@2440
  1180
kpeter@2575
  1181
      // Checking if the flow amount equals zero on all the artificial
kpeter@2575
  1182
      // edges
kpeter@2575
  1183
      for (InEdgeIt e(_graph, _root); e != INVALID; ++e)
kpeter@2575
  1184
        if (_flow[e] > 0) return false;
kpeter@2575
  1185
      for (OutEdgeIt e(_graph, _root); e != INVALID; ++e)
kpeter@2575
  1186
        if (_flow[e] > 0) return false;
deba@2440
  1187
kpeter@2575
  1188
      // Copying flow values to _flow_result
kpeter@2575
  1189
      if (_lower) {
kpeter@2575
  1190
        for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e)
kpeter@2581
  1191
          (*_flow_result)[e] = (*_lower)[e] + _flow[_edge_ref[e]];
deba@2440
  1192
      } else {
kpeter@2575
  1193
        for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e)
kpeter@2581
  1194
          (*_flow_result)[e] = _flow[_edge_ref[e]];
deba@2440
  1195
      }
kpeter@2575
  1196
      // Copying potential values to _potential_result
kpeter@2575
  1197
      for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n)
kpeter@2581
  1198
        (*_potential_result)[n] = _potential[_node_ref[n]];
deba@2440
  1199
deba@2440
  1200
      return true;
deba@2440
  1201
    }
deba@2440
  1202
deba@2440
  1203
  }; //class NetworkSimplex
deba@2440
  1204
deba@2440
  1205
  ///@}
deba@2440
  1206
deba@2440
  1207
} //namespace lemon
deba@2440
  1208
deba@2440
  1209
#endif //LEMON_NETWORK_SIMPLEX_H