lemon/network_simplex.h
author deba
Wed, 27 Feb 2008 11:39:03 +0000
changeset 2580 fa71d9612c42
parent 2575 e866e288cba6
child 2581 054566ac0934
permissions -rw-r--r--
Bug fixes
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
deba@2440
    40
  /// \brief Implementation of the network simplex algorithm for
deba@2440
    41
  /// finding a minimum cost flow.
deba@2440
    42
  ///
kpeter@2556
    43
  /// \ref NetworkSimplex implements the network simplex algorithm for
kpeter@2556
    44
  /// 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@2575
    55
  /// - \c LowerMap::Value must be convertible to \c CapacityMap::Value.
kpeter@2575
    56
  /// - \c CapacityMap::Value and \c SupplyMap::Value must be
kpeter@2575
    57
  ///   convertible to each other.
kpeter@2575
    58
  /// - All value types must be convertible to \c CostMap::Value, which
kpeter@2575
    59
  ///   must be signed type.
kpeter@2575
    60
  ///
kpeter@2575
    61
  /// \note \ref NetworkSimplex provides six different pivot rule
kpeter@2575
    62
  /// implementations that significantly affect the efficiency of the
kpeter@2575
    63
  /// algorithm.
kpeter@2575
    64
  /// By default a combined pivot rule is used, which is the fastest
kpeter@2575
    65
  /// implementation according to our benchmark tests.
kpeter@2575
    66
  /// Another pivot rule can be selected using \ref run() function
kpeter@2575
    67
  /// with the proper parameter.
deba@2440
    68
  ///
deba@2440
    69
  /// \author Peter Kovacs
deba@2440
    70
kpeter@2533
    71
  template < typename Graph,
kpeter@2533
    72
             typename LowerMap = typename Graph::template EdgeMap<int>,
kpeter@2575
    73
             typename CapacityMap = typename Graph::template EdgeMap<int>,
kpeter@2533
    74
             typename CostMap = typename Graph::template EdgeMap<int>,
kpeter@2575
    75
             typename SupplyMap = typename Graph::template NodeMap<int> >
deba@2440
    76
  class NetworkSimplex
deba@2440
    77
  {
deba@2440
    78
    typedef typename CapacityMap::Value Capacity;
deba@2440
    79
    typedef typename CostMap::Value Cost;
deba@2440
    80
    typedef typename SupplyMap::Value Supply;
deba@2440
    81
deba@2440
    82
    typedef SmartGraph SGraph;
kpeter@2556
    83
    GRAPH_TYPEDEFS(typename SGraph);
deba@2440
    84
deba@2440
    85
    typedef typename SGraph::template EdgeMap<Capacity> SCapacityMap;
deba@2440
    86
    typedef typename SGraph::template EdgeMap<Cost> SCostMap;
deba@2440
    87
    typedef typename SGraph::template NodeMap<Supply> SSupplyMap;
deba@2440
    88
    typedef typename SGraph::template NodeMap<Cost> SPotentialMap;
deba@2440
    89
deba@2440
    90
    typedef typename SGraph::template NodeMap<int> IntNodeMap;
deba@2440
    91
    typedef typename SGraph::template NodeMap<bool> BoolNodeMap;
deba@2440
    92
    typedef typename SGraph::template NodeMap<Node> NodeNodeMap;
deba@2440
    93
    typedef typename SGraph::template NodeMap<Edge> EdgeNodeMap;
deba@2440
    94
    typedef typename SGraph::template EdgeMap<int> IntEdgeMap;
deba@2440
    95
deba@2440
    96
    typedef typename Graph::template NodeMap<Node> NodeRefMap;
deba@2440
    97
    typedef typename Graph::template EdgeMap<Edge> EdgeRefMap;
deba@2440
    98
deba@2440
    99
  public:
deba@2440
   100
kpeter@2556
   101
    /// The type of the flow map.
deba@2440
   102
    typedef typename Graph::template EdgeMap<Capacity> FlowMap;
kpeter@2556
   103
    /// The type of the potential map.
deba@2440
   104
    typedef typename Graph::template NodeMap<Cost> PotentialMap;
deba@2440
   105
kpeter@2575
   106
  public:
deba@2440
   107
kpeter@2575
   108
    /// Enum type to select the pivot rule used by \ref run().
kpeter@2575
   109
    enum PivotRuleEnum {
kpeter@2575
   110
      FIRST_ELIGIBLE_PIVOT,
kpeter@2575
   111
      BEST_ELIGIBLE_PIVOT,
kpeter@2575
   112
      BLOCK_SEARCH_PIVOT,
kpeter@2575
   113
      LIMITED_SEARCH_PIVOT,
kpeter@2575
   114
      CANDIDATE_LIST_PIVOT,
kpeter@2575
   115
      COMBINED_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@2575
   154
    class FirstEligiblePivotRule
kpeter@2575
   155
    {
kpeter@2575
   156
    private:
deba@2440
   157
kpeter@2575
   158
      NetworkSimplex &_ns;
kpeter@2575
   159
      EdgeIt _next_edge;
deba@2440
   160
kpeter@2575
   161
    public:
deba@2440
   162
kpeter@2575
   163
      /// Constructor.
kpeter@2575
   164
      FirstEligiblePivotRule(NetworkSimplex &ns) :
kpeter@2575
   165
        _ns(ns), _next_edge(ns._graph) {}
kpeter@2575
   166
kpeter@2575
   167
      /// Finds the next entering edge.
kpeter@2575
   168
      bool findEnteringEdge() {
kpeter@2575
   169
        for (EdgeIt e = _next_edge; e != INVALID; ++e) {
kpeter@2575
   170
          if (_ns._state[e] * _ns._red_cost[e] < 0) {
kpeter@2575
   171
            _ns._in_edge = e;
kpeter@2575
   172
            _next_edge = ++e;
kpeter@2575
   173
            return true;
kpeter@2575
   174
          }
kpeter@2575
   175
        }
kpeter@2575
   176
        for (EdgeIt e(_ns._graph); e != _next_edge; ++e) {
kpeter@2575
   177
          if (_ns._state[e] * _ns._red_cost[e] < 0) {
kpeter@2575
   178
            _ns._in_edge = e;
kpeter@2575
   179
            _next_edge = ++e;
kpeter@2575
   180
            return true;
kpeter@2575
   181
          }
kpeter@2575
   182
        }
kpeter@2575
   183
        return false;
kpeter@2575
   184
      }
kpeter@2575
   185
    }; //class FirstEligiblePivotRule
kpeter@2575
   186
kpeter@2575
   187
    /// \brief Implementation of the "Best Eligible" pivot rule for the
kpeter@2575
   188
    /// \ref NetworkSimplex "network simplex" algorithm.
kpeter@2575
   189
    ///
kpeter@2575
   190
    /// This class implements the "Best Eligible" pivot rule
kpeter@2575
   191
    /// for the \ref NetworkSimplex "network simplex" algorithm.
kpeter@2575
   192
    class BestEligiblePivotRule
kpeter@2575
   193
    {
kpeter@2575
   194
    private:
kpeter@2575
   195
kpeter@2575
   196
      NetworkSimplex &_ns;
kpeter@2575
   197
kpeter@2575
   198
    public:
kpeter@2575
   199
kpeter@2575
   200
      /// Constructor.
kpeter@2575
   201
      BestEligiblePivotRule(NetworkSimplex &ns) : _ns(ns) {}
kpeter@2575
   202
kpeter@2575
   203
      /// Finds the next entering edge.
kpeter@2575
   204
      bool findEnteringEdge() {
kpeter@2575
   205
        Cost min = 0;
kpeter@2575
   206
        for (EdgeIt e(_ns._graph); e != INVALID; ++e) {
kpeter@2575
   207
          if (_ns._state[e] * _ns._red_cost[e] < min) {
kpeter@2575
   208
            min = _ns._state[e] * _ns._red_cost[e];
kpeter@2575
   209
            _ns._in_edge = e;
kpeter@2575
   210
          }
kpeter@2575
   211
        }
kpeter@2575
   212
        return min < 0;
kpeter@2575
   213
      }
kpeter@2575
   214
    }; //class BestEligiblePivotRule
kpeter@2575
   215
kpeter@2575
   216
    /// \brief Implementation of the "Block Search" pivot rule for the
kpeter@2575
   217
    /// \ref NetworkSimplex "network simplex" algorithm.
kpeter@2575
   218
    ///
kpeter@2575
   219
    /// This class implements the "Block Search" pivot rule
kpeter@2575
   220
    /// for the \ref NetworkSimplex "network simplex" algorithm.
kpeter@2575
   221
    class BlockSearchPivotRule
kpeter@2575
   222
    {
kpeter@2575
   223
    private:
kpeter@2575
   224
kpeter@2575
   225
      NetworkSimplex &_ns;
kpeter@2575
   226
      EdgeIt _next_edge, _min_edge;
kpeter@2575
   227
      int _block_size;
kpeter@2575
   228
kpeter@2575
   229
      static const int MIN_BLOCK_SIZE = 10;
kpeter@2575
   230
kpeter@2575
   231
    public:
kpeter@2575
   232
kpeter@2575
   233
      /// Constructor.
kpeter@2575
   234
      BlockSearchPivotRule(NetworkSimplex &ns) :
kpeter@2575
   235
        _ns(ns), _next_edge(ns._graph), _min_edge(ns._graph)
kpeter@2575
   236
      {
kpeter@2575
   237
        _block_size = 2 * int(sqrt(countEdges(_ns._graph)));
kpeter@2575
   238
        if (_block_size < MIN_BLOCK_SIZE) _block_size = MIN_BLOCK_SIZE;
kpeter@2575
   239
      }
kpeter@2575
   240
kpeter@2575
   241
      /// Finds the next entering edge.
kpeter@2575
   242
      bool findEnteringEdge() {
kpeter@2575
   243
        Cost curr, min = 0;
kpeter@2575
   244
        int cnt = 0;
kpeter@2575
   245
        for (EdgeIt e = _next_edge; e != INVALID; ++e) {
kpeter@2575
   246
          if ((curr = _ns._state[e] * _ns._red_cost[e]) < min) {
kpeter@2575
   247
            min = curr;
kpeter@2575
   248
            _min_edge = e;
kpeter@2575
   249
          }
kpeter@2575
   250
          if (++cnt == _block_size) {
kpeter@2575
   251
            if (min < 0) break;
kpeter@2575
   252
            cnt = 0;
kpeter@2575
   253
          }
kpeter@2575
   254
        }
kpeter@2575
   255
        if (min == 0) {
kpeter@2575
   256
          for (EdgeIt e(_ns._graph); e != _next_edge; ++e) {
kpeter@2575
   257
            if ((curr = _ns._state[e] * _ns._red_cost[e]) < min) {
kpeter@2575
   258
              min = curr;
kpeter@2575
   259
              _min_edge = e;
kpeter@2575
   260
            }
kpeter@2575
   261
            if (++cnt == _block_size) {
kpeter@2575
   262
              if (min < 0) break;
kpeter@2575
   263
              cnt = 0;
kpeter@2575
   264
            }
kpeter@2575
   265
          }
kpeter@2575
   266
        }
kpeter@2575
   267
        _ns._in_edge = _min_edge;
kpeter@2575
   268
        _next_edge = ++_min_edge;
kpeter@2575
   269
        return min < 0;
kpeter@2575
   270
      }
kpeter@2575
   271
    }; //class BlockSearchPivotRule
kpeter@2575
   272
kpeter@2575
   273
    /// \brief Implementation of the "Limited Search" pivot rule for the
kpeter@2575
   274
    /// \ref NetworkSimplex "network simplex" algorithm.
kpeter@2575
   275
    ///
kpeter@2575
   276
    /// This class implements the "Limited Search" pivot rule
kpeter@2575
   277
    /// for the \ref NetworkSimplex "network simplex" algorithm.
kpeter@2575
   278
    class LimitedSearchPivotRule
kpeter@2575
   279
    {
kpeter@2575
   280
    private:
kpeter@2575
   281
kpeter@2575
   282
      NetworkSimplex &_ns;
kpeter@2575
   283
      EdgeIt _next_edge, _min_edge;
kpeter@2575
   284
      int _sample_size;
kpeter@2575
   285
kpeter@2575
   286
      static const int MIN_SAMPLE_SIZE = 10;
kpeter@2575
   287
      static const double SAMPLE_SIZE_FACTOR = 0.0015;
kpeter@2575
   288
kpeter@2575
   289
    public:
kpeter@2575
   290
kpeter@2575
   291
      /// Constructor.
kpeter@2575
   292
      LimitedSearchPivotRule(NetworkSimplex &ns) :
kpeter@2575
   293
        _ns(ns), _next_edge(ns._graph), _min_edge(ns._graph)
kpeter@2575
   294
      {
kpeter@2575
   295
        _sample_size = int(SAMPLE_SIZE_FACTOR * countEdges(_ns._graph));
kpeter@2575
   296
        if (_sample_size < MIN_SAMPLE_SIZE)
kpeter@2575
   297
          _sample_size = MIN_SAMPLE_SIZE;
kpeter@2575
   298
      }
kpeter@2575
   299
kpeter@2575
   300
      /// Finds the next entering edge.
kpeter@2575
   301
      bool findEnteringEdge() {
kpeter@2575
   302
        Cost curr, min = 0;
kpeter@2575
   303
        int cnt = 0;
kpeter@2575
   304
        for (EdgeIt e = _next_edge; e != INVALID; ++e) {
kpeter@2575
   305
          if ((curr = _ns._state[e] * _ns._red_cost[e]) < min) {
kpeter@2575
   306
            min = curr;
kpeter@2575
   307
            _min_edge = e;
kpeter@2575
   308
          }
kpeter@2575
   309
          if (curr < 0 && ++cnt == _sample_size) break;
kpeter@2575
   310
        }
kpeter@2575
   311
        if (min == 0) {
kpeter@2575
   312
          for (EdgeIt e(_ns._graph); e != _next_edge; ++e) {
kpeter@2575
   313
            if ((curr = _ns._state[e] * _ns._red_cost[e]) < min) {
kpeter@2575
   314
              min = curr;
kpeter@2575
   315
              _min_edge = e;
kpeter@2575
   316
            }
kpeter@2575
   317
            if (curr < 0 && ++cnt == _sample_size) break;
kpeter@2575
   318
          }
kpeter@2575
   319
        }
kpeter@2575
   320
        _ns._in_edge = _min_edge;
kpeter@2575
   321
        _next_edge = ++_min_edge;
kpeter@2575
   322
        return min < 0;
kpeter@2575
   323
      }
kpeter@2575
   324
    }; //class LimitedSearchPivotRule
kpeter@2575
   325
kpeter@2575
   326
    /// \brief Implementation of the "Candidate List" pivot rule for the
kpeter@2575
   327
    /// \ref NetworkSimplex "network simplex" algorithm.
kpeter@2575
   328
    ///
kpeter@2575
   329
    /// This class implements the "Candidate List" pivot rule
kpeter@2575
   330
    /// for the \ref NetworkSimplex "network simplex" algorithm.
kpeter@2575
   331
    class CandidateListPivotRule
kpeter@2575
   332
    {
kpeter@2575
   333
    private:
kpeter@2575
   334
kpeter@2575
   335
      NetworkSimplex &_ns;
kpeter@2575
   336
kpeter@2575
   337
      // The list of candidate edges.
kpeter@2575
   338
      std::vector<Edge> _candidates;
kpeter@2575
   339
      // The maximum length of the edge list.
kpeter@2575
   340
      int _list_length;
kpeter@2575
   341
      // The maximum number of minor iterations between two major
kpeter@2575
   342
      // itarations.
kpeter@2575
   343
      int _minor_limit;
kpeter@2575
   344
kpeter@2575
   345
      int _minor_count;
kpeter@2575
   346
      EdgeIt _next_edge;
kpeter@2575
   347
kpeter@2575
   348
      static const double LIST_LENGTH_FACTOR = 0.002;
kpeter@2575
   349
      static const double MINOR_LIMIT_FACTOR = 0.1;
kpeter@2575
   350
      static const int MIN_LIST_LENGTH = 10;
kpeter@2575
   351
      static const int MIN_MINOR_LIMIT = 2;
kpeter@2575
   352
kpeter@2575
   353
    public:
kpeter@2575
   354
kpeter@2575
   355
      /// Constructor.
kpeter@2575
   356
      CandidateListPivotRule(NetworkSimplex &ns) :
kpeter@2575
   357
        _ns(ns), _next_edge(ns._graph)
kpeter@2575
   358
      {
kpeter@2575
   359
        int edge_num = countEdges(_ns._graph);
kpeter@2575
   360
        _minor_count = 0;
kpeter@2575
   361
        _list_length = int(edge_num * LIST_LENGTH_FACTOR);
kpeter@2575
   362
        if (_list_length < MIN_LIST_LENGTH)
kpeter@2575
   363
          _list_length = MIN_LIST_LENGTH;
kpeter@2575
   364
        _minor_limit = int(_list_length * MINOR_LIMIT_FACTOR);
kpeter@2575
   365
        if (_minor_limit < MIN_MINOR_LIMIT)
kpeter@2575
   366
          _minor_limit = MIN_MINOR_LIMIT;
kpeter@2575
   367
      }
kpeter@2575
   368
kpeter@2575
   369
      /// Finds the next entering edge.
kpeter@2575
   370
      bool findEnteringEdge() {
kpeter@2575
   371
        Cost min, curr;
kpeter@2575
   372
        if (_minor_count < _minor_limit && _candidates.size() > 0) {
kpeter@2575
   373
          // Minor iteration
kpeter@2575
   374
          ++_minor_count;
kpeter@2575
   375
          Edge e;
kpeter@2575
   376
          min = 0;
kpeter@2575
   377
          for (int i = 0; i < int(_candidates.size()); ++i) {
kpeter@2575
   378
            e = _candidates[i];
kpeter@2575
   379
            if ((curr = _ns._state[e] * _ns._red_cost[e]) < min) {
kpeter@2575
   380
              min = curr;
kpeter@2575
   381
              _ns._in_edge = e;
kpeter@2575
   382
            }
kpeter@2575
   383
          }
kpeter@2575
   384
          if (min < 0) return true;
kpeter@2575
   385
        }
kpeter@2575
   386
kpeter@2575
   387
        // Major iteration
kpeter@2575
   388
        _candidates.clear();
kpeter@2575
   389
        EdgeIt e = _next_edge;
kpeter@2575
   390
        min = 0;
kpeter@2575
   391
        for ( ; e != INVALID; ++e) {
kpeter@2575
   392
          if ((curr = _ns._state[e] * _ns._red_cost[e]) < 0) {
kpeter@2575
   393
            _candidates.push_back(e);
kpeter@2575
   394
            if (curr < min) {
kpeter@2575
   395
              min = curr;
kpeter@2575
   396
              _ns._in_edge = e;
kpeter@2575
   397
            }
kpeter@2575
   398
            if (int(_candidates.size()) == _list_length) break;
kpeter@2575
   399
          }
kpeter@2575
   400
        }
kpeter@2575
   401
        if (int(_candidates.size()) < _list_length) {
kpeter@2575
   402
          for (e = EdgeIt(_ns._graph); e != _next_edge; ++e) {
kpeter@2575
   403
            if ((curr = _ns._state[e] * _ns._red_cost[e]) < 0) {
kpeter@2575
   404
              _candidates.push_back(e);
kpeter@2575
   405
              if (curr < min) {
kpeter@2575
   406
                min = curr;
kpeter@2575
   407
                _ns._in_edge = e;
kpeter@2575
   408
              }
kpeter@2575
   409
              if (int(_candidates.size()) == _list_length) break;
kpeter@2575
   410
            }
kpeter@2575
   411
          }
kpeter@2575
   412
        }
kpeter@2575
   413
        if (_candidates.size() == 0) return false;
kpeter@2575
   414
        _minor_count = 1;
kpeter@2575
   415
        _next_edge = ++e;
kpeter@2575
   416
        return true;
kpeter@2575
   417
      }
kpeter@2575
   418
    }; //class CandidateListPivotRule
kpeter@2575
   419
kpeter@2575
   420
  private:
kpeter@2575
   421
kpeter@2579
   422
    // State constants for edges
kpeter@2579
   423
    enum EdgeStateEnum {
kpeter@2579
   424
      STATE_UPPER = -1,
kpeter@2579
   425
      STATE_TREE  =  0,
kpeter@2579
   426
      STATE_LOWER =  1
kpeter@2579
   427
    };
kpeter@2575
   428
kpeter@2575
   429
    // Constant for the combined pivot rule.
kpeter@2575
   430
    static const int COMBINED_PIVOT_MAX_DEG = 5;
kpeter@2575
   431
kpeter@2575
   432
  private:
kpeter@2575
   433
kpeter@2575
   434
    // The directed graph the algorithm runs on
kpeter@2575
   435
    SGraph _graph;
kpeter@2575
   436
    // The original graph
kpeter@2575
   437
    const Graph &_graph_ref;
kpeter@2575
   438
    // The original lower bound map
kpeter@2575
   439
    const LowerMap *_lower;
kpeter@2575
   440
    // The capacity map
kpeter@2575
   441
    SCapacityMap _capacity;
kpeter@2575
   442
    // The cost map
kpeter@2575
   443
    SCostMap _cost;
kpeter@2575
   444
    // The supply map
kpeter@2575
   445
    SSupplyMap _supply;
kpeter@2575
   446
    bool _valid_supply;
kpeter@2575
   447
kpeter@2575
   448
    // Edge map of the current flow
kpeter@2575
   449
    SCapacityMap _flow;
kpeter@2575
   450
    // Node map of the current potentials
kpeter@2575
   451
    SPotentialMap _potential;
kpeter@2575
   452
kpeter@2575
   453
    // The depth node map of the spanning tree structure
kpeter@2575
   454
    IntNodeMap _depth;
kpeter@2575
   455
    // The parent node map of the spanning tree structure
kpeter@2575
   456
    NodeNodeMap _parent;
kpeter@2575
   457
    // The pred_edge node map of the spanning tree structure
kpeter@2575
   458
    EdgeNodeMap _pred_edge;
kpeter@2575
   459
    // The thread node map of the spanning tree structure
kpeter@2575
   460
    NodeNodeMap _thread;
kpeter@2575
   461
    // The forward node map of the spanning tree structure
kpeter@2575
   462
    BoolNodeMap _forward;
kpeter@2575
   463
    // The state edge map
kpeter@2575
   464
    IntEdgeMap _state;
kpeter@2575
   465
    // The root node of the starting spanning tree
kpeter@2575
   466
    Node _root;
kpeter@2575
   467
kpeter@2575
   468
    // The reduced cost map
kpeter@2575
   469
    ReducedCostMap _red_cost;
kpeter@2575
   470
kpeter@2575
   471
    // Members for handling the original graph
kpeter@2575
   472
    FlowMap _flow_result;
kpeter@2575
   473
    PotentialMap _potential_result;
kpeter@2575
   474
    NodeRefMap _node_ref;
kpeter@2575
   475
    EdgeRefMap _edge_ref;
deba@2440
   476
kpeter@2556
   477
    // The entering edge of the current pivot iteration.
kpeter@2575
   478
    Edge _in_edge;
kpeter@2575
   479
kpeter@2556
   480
    // Temporary nodes used in the current pivot iteration.
kpeter@2556
   481
    Node join, u_in, v_in, u_out, v_out;
kpeter@2556
   482
    Node right, first, second, last;
kpeter@2556
   483
    Node stem, par_stem, new_stem;
kpeter@2556
   484
    // The maximum augment amount along the found cycle in the current
kpeter@2556
   485
    // pivot iteration.
kpeter@2556
   486
    Capacity delta;
deba@2440
   487
deba@2440
   488
  public :
deba@2440
   489
deba@2440
   490
    /// \brief General constructor of the class (with lower bounds).
deba@2440
   491
    ///
deba@2440
   492
    /// General constructor of the class (with lower bounds).
deba@2440
   493
    ///
kpeter@2575
   494
    /// \param graph The directed graph the algorithm runs on.
kpeter@2575
   495
    /// \param lower The lower bounds of the edges.
kpeter@2575
   496
    /// \param capacity The capacities (upper bounds) of the edges.
kpeter@2575
   497
    /// \param cost The cost (length) values of the edges.
kpeter@2575
   498
    /// \param supply The supply values of the nodes (signed).
kpeter@2575
   499
    NetworkSimplex( const Graph &graph,
kpeter@2575
   500
                    const LowerMap &lower,
kpeter@2575
   501
                    const CapacityMap &capacity,
kpeter@2575
   502
                    const CostMap &cost,
kpeter@2575
   503
                    const SupplyMap &supply ) :
kpeter@2575
   504
      _graph(), _graph_ref(graph), _lower(&lower), _capacity(_graph),
kpeter@2575
   505
      _cost(_graph), _supply(_graph), _flow(_graph),
kpeter@2575
   506
      _potential(_graph), _depth(_graph), _parent(_graph),
kpeter@2575
   507
      _pred_edge(_graph), _thread(_graph), _forward(_graph),
kpeter@2575
   508
      _state(_graph), _red_cost(_graph, _cost, _potential),
kpeter@2575
   509
      _flow_result(graph), _potential_result(graph),
kpeter@2575
   510
      _node_ref(graph), _edge_ref(graph)
deba@2440
   511
    {
deba@2440
   512
      // Checking the sum of supply values
deba@2440
   513
      Supply sum = 0;
kpeter@2575
   514
      for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n)
kpeter@2575
   515
        sum += supply[n];
kpeter@2575
   516
      if (!(_valid_supply = sum == 0)) return;
deba@2440
   517
kpeter@2575
   518
      // Copying _graph_ref to _graph
kpeter@2575
   519
      _graph.reserveNode(countNodes(_graph_ref) + 1);
kpeter@2575
   520
      _graph.reserveEdge(countEdges(_graph_ref) + countNodes(_graph_ref));
kpeter@2575
   521
      copyGraph(_graph, _graph_ref)
kpeter@2575
   522
        .edgeMap(_cost, cost)
kpeter@2575
   523
        .nodeRef(_node_ref)
kpeter@2575
   524
        .edgeRef(_edge_ref)
kpeter@2556
   525
        .run();
deba@2440
   526
kpeter@2556
   527
      // Removing non-zero lower bounds
kpeter@2575
   528
      for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e) {
kpeter@2575
   529
        _capacity[_edge_ref[e]] = capacity[e] - lower[e];
deba@2440
   530
      }
kpeter@2575
   531
      for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n) {
kpeter@2575
   532
        Supply s = supply[n];
kpeter@2575
   533
        for (typename Graph::InEdgeIt e(_graph_ref, n); e != INVALID; ++e)
kpeter@2575
   534
          s += lower[e];
kpeter@2575
   535
        for (typename Graph::OutEdgeIt e(_graph_ref, n); e != INVALID; ++e)
kpeter@2575
   536
          s -= lower[e];
kpeter@2575
   537
        _supply[_node_ref[n]] = s;
deba@2440
   538
      }
deba@2440
   539
    }
deba@2440
   540
deba@2440
   541
    /// \brief General constructor of the class (without lower bounds).
deba@2440
   542
    ///
deba@2440
   543
    /// General constructor of the class (without lower bounds).
deba@2440
   544
    ///
kpeter@2575
   545
    /// \param graph The directed graph the algorithm runs on.
kpeter@2575
   546
    /// \param capacity The capacities (upper bounds) of the edges.
kpeter@2575
   547
    /// \param cost The cost (length) values of the edges.
kpeter@2575
   548
    /// \param supply The supply values of the nodes (signed).
kpeter@2575
   549
    NetworkSimplex( const Graph &graph,
kpeter@2575
   550
                    const CapacityMap &capacity,
kpeter@2575
   551
                    const CostMap &cost,
kpeter@2575
   552
                    const SupplyMap &supply ) :
kpeter@2575
   553
      _graph(), _graph_ref(graph), _lower(NULL), _capacity(_graph),
kpeter@2575
   554
      _cost(_graph), _supply(_graph), _flow(_graph),
kpeter@2575
   555
      _potential(_graph), _depth(_graph), _parent(_graph),
kpeter@2575
   556
      _pred_edge(_graph), _thread(_graph), _forward(_graph),
kpeter@2575
   557
      _state(_graph), _red_cost(_graph, _cost, _potential),
kpeter@2575
   558
      _flow_result(graph), _potential_result(graph),
kpeter@2575
   559
      _node_ref(graph), _edge_ref(graph)
deba@2440
   560
    {
deba@2440
   561
      // Checking the sum of supply values
deba@2440
   562
      Supply sum = 0;
kpeter@2575
   563
      for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n)
kpeter@2575
   564
        sum += supply[n];
kpeter@2575
   565
      if (!(_valid_supply = sum == 0)) return;
deba@2440
   566
kpeter@2575
   567
      // Copying _graph_ref to graph
kpeter@2575
   568
      copyGraph(_graph, _graph_ref)
kpeter@2575
   569
        .edgeMap(_capacity, capacity)
kpeter@2575
   570
        .edgeMap(_cost, cost)
kpeter@2575
   571
        .nodeMap(_supply, supply)
kpeter@2575
   572
        .nodeRef(_node_ref)
kpeter@2575
   573
        .edgeRef(_edge_ref)
kpeter@2556
   574
        .run();
deba@2440
   575
    }
deba@2440
   576
deba@2440
   577
    /// \brief Simple constructor of the class (with lower bounds).
deba@2440
   578
    ///
deba@2440
   579
    /// Simple constructor of the class (with lower bounds).
deba@2440
   580
    ///
kpeter@2575
   581
    /// \param graph The directed graph the algorithm runs on.
kpeter@2575
   582
    /// \param lower The lower bounds of the edges.
kpeter@2575
   583
    /// \param capacity The capacities (upper bounds) of the edges.
kpeter@2575
   584
    /// \param cost The cost (length) values of the edges.
kpeter@2575
   585
    /// \param s The source node.
kpeter@2575
   586
    /// \param t The target node.
kpeter@2575
   587
    /// \param flow_value The required amount of flow from node \c s
kpeter@2575
   588
    /// to node \c t (i.e. the supply of \c s and the demand of \c t).
kpeter@2575
   589
    NetworkSimplex( const Graph &graph,
kpeter@2575
   590
                    const LowerMap &lower,
kpeter@2575
   591
                    const CapacityMap &capacity,
kpeter@2575
   592
                    const CostMap &cost,
kpeter@2575
   593
                    typename Graph::Node s,
kpeter@2575
   594
                    typename Graph::Node t,
kpeter@2575
   595
                    typename SupplyMap::Value flow_value ) :
kpeter@2575
   596
      _graph(), _graph_ref(graph), _lower(&lower), _capacity(_graph),
kpeter@2575
   597
      _cost(_graph), _supply(_graph), _flow(_graph),
kpeter@2575
   598
      _potential(_graph), _depth(_graph), _parent(_graph),
kpeter@2575
   599
      _pred_edge(_graph), _thread(_graph), _forward(_graph),
kpeter@2575
   600
      _state(_graph), _red_cost(_graph, _cost, _potential),
kpeter@2575
   601
      _flow_result(graph), _potential_result(graph),
kpeter@2575
   602
      _node_ref(graph), _edge_ref(graph)
deba@2440
   603
    {
kpeter@2575
   604
      // Copying _graph_ref to graph
kpeter@2575
   605
      copyGraph(_graph, _graph_ref)
kpeter@2575
   606
        .edgeMap(_cost, cost)
kpeter@2575
   607
        .nodeRef(_node_ref)
kpeter@2575
   608
        .edgeRef(_edge_ref)
kpeter@2556
   609
        .run();
deba@2440
   610
kpeter@2556
   611
      // Removing non-zero lower bounds
kpeter@2575
   612
      for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e) {
kpeter@2575
   613
        _capacity[_edge_ref[e]] = capacity[e] - lower[e];
deba@2440
   614
      }
kpeter@2575
   615
      for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n) {
kpeter@2575
   616
        Supply sum = 0;
kpeter@2575
   617
        if (n == s) sum =  flow_value;
kpeter@2575
   618
        if (n == t) sum = -flow_value;
kpeter@2575
   619
        for (typename Graph::InEdgeIt e(_graph_ref, n); e != INVALID; ++e)
kpeter@2575
   620
          sum += lower[e];
kpeter@2575
   621
        for (typename Graph::OutEdgeIt e(_graph_ref, n); e != INVALID; ++e)
kpeter@2575
   622
          sum -= lower[e];
kpeter@2575
   623
        _supply[_node_ref[n]] = sum;
deba@2440
   624
      }
kpeter@2575
   625
      _valid_supply = true;
deba@2440
   626
    }
deba@2440
   627
deba@2440
   628
    /// \brief Simple constructor of the class (without lower bounds).
deba@2440
   629
    ///
deba@2440
   630
    /// Simple constructor of the class (without lower bounds).
deba@2440
   631
    ///
kpeter@2575
   632
    /// \param graph The directed graph the algorithm runs on.
kpeter@2575
   633
    /// \param capacity The capacities (upper bounds) of the edges.
kpeter@2575
   634
    /// \param cost The cost (length) values of the edges.
kpeter@2575
   635
    /// \param s The source node.
kpeter@2575
   636
    /// \param t The target node.
kpeter@2575
   637
    /// \param flow_value The required amount of flow from node \c s
kpeter@2575
   638
    /// to node \c t (i.e. the supply of \c s and the demand of \c t).
kpeter@2575
   639
    NetworkSimplex( const Graph &graph,
kpeter@2575
   640
                    const CapacityMap &capacity,
kpeter@2575
   641
                    const CostMap &cost,
kpeter@2575
   642
                    typename Graph::Node s,
kpeter@2575
   643
                    typename Graph::Node t,
kpeter@2575
   644
                    typename SupplyMap::Value flow_value ) :
kpeter@2575
   645
      _graph(), _graph_ref(graph), _lower(NULL), _capacity(_graph),
kpeter@2575
   646
      _cost(_graph), _supply(_graph, 0), _flow(_graph),
kpeter@2575
   647
      _potential(_graph), _depth(_graph), _parent(_graph),
kpeter@2575
   648
      _pred_edge(_graph), _thread(_graph), _forward(_graph),
kpeter@2575
   649
      _state(_graph), _red_cost(_graph, _cost, _potential),
kpeter@2575
   650
      _flow_result(graph), _potential_result(graph),
kpeter@2575
   651
      _node_ref(graph), _edge_ref(graph)
deba@2440
   652
    {
kpeter@2575
   653
      // Copying _graph_ref to graph
kpeter@2575
   654
      copyGraph(_graph, _graph_ref)
kpeter@2575
   655
        .edgeMap(_capacity, capacity)
kpeter@2575
   656
        .edgeMap(_cost, cost)
kpeter@2575
   657
        .nodeRef(_node_ref)
kpeter@2575
   658
        .edgeRef(_edge_ref)
kpeter@2556
   659
        .run();
kpeter@2575
   660
      _supply[_node_ref[s]] =  flow_value;
kpeter@2575
   661
      _supply[_node_ref[t]] = -flow_value;
kpeter@2575
   662
      _valid_supply = true;
deba@2440
   663
    }
deba@2440
   664
kpeter@2556
   665
    /// \brief Runs the algorithm.
kpeter@2556
   666
    ///
kpeter@2556
   667
    /// Runs the algorithm.
kpeter@2556
   668
    ///
kpeter@2575
   669
    /// \param pivot_rule The pivot rule that is used during the
kpeter@2575
   670
    /// algorithm.
kpeter@2575
   671
    ///
kpeter@2575
   672
    /// The available pivot rules:
kpeter@2575
   673
    ///
kpeter@2575
   674
    /// - FIRST_ELIGIBLE_PIVOT The next eligible edge is selected in
kpeter@2575
   675
    /// a wraparound fashion in every iteration
kpeter@2575
   676
    /// (\ref FirstEligiblePivotRule).
kpeter@2575
   677
    ///
kpeter@2575
   678
    /// - BEST_ELIGIBLE_PIVOT The best eligible edge is selected in
kpeter@2575
   679
    /// every iteration (\ref BestEligiblePivotRule).
kpeter@2575
   680
    ///
kpeter@2575
   681
    /// - BLOCK_SEARCH_PIVOT A specified number of edges are examined in
kpeter@2575
   682
    /// every iteration in a wraparound fashion and the best eligible
kpeter@2575
   683
    /// edge is selected from this block (\ref BlockSearchPivotRule).
kpeter@2575
   684
    ///
kpeter@2575
   685
    /// - LIMITED_SEARCH_PIVOT A specified number of eligible edges are
kpeter@2575
   686
    /// examined in every iteration in a wraparound fashion and the best
kpeter@2575
   687
    /// one is selected from them (\ref LimitedSearchPivotRule).
kpeter@2575
   688
    ///
kpeter@2575
   689
    /// - CANDIDATE_LIST_PIVOT In major iterations a candidate list is
kpeter@2575
   690
    /// built from eligible edges and it is used for edge selection in
kpeter@2575
   691
    /// the following minor iterations (\ref CandidateListPivotRule).
kpeter@2575
   692
    ///
kpeter@2575
   693
    /// - COMBINED_PIVOT This is a combined version of the two fastest
kpeter@2575
   694
    /// pivot rules.
kpeter@2575
   695
    /// For rather sparse graphs \ref LimitedSearchPivotRule
kpeter@2575
   696
    /// "Limited Search" implementation is used, otherwise
kpeter@2575
   697
    /// \ref BlockSearchPivotRule "Block Search" pivot rule is used.
kpeter@2575
   698
    /// According to our benchmark tests this combined method is the
kpeter@2575
   699
    /// most efficient.
kpeter@2575
   700
    ///
kpeter@2556
   701
    /// \return \c true if a feasible flow can be found.
kpeter@2575
   702
    bool run(PivotRuleEnum pivot_rule = COMBINED_PIVOT) {
kpeter@2575
   703
      return init() && start(pivot_rule);
kpeter@2556
   704
    }
kpeter@2556
   705
kpeter@2575
   706
    /// \brief Returns a const reference to the edge map storing the
kpeter@2575
   707
    /// found flow.
deba@2440
   708
    ///
kpeter@2575
   709
    /// Returns a const reference to the edge map storing the found flow.
deba@2440
   710
    ///
deba@2440
   711
    /// \pre \ref run() must be called before using this function.
deba@2440
   712
    const FlowMap& flowMap() const {
kpeter@2575
   713
      return _flow_result;
deba@2440
   714
    }
deba@2440
   715
kpeter@2575
   716
    /// \brief Returns a const reference to the node map storing the
kpeter@2575
   717
    /// found potentials (the dual solution).
deba@2440
   718
    ///
kpeter@2575
   719
    /// Returns a const reference to the node map storing the found
kpeter@2575
   720
    /// potentials (the dual solution).
deba@2440
   721
    ///
deba@2440
   722
    /// \pre \ref run() must be called before using this function.
deba@2440
   723
    const PotentialMap& potentialMap() const {
kpeter@2575
   724
      return _potential_result;
deba@2440
   725
    }
deba@2440
   726
deba@2440
   727
    /// \brief Returns the total cost of the found flow.
deba@2440
   728
    ///
deba@2440
   729
    /// Returns the total cost of the found flow. The complexity of the
deba@2440
   730
    /// function is \f$ O(e) \f$.
deba@2440
   731
    ///
deba@2440
   732
    /// \pre \ref run() must be called before using this function.
deba@2440
   733
    Cost totalCost() const {
deba@2440
   734
      Cost c = 0;
kpeter@2575
   735
      for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e)
kpeter@2575
   736
        c += _flow_result[e] * _cost[_edge_ref[e]];
deba@2440
   737
      return c;
deba@2440
   738
    }
deba@2440
   739
kpeter@2575
   740
  private:
deba@2440
   741
deba@2440
   742
    /// \brief Extends the underlaying graph and initializes all the
deba@2440
   743
    /// node and edge maps.
deba@2440
   744
    bool init() {
kpeter@2575
   745
      if (!_valid_supply) return false;
deba@2440
   746
deba@2440
   747
      // Initializing state and flow maps
kpeter@2575
   748
      for (EdgeIt e(_graph); e != INVALID; ++e) {
kpeter@2575
   749
        _flow[e] = 0;
kpeter@2575
   750
        _state[e] = STATE_LOWER;
deba@2440
   751
      }
deba@2440
   752
deba@2440
   753
      // Adding an artificial root node to the graph
kpeter@2575
   754
      _root = _graph.addNode();
kpeter@2575
   755
      _parent[_root] = INVALID;
kpeter@2575
   756
      _pred_edge[_root] = INVALID;
kpeter@2575
   757
      _depth[_root] = 0;
kpeter@2575
   758
      _supply[_root] = 0;
kpeter@2575
   759
      _potential[_root] = 0;
deba@2440
   760
deba@2440
   761
      // Adding artificial edges to the graph and initializing the node
deba@2440
   762
      // maps of the spanning tree data structure
kpeter@2575
   763
      Node last = _root;
deba@2440
   764
      Edge e;
deba@2440
   765
      Cost max_cost = std::numeric_limits<Cost>::max() / 4;
kpeter@2575
   766
      for (NodeIt u(_graph); u != INVALID; ++u) {
kpeter@2575
   767
        if (u == _root) continue;
kpeter@2575
   768
        _thread[last] = u;
kpeter@2556
   769
        last = u;
kpeter@2575
   770
        _parent[u] = _root;
kpeter@2575
   771
        _depth[u] = 1;
kpeter@2575
   772
        if (_supply[u] >= 0) {
kpeter@2575
   773
          e = _graph.addEdge(u, _root);
kpeter@2575
   774
          _flow[e] = _supply[u];
kpeter@2575
   775
          _forward[u] = true;
kpeter@2575
   776
          _potential[u] = -max_cost;
kpeter@2556
   777
        } else {
kpeter@2575
   778
          e = _graph.addEdge(_root, u);
kpeter@2575
   779
          _flow[e] = -_supply[u];
kpeter@2575
   780
          _forward[u] = false;
kpeter@2575
   781
          _potential[u] = max_cost;
kpeter@2556
   782
        }
kpeter@2575
   783
        _cost[e] = max_cost;
kpeter@2575
   784
        _capacity[e] = std::numeric_limits<Capacity>::max();
kpeter@2575
   785
        _state[e] = STATE_TREE;
kpeter@2575
   786
        _pred_edge[u] = e;
deba@2440
   787
      }
kpeter@2575
   788
      _thread[last] = _root;
deba@2440
   789
kpeter@2575
   790
      return true;
deba@2440
   791
    }
deba@2440
   792
kpeter@2575
   793
    /// Finds the join node.
kpeter@2575
   794
    Node findJoinNode() {
kpeter@2575
   795
      Node u = _graph.source(_in_edge);
kpeter@2575
   796
      Node v = _graph.target(_in_edge);
kpeter@2575
   797
      while (u != v) {
kpeter@2575
   798
        if (_depth[u] == _depth[v]) {
kpeter@2575
   799
          u = _parent[u];
kpeter@2575
   800
          v = _parent[v];
kpeter@2556
   801
        }
kpeter@2575
   802
        else if (_depth[u] > _depth[v]) u = _parent[u];
kpeter@2575
   803
        else v = _parent[v];
deba@2440
   804
      }
deba@2440
   805
      return u;
deba@2440
   806
    }
deba@2440
   807
deba@2440
   808
    /// \brief Finds the leaving edge of the cycle. Returns \c true if
deba@2440
   809
    /// the leaving edge is not the same as the entering edge.
deba@2440
   810
    bool findLeavingEdge() {
deba@2440
   811
      // Initializing first and second nodes according to the direction
deba@2440
   812
      // of the cycle
kpeter@2575
   813
      if (_state[_in_edge] == STATE_LOWER) {
kpeter@2575
   814
        first  = _graph.source(_in_edge);
kpeter@2575
   815
        second = _graph.target(_in_edge);
deba@2440
   816
      } else {
kpeter@2575
   817
        first  = _graph.target(_in_edge);
kpeter@2575
   818
        second = _graph.source(_in_edge);
deba@2440
   819
      }
kpeter@2575
   820
      delta = _capacity[_in_edge];
deba@2440
   821
      bool result = false;
deba@2440
   822
      Capacity d;
deba@2440
   823
      Edge e;
deba@2440
   824
deba@2440
   825
      // Searching the cycle along the path form the first node to the
deba@2440
   826
      // root node
kpeter@2575
   827
      for (Node u = first; u != join; u = _parent[u]) {
kpeter@2575
   828
        e = _pred_edge[u];
kpeter@2575
   829
        d = _forward[u] ? _flow[e] : _capacity[e] - _flow[e];
kpeter@2556
   830
        if (d < delta) {
kpeter@2556
   831
          delta = d;
kpeter@2556
   832
          u_out = u;
kpeter@2556
   833
          u_in = first;
kpeter@2556
   834
          v_in = second;
kpeter@2556
   835
          result = true;
kpeter@2556
   836
        }
deba@2440
   837
      }
deba@2440
   838
      // Searching the cycle along the path form the second node to the
deba@2440
   839
      // root node
kpeter@2575
   840
      for (Node u = second; u != join; u = _parent[u]) {
kpeter@2575
   841
        e = _pred_edge[u];
kpeter@2575
   842
        d = _forward[u] ? _capacity[e] - _flow[e] : _flow[e];
kpeter@2556
   843
        if (d <= delta) {
kpeter@2556
   844
          delta = d;
kpeter@2556
   845
          u_out = u;
kpeter@2556
   846
          u_in = second;
kpeter@2556
   847
          v_in = first;
kpeter@2556
   848
          result = true;
kpeter@2556
   849
        }
deba@2440
   850
      }
deba@2440
   851
      return result;
deba@2440
   852
    }
deba@2440
   853
kpeter@2575
   854
    /// Changes \c flow and \c state edge maps.
deba@2440
   855
    void changeFlows(bool change) {
deba@2440
   856
      // Augmenting along the cycle
deba@2440
   857
      if (delta > 0) {
kpeter@2575
   858
        Capacity val = _state[_in_edge] * delta;
kpeter@2575
   859
        _flow[_in_edge] += val;
kpeter@2575
   860
        for (Node u = _graph.source(_in_edge); u != join; u = _parent[u]) {
kpeter@2575
   861
          _flow[_pred_edge[u]] += _forward[u] ? -val : val;
kpeter@2556
   862
        }
kpeter@2575
   863
        for (Node u = _graph.target(_in_edge); u != join; u = _parent[u]) {
kpeter@2575
   864
          _flow[_pred_edge[u]] += _forward[u] ? val : -val;
kpeter@2556
   865
        }
deba@2440
   866
      }
deba@2440
   867
      // Updating the state of the entering and leaving edges
deba@2440
   868
      if (change) {
kpeter@2575
   869
        _state[_in_edge] = STATE_TREE;
kpeter@2575
   870
        _state[_pred_edge[u_out]] =
kpeter@2575
   871
          (_flow[_pred_edge[u_out]] == 0) ? STATE_LOWER : STATE_UPPER;
deba@2440
   872
      } else {
kpeter@2575
   873
        _state[_in_edge] = -_state[_in_edge];
deba@2440
   874
      }
deba@2440
   875
    }
deba@2440
   876
kpeter@2575
   877
    /// Updates \c thread and \c parent node maps.
deba@2440
   878
    void updateThreadParent() {
deba@2440
   879
      Node u;
kpeter@2575
   880
      v_out = _parent[u_out];
deba@2440
   881
deba@2440
   882
      // Handling the case when join and v_out coincide
deba@2440
   883
      bool par_first = false;
deba@2440
   884
      if (join == v_out) {
kpeter@2575
   885
        for (u = join; u != u_in && u != v_in; u = _thread[u]) ;
kpeter@2556
   886
        if (u == v_in) {
kpeter@2556
   887
          par_first = true;
kpeter@2575
   888
          while (_thread[u] != u_out) u = _thread[u];
kpeter@2556
   889
          first = u;
kpeter@2556
   890
        }
deba@2440
   891
      }
deba@2440
   892
deba@2440
   893
      // Finding the last successor of u_in (u) and the node after it
deba@2440
   894
      // (right) according to the thread index
kpeter@2575
   895
      for (u = u_in; _depth[_thread[u]] > _depth[u_in]; u = _thread[u]) ;
kpeter@2575
   896
      right = _thread[u];
kpeter@2575
   897
      if (_thread[v_in] == u_out) {
kpeter@2575
   898
        for (last = u; _depth[last] > _depth[u_out]; last = _thread[last]) ;
kpeter@2575
   899
        if (last == u_out) last = _thread[last];
deba@2440
   900
      }
kpeter@2575
   901
      else last = _thread[v_in];
deba@2440
   902
deba@2440
   903
      // Updating stem nodes
kpeter@2575
   904
      _thread[v_in] = stem = u_in;
deba@2440
   905
      par_stem = v_in;
deba@2440
   906
      while (stem != u_out) {
kpeter@2575
   907
        _thread[u] = new_stem = _parent[stem];
deba@2440
   908
kpeter@2556
   909
        // Finding the node just before the stem node (u) according to
kpeter@2556
   910
        // the original thread index
kpeter@2575
   911
        for (u = new_stem; _thread[u] != stem; u = _thread[u]) ;
kpeter@2575
   912
        _thread[u] = right;
deba@2440
   913
kpeter@2556
   914
        // Changing the parent node of stem and shifting stem and
kpeter@2556
   915
        // par_stem nodes
kpeter@2575
   916
        _parent[stem] = par_stem;
kpeter@2556
   917
        par_stem = stem;
kpeter@2556
   918
        stem = new_stem;
deba@2440
   919
kpeter@2556
   920
        // Finding the last successor of stem (u) and the node after it
kpeter@2556
   921
        // (right) according to the thread index
kpeter@2575
   922
        for (u = stem; _depth[_thread[u]] > _depth[stem]; u = _thread[u]) ;
kpeter@2575
   923
        right = _thread[u];
deba@2440
   924
      }
kpeter@2575
   925
      _parent[u_out] = par_stem;
kpeter@2575
   926
      _thread[u] = last;
deba@2440
   927
deba@2440
   928
      if (join == v_out && par_first) {
kpeter@2575
   929
        if (first != v_in) _thread[first] = right;
deba@2440
   930
      } else {
kpeter@2575
   931
        for (u = v_out; _thread[u] != u_out; u = _thread[u]) ;
kpeter@2575
   932
        _thread[u] = right;
deba@2440
   933
      }
deba@2440
   934
    }
deba@2440
   935
kpeter@2575
   936
    /// Updates \c pred_edge and \c forward node maps.
deba@2440
   937
    void updatePredEdge() {
deba@2440
   938
      Node u = u_out, v;
deba@2440
   939
      while (u != u_in) {
kpeter@2575
   940
        v = _parent[u];
kpeter@2575
   941
        _pred_edge[u] = _pred_edge[v];
kpeter@2575
   942
        _forward[u] = !_forward[v];
kpeter@2556
   943
        u = v;
deba@2440
   944
      }
kpeter@2575
   945
      _pred_edge[u_in] = _in_edge;
kpeter@2575
   946
      _forward[u_in] = (u_in == _graph.source(_in_edge));
deba@2440
   947
    }
deba@2440
   948
kpeter@2575
   949
    /// Updates \c depth and \c potential node maps.
deba@2440
   950
    void updateDepthPotential() {
kpeter@2575
   951
      _depth[u_in] = _depth[v_in] + 1;
kpeter@2575
   952
      _potential[u_in] = _forward[u_in] ?
kpeter@2575
   953
        _potential[v_in] - _cost[_pred_edge[u_in]] :
kpeter@2575
   954
        _potential[v_in] + _cost[_pred_edge[u_in]];
deba@2440
   955
kpeter@2575
   956
      Node u = _thread[u_in], v;
deba@2440
   957
      while (true) {
kpeter@2575
   958
        v = _parent[u];
kpeter@2556
   959
        if (v == INVALID) break;
kpeter@2575
   960
        _depth[u] = _depth[v] + 1;
kpeter@2575
   961
        _potential[u] = _forward[u] ?
kpeter@2575
   962
          _potential[v] - _cost[_pred_edge[u]] :
kpeter@2575
   963
          _potential[v] + _cost[_pred_edge[u]];
kpeter@2575
   964
        if (_depth[u] <= _depth[v_in]) break;
kpeter@2575
   965
        u = _thread[u];
deba@2440
   966
      }
deba@2440
   967
    }
deba@2440
   968
kpeter@2575
   969
    /// Executes the algorithm.
kpeter@2575
   970
    bool start(PivotRuleEnum pivot_rule) {
kpeter@2575
   971
      switch (pivot_rule) {
kpeter@2575
   972
        case FIRST_ELIGIBLE_PIVOT:
kpeter@2575
   973
          return start<FirstEligiblePivotRule>();
kpeter@2575
   974
        case BEST_ELIGIBLE_PIVOT:
kpeter@2575
   975
          return start<BestEligiblePivotRule>();
kpeter@2575
   976
        case BLOCK_SEARCH_PIVOT:
kpeter@2575
   977
          return start<BlockSearchPivotRule>();
kpeter@2575
   978
        case LIMITED_SEARCH_PIVOT:
kpeter@2575
   979
          return start<LimitedSearchPivotRule>();
kpeter@2575
   980
        case CANDIDATE_LIST_PIVOT:
kpeter@2575
   981
          return start<CandidateListPivotRule>();
kpeter@2575
   982
        case COMBINED_PIVOT:
kpeter@2575
   983
          if ( countEdges(_graph) / countNodes(_graph) <=
kpeter@2575
   984
               COMBINED_PIVOT_MAX_DEG )
kpeter@2575
   985
            return start<LimitedSearchPivotRule>();
kpeter@2575
   986
          else
kpeter@2575
   987
            return start<BlockSearchPivotRule>();
kpeter@2575
   988
      }
kpeter@2575
   989
      return false;
kpeter@2575
   990
    }
kpeter@2575
   991
kpeter@2575
   992
    template<class PivotRuleImplementation>
deba@2440
   993
    bool start() {
kpeter@2575
   994
      PivotRuleImplementation pivot(*this);
kpeter@2575
   995
kpeter@2575
   996
      // Executing the network simplex algorithm
kpeter@2575
   997
      while (pivot.findEnteringEdge()) {
kpeter@2556
   998
        join = findJoinNode();
kpeter@2556
   999
        bool change = findLeavingEdge();
kpeter@2556
  1000
        changeFlows(change);
kpeter@2556
  1001
        if (change) {
kpeter@2556
  1002
          updateThreadParent();
kpeter@2556
  1003
          updatePredEdge();
kpeter@2556
  1004
          updateDepthPotential();
kpeter@2556
  1005
        }
deba@2440
  1006
      }
deba@2440
  1007
kpeter@2575
  1008
      // Checking if the flow amount equals zero on all the artificial
kpeter@2575
  1009
      // edges
kpeter@2575
  1010
      for (InEdgeIt e(_graph, _root); e != INVALID; ++e)
kpeter@2575
  1011
        if (_flow[e] > 0) return false;
kpeter@2575
  1012
      for (OutEdgeIt e(_graph, _root); e != INVALID; ++e)
kpeter@2575
  1013
        if (_flow[e] > 0) return false;
deba@2440
  1014
kpeter@2575
  1015
      // Copying flow values to _flow_result
kpeter@2575
  1016
      if (_lower) {
kpeter@2575
  1017
        for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e)
kpeter@2575
  1018
          _flow_result[e] = (*_lower)[e] + _flow[_edge_ref[e]];
deba@2440
  1019
      } else {
kpeter@2575
  1020
        for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e)
kpeter@2575
  1021
          _flow_result[e] = _flow[_edge_ref[e]];
deba@2440
  1022
      }
kpeter@2575
  1023
      // Copying potential values to _potential_result
kpeter@2575
  1024
      for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n)
kpeter@2575
  1025
        _potential_result[n] = _potential[_node_ref[n]];
deba@2440
  1026
deba@2440
  1027
      return true;
deba@2440
  1028
    }
deba@2440
  1029
deba@2440
  1030
  }; //class NetworkSimplex
deba@2440
  1031
deba@2440
  1032
  ///@}
deba@2440
  1033
deba@2440
  1034
} //namespace lemon
deba@2440
  1035
deba@2440
  1036
#endif //LEMON_NETWORK_SIMPLEX_H