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