lemon/network_simplex.h
author kpeter
Thu, 28 Feb 2008 02:54:27 +0000
changeset 2581 054566ac0934
parent 2579 691ce54544c5
child 2588 4d3bc1d04c1d
permissions -rw-r--r--
Query improvements in the min cost flow algorithms.

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