lemon/network_simplex.h
author hegyi
Tue, 08 Apr 2008 11:39:40 +0000
changeset 2602 1c7790d9e025
parent 2588 4d3bc1d04c1d
child 2619 30fb4d68b0e8
permissions -rw-r--r--
Rel.07 NEWS - 3. round
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@2593
   283
      static const int SAMPLE_SIZE_FACTOR = 15;
kpeter@2575
   284
      static const int MIN_SAMPLE_SIZE = 10;
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@2593
   292
        _sample_size = countEdges(_ns._graph) *
kpeter@2593
   293
                       SAMPLE_SIZE_FACTOR / 10000;
kpeter@2575
   294
        if (_sample_size < MIN_SAMPLE_SIZE)
kpeter@2575
   295
          _sample_size = MIN_SAMPLE_SIZE;
kpeter@2575
   296
      }
kpeter@2575
   297
kpeter@2575
   298
      /// Finds the next entering edge.
kpeter@2575
   299
      bool findEnteringEdge() {
kpeter@2575
   300
        Cost curr, min = 0;
kpeter@2575
   301
        int cnt = 0;
kpeter@2575
   302
        for (EdgeIt e = _next_edge; e != INVALID; ++e) {
kpeter@2575
   303
          if ((curr = _ns._state[e] * _ns._red_cost[e]) < min) {
kpeter@2575
   304
            min = curr;
kpeter@2575
   305
            _min_edge = e;
kpeter@2575
   306
          }
kpeter@2575
   307
          if (curr < 0 && ++cnt == _sample_size) break;
kpeter@2575
   308
        }
kpeter@2575
   309
        if (min == 0) {
kpeter@2575
   310
          for (EdgeIt e(_ns._graph); e != _next_edge; ++e) {
kpeter@2575
   311
            if ((curr = _ns._state[e] * _ns._red_cost[e]) < min) {
kpeter@2575
   312
              min = curr;
kpeter@2575
   313
              _min_edge = e;
kpeter@2575
   314
            }
kpeter@2575
   315
            if (curr < 0 && ++cnt == _sample_size) break;
kpeter@2575
   316
          }
kpeter@2575
   317
        }
kpeter@2575
   318
        _ns._in_edge = _min_edge;
kpeter@2575
   319
        _next_edge = ++_min_edge;
kpeter@2575
   320
        return min < 0;
kpeter@2575
   321
      }
kpeter@2575
   322
    }; //class LimitedSearchPivotRule
kpeter@2575
   323
kpeter@2575
   324
    /// \brief Implementation of the "Candidate List" pivot rule for the
kpeter@2575
   325
    /// \ref NetworkSimplex "network simplex" algorithm.
kpeter@2575
   326
    ///
kpeter@2575
   327
    /// This class implements the "Candidate List" pivot rule
kpeter@2575
   328
    /// for the \ref NetworkSimplex "network simplex" algorithm.
kpeter@2575
   329
    class CandidateListPivotRule
kpeter@2575
   330
    {
kpeter@2575
   331
    private:
kpeter@2575
   332
kpeter@2575
   333
      NetworkSimplex &_ns;
kpeter@2575
   334
kpeter@2575
   335
      // The list of candidate edges.
kpeter@2575
   336
      std::vector<Edge> _candidates;
kpeter@2575
   337
      // The maximum length of the edge list.
kpeter@2575
   338
      int _list_length;
kpeter@2575
   339
      // The maximum number of minor iterations between two major
kpeter@2575
   340
      // itarations.
kpeter@2575
   341
      int _minor_limit;
kpeter@2575
   342
kpeter@2575
   343
      int _minor_count;
kpeter@2575
   344
      EdgeIt _next_edge;
kpeter@2575
   345
kpeter@2593
   346
      static const int LIST_LENGTH_FACTOR = 20;
kpeter@2593
   347
      static const int MINOR_LIMIT_FACTOR = 10;
kpeter@2575
   348
      static const int MIN_LIST_LENGTH = 10;
kpeter@2575
   349
      static const int MIN_MINOR_LIMIT = 2;
kpeter@2575
   350
kpeter@2575
   351
    public:
kpeter@2575
   352
kpeter@2575
   353
      /// Constructor.
kpeter@2575
   354
      CandidateListPivotRule(NetworkSimplex &ns) :
kpeter@2575
   355
        _ns(ns), _next_edge(ns._graph)
kpeter@2575
   356
      {
kpeter@2575
   357
        int edge_num = countEdges(_ns._graph);
kpeter@2575
   358
        _minor_count = 0;
kpeter@2593
   359
        _list_length = edge_num * LIST_LENGTH_FACTOR / 10000;
kpeter@2575
   360
        if (_list_length < MIN_LIST_LENGTH)
kpeter@2575
   361
          _list_length = MIN_LIST_LENGTH;
kpeter@2593
   362
        _minor_limit = _list_length * MINOR_LIMIT_FACTOR / 100;
kpeter@2575
   363
        if (_minor_limit < MIN_MINOR_LIMIT)
kpeter@2575
   364
          _minor_limit = MIN_MINOR_LIMIT;
kpeter@2575
   365
      }
kpeter@2575
   366
kpeter@2575
   367
      /// Finds the next entering edge.
kpeter@2575
   368
      bool findEnteringEdge() {
kpeter@2575
   369
        Cost min, curr;
kpeter@2575
   370
        if (_minor_count < _minor_limit && _candidates.size() > 0) {
kpeter@2575
   371
          // Minor iteration
kpeter@2575
   372
          ++_minor_count;
kpeter@2575
   373
          Edge e;
kpeter@2575
   374
          min = 0;
kpeter@2575
   375
          for (int i = 0; i < int(_candidates.size()); ++i) {
kpeter@2575
   376
            e = _candidates[i];
kpeter@2575
   377
            if ((curr = _ns._state[e] * _ns._red_cost[e]) < min) {
kpeter@2575
   378
              min = curr;
kpeter@2575
   379
              _ns._in_edge = e;
kpeter@2575
   380
            }
kpeter@2575
   381
          }
kpeter@2575
   382
          if (min < 0) return true;
kpeter@2575
   383
        }
kpeter@2575
   384
kpeter@2575
   385
        // Major iteration
kpeter@2575
   386
        _candidates.clear();
kpeter@2575
   387
        EdgeIt e = _next_edge;
kpeter@2575
   388
        min = 0;
kpeter@2575
   389
        for ( ; e != INVALID; ++e) {
kpeter@2575
   390
          if ((curr = _ns._state[e] * _ns._red_cost[e]) < 0) {
kpeter@2575
   391
            _candidates.push_back(e);
kpeter@2575
   392
            if (curr < min) {
kpeter@2575
   393
              min = curr;
kpeter@2575
   394
              _ns._in_edge = e;
kpeter@2575
   395
            }
kpeter@2575
   396
            if (int(_candidates.size()) == _list_length) break;
kpeter@2575
   397
          }
kpeter@2575
   398
        }
kpeter@2575
   399
        if (int(_candidates.size()) < _list_length) {
kpeter@2575
   400
          for (e = EdgeIt(_ns._graph); e != _next_edge; ++e) {
kpeter@2575
   401
            if ((curr = _ns._state[e] * _ns._red_cost[e]) < 0) {
kpeter@2575
   402
              _candidates.push_back(e);
kpeter@2575
   403
              if (curr < min) {
kpeter@2575
   404
                min = curr;
kpeter@2575
   405
                _ns._in_edge = e;
kpeter@2575
   406
              }
kpeter@2575
   407
              if (int(_candidates.size()) == _list_length) break;
kpeter@2575
   408
            }
kpeter@2575
   409
          }
kpeter@2575
   410
        }
kpeter@2575
   411
        if (_candidates.size() == 0) return false;
kpeter@2575
   412
        _minor_count = 1;
kpeter@2575
   413
        _next_edge = ++e;
kpeter@2575
   414
        return true;
kpeter@2575
   415
      }
kpeter@2575
   416
    }; //class CandidateListPivotRule
kpeter@2575
   417
kpeter@2575
   418
  private:
kpeter@2575
   419
kpeter@2579
   420
    // State constants for edges
kpeter@2579
   421
    enum EdgeStateEnum {
kpeter@2579
   422
      STATE_UPPER = -1,
kpeter@2579
   423
      STATE_TREE  =  0,
kpeter@2579
   424
      STATE_LOWER =  1
kpeter@2579
   425
    };
kpeter@2575
   426
kpeter@2575
   427
    // Constant for the combined pivot rule.
kpeter@2575
   428
    static const int COMBINED_PIVOT_MAX_DEG = 5;
kpeter@2575
   429
kpeter@2575
   430
  private:
kpeter@2575
   431
kpeter@2575
   432
    // The directed graph the algorithm runs on
kpeter@2575
   433
    SGraph _graph;
kpeter@2575
   434
    // The original graph
kpeter@2575
   435
    const Graph &_graph_ref;
kpeter@2575
   436
    // The original lower bound map
kpeter@2575
   437
    const LowerMap *_lower;
kpeter@2575
   438
    // The capacity map
kpeter@2575
   439
    SCapacityMap _capacity;
kpeter@2575
   440
    // The cost map
kpeter@2575
   441
    SCostMap _cost;
kpeter@2575
   442
    // The supply map
kpeter@2575
   443
    SSupplyMap _supply;
kpeter@2575
   444
    bool _valid_supply;
kpeter@2575
   445
kpeter@2575
   446
    // Edge map of the current flow
kpeter@2575
   447
    SCapacityMap _flow;
kpeter@2575
   448
    // Node map of the current potentials
kpeter@2575
   449
    SPotentialMap _potential;
kpeter@2575
   450
kpeter@2575
   451
    // The depth node map of the spanning tree structure
kpeter@2575
   452
    IntNodeMap _depth;
kpeter@2575
   453
    // The parent node map of the spanning tree structure
kpeter@2575
   454
    NodeNodeMap _parent;
kpeter@2575
   455
    // The pred_edge node map of the spanning tree structure
kpeter@2575
   456
    EdgeNodeMap _pred_edge;
kpeter@2575
   457
    // The thread node map of the spanning tree structure
kpeter@2575
   458
    NodeNodeMap _thread;
kpeter@2575
   459
    // The forward node map of the spanning tree structure
kpeter@2575
   460
    BoolNodeMap _forward;
kpeter@2575
   461
    // The state edge map
kpeter@2575
   462
    IntEdgeMap _state;
kpeter@2575
   463
    // The root node of the starting spanning tree
kpeter@2575
   464
    Node _root;
kpeter@2575
   465
kpeter@2575
   466
    // The reduced cost map
kpeter@2575
   467
    ReducedCostMap _red_cost;
kpeter@2575
   468
kpeter@2575
   469
    // Members for handling the original graph
kpeter@2581
   470
    FlowMap *_flow_result;
kpeter@2581
   471
    PotentialMap *_potential_result;
kpeter@2581
   472
    bool _local_flow;
kpeter@2581
   473
    bool _local_potential;
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
kpeter@2581
   490
    /// \brief General constructor (with lower bounds).
deba@2440
   491
    ///
kpeter@2581
   492
    /// General constructor (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@2581
   509
      _flow_result(0), _potential_result(0),
kpeter@2581
   510
      _local_flow(false), _local_potential(false),
kpeter@2575
   511
      _node_ref(graph), _edge_ref(graph)
deba@2440
   512
    {
deba@2440
   513
      // Checking the sum of supply values
deba@2440
   514
      Supply sum = 0;
kpeter@2575
   515
      for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n)
kpeter@2575
   516
        sum += supply[n];
kpeter@2575
   517
      if (!(_valid_supply = sum == 0)) return;
deba@2440
   518
kpeter@2575
   519
      // Copying _graph_ref to _graph
kpeter@2575
   520
      _graph.reserveNode(countNodes(_graph_ref) + 1);
kpeter@2575
   521
      _graph.reserveEdge(countEdges(_graph_ref) + countNodes(_graph_ref));
kpeter@2575
   522
      copyGraph(_graph, _graph_ref)
kpeter@2575
   523
        .edgeMap(_cost, cost)
kpeter@2575
   524
        .nodeRef(_node_ref)
kpeter@2575
   525
        .edgeRef(_edge_ref)
kpeter@2556
   526
        .run();
deba@2440
   527
kpeter@2556
   528
      // Removing non-zero lower bounds
kpeter@2575
   529
      for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e) {
kpeter@2575
   530
        _capacity[_edge_ref[e]] = capacity[e] - lower[e];
deba@2440
   531
      }
kpeter@2575
   532
      for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n) {
kpeter@2575
   533
        Supply s = supply[n];
kpeter@2575
   534
        for (typename Graph::InEdgeIt e(_graph_ref, n); e != INVALID; ++e)
kpeter@2575
   535
          s += lower[e];
kpeter@2575
   536
        for (typename Graph::OutEdgeIt e(_graph_ref, n); e != INVALID; ++e)
kpeter@2575
   537
          s -= lower[e];
kpeter@2575
   538
        _supply[_node_ref[n]] = s;
deba@2440
   539
      }
deba@2440
   540
    }
deba@2440
   541
kpeter@2581
   542
    /// \brief General constructor (without lower bounds).
deba@2440
   543
    ///
kpeter@2581
   544
    /// General constructor (without lower bounds).
deba@2440
   545
    ///
kpeter@2575
   546
    /// \param graph The directed graph the algorithm runs on.
kpeter@2575
   547
    /// \param capacity The capacities (upper bounds) of the edges.
kpeter@2575
   548
    /// \param cost The cost (length) values of the edges.
kpeter@2575
   549
    /// \param supply The supply values of the nodes (signed).
kpeter@2575
   550
    NetworkSimplex( const Graph &graph,
kpeter@2575
   551
                    const CapacityMap &capacity,
kpeter@2575
   552
                    const CostMap &cost,
kpeter@2575
   553
                    const SupplyMap &supply ) :
kpeter@2575
   554
      _graph(), _graph_ref(graph), _lower(NULL), _capacity(_graph),
kpeter@2575
   555
      _cost(_graph), _supply(_graph), _flow(_graph),
kpeter@2575
   556
      _potential(_graph), _depth(_graph), _parent(_graph),
kpeter@2575
   557
      _pred_edge(_graph), _thread(_graph), _forward(_graph),
kpeter@2575
   558
      _state(_graph), _red_cost(_graph, _cost, _potential),
kpeter@2581
   559
      _flow_result(0), _potential_result(0),
kpeter@2581
   560
      _local_flow(false), _local_potential(false),
kpeter@2575
   561
      _node_ref(graph), _edge_ref(graph)
deba@2440
   562
    {
deba@2440
   563
      // Checking the sum of supply values
deba@2440
   564
      Supply sum = 0;
kpeter@2575
   565
      for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n)
kpeter@2575
   566
        sum += supply[n];
kpeter@2575
   567
      if (!(_valid_supply = sum == 0)) return;
deba@2440
   568
kpeter@2575
   569
      // Copying _graph_ref to graph
kpeter@2575
   570
      copyGraph(_graph, _graph_ref)
kpeter@2575
   571
        .edgeMap(_capacity, capacity)
kpeter@2575
   572
        .edgeMap(_cost, cost)
kpeter@2575
   573
        .nodeMap(_supply, supply)
kpeter@2575
   574
        .nodeRef(_node_ref)
kpeter@2575
   575
        .edgeRef(_edge_ref)
kpeter@2556
   576
        .run();
deba@2440
   577
    }
deba@2440
   578
kpeter@2581
   579
    /// \brief Simple constructor (with lower bounds).
deba@2440
   580
    ///
kpeter@2581
   581
    /// Simple constructor (with lower bounds).
deba@2440
   582
    ///
kpeter@2575
   583
    /// \param graph The directed graph the algorithm runs on.
kpeter@2575
   584
    /// \param lower The lower bounds of the edges.
kpeter@2575
   585
    /// \param capacity The capacities (upper bounds) of the edges.
kpeter@2575
   586
    /// \param cost The cost (length) values of the edges.
kpeter@2575
   587
    /// \param s The source node.
kpeter@2575
   588
    /// \param t The target node.
kpeter@2575
   589
    /// \param flow_value The required amount of flow from node \c s
kpeter@2575
   590
    /// to node \c t (i.e. the supply of \c s and the demand of \c t).
kpeter@2575
   591
    NetworkSimplex( const Graph &graph,
kpeter@2575
   592
                    const LowerMap &lower,
kpeter@2575
   593
                    const CapacityMap &capacity,
kpeter@2575
   594
                    const CostMap &cost,
kpeter@2575
   595
                    typename Graph::Node s,
kpeter@2575
   596
                    typename Graph::Node t,
kpeter@2575
   597
                    typename SupplyMap::Value flow_value ) :
kpeter@2575
   598
      _graph(), _graph_ref(graph), _lower(&lower), _capacity(_graph),
kpeter@2575
   599
      _cost(_graph), _supply(_graph), _flow(_graph),
kpeter@2575
   600
      _potential(_graph), _depth(_graph), _parent(_graph),
kpeter@2575
   601
      _pred_edge(_graph), _thread(_graph), _forward(_graph),
kpeter@2575
   602
      _state(_graph), _red_cost(_graph, _cost, _potential),
kpeter@2581
   603
      _flow_result(0), _potential_result(0),
kpeter@2581
   604
      _local_flow(false), _local_potential(false),
kpeter@2575
   605
      _node_ref(graph), _edge_ref(graph)
deba@2440
   606
    {
kpeter@2575
   607
      // Copying _graph_ref to graph
kpeter@2575
   608
      copyGraph(_graph, _graph_ref)
kpeter@2575
   609
        .edgeMap(_cost, cost)
kpeter@2575
   610
        .nodeRef(_node_ref)
kpeter@2575
   611
        .edgeRef(_edge_ref)
kpeter@2556
   612
        .run();
deba@2440
   613
kpeter@2556
   614
      // Removing non-zero lower bounds
kpeter@2575
   615
      for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e) {
kpeter@2575
   616
        _capacity[_edge_ref[e]] = capacity[e] - lower[e];
deba@2440
   617
      }
kpeter@2575
   618
      for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n) {
kpeter@2575
   619
        Supply sum = 0;
kpeter@2575
   620
        if (n == s) sum =  flow_value;
kpeter@2575
   621
        if (n == t) sum = -flow_value;
kpeter@2575
   622
        for (typename Graph::InEdgeIt e(_graph_ref, n); e != INVALID; ++e)
kpeter@2575
   623
          sum += lower[e];
kpeter@2575
   624
        for (typename Graph::OutEdgeIt e(_graph_ref, n); e != INVALID; ++e)
kpeter@2575
   625
          sum -= lower[e];
kpeter@2575
   626
        _supply[_node_ref[n]] = sum;
deba@2440
   627
      }
kpeter@2575
   628
      _valid_supply = true;
deba@2440
   629
    }
deba@2440
   630
kpeter@2581
   631
    /// \brief Simple constructor (without lower bounds).
deba@2440
   632
    ///
kpeter@2581
   633
    /// Simple constructor (without lower bounds).
deba@2440
   634
    ///
kpeter@2575
   635
    /// \param graph The directed graph the algorithm runs on.
kpeter@2575
   636
    /// \param capacity The capacities (upper bounds) of the edges.
kpeter@2575
   637
    /// \param cost The cost (length) values of the edges.
kpeter@2575
   638
    /// \param s The source node.
kpeter@2575
   639
    /// \param t The target node.
kpeter@2575
   640
    /// \param flow_value The required amount of flow from node \c s
kpeter@2575
   641
    /// to node \c t (i.e. the supply of \c s and the demand of \c t).
kpeter@2575
   642
    NetworkSimplex( const Graph &graph,
kpeter@2575
   643
                    const CapacityMap &capacity,
kpeter@2575
   644
                    const CostMap &cost,
kpeter@2575
   645
                    typename Graph::Node s,
kpeter@2575
   646
                    typename Graph::Node t,
kpeter@2575
   647
                    typename SupplyMap::Value flow_value ) :
kpeter@2575
   648
      _graph(), _graph_ref(graph), _lower(NULL), _capacity(_graph),
kpeter@2575
   649
      _cost(_graph), _supply(_graph, 0), _flow(_graph),
kpeter@2575
   650
      _potential(_graph), _depth(_graph), _parent(_graph),
kpeter@2575
   651
      _pred_edge(_graph), _thread(_graph), _forward(_graph),
kpeter@2575
   652
      _state(_graph), _red_cost(_graph, _cost, _potential),
kpeter@2581
   653
      _flow_result(0), _potential_result(0),
kpeter@2581
   654
      _local_flow(false), _local_potential(false),
kpeter@2575
   655
      _node_ref(graph), _edge_ref(graph)
deba@2440
   656
    {
kpeter@2575
   657
      // Copying _graph_ref to graph
kpeter@2575
   658
      copyGraph(_graph, _graph_ref)
kpeter@2575
   659
        .edgeMap(_capacity, capacity)
kpeter@2575
   660
        .edgeMap(_cost, cost)
kpeter@2575
   661
        .nodeRef(_node_ref)
kpeter@2575
   662
        .edgeRef(_edge_ref)
kpeter@2556
   663
        .run();
kpeter@2575
   664
      _supply[_node_ref[s]] =  flow_value;
kpeter@2575
   665
      _supply[_node_ref[t]] = -flow_value;
kpeter@2575
   666
      _valid_supply = true;
deba@2440
   667
    }
deba@2440
   668
kpeter@2581
   669
    /// Destructor.
kpeter@2581
   670
    ~NetworkSimplex() {
kpeter@2581
   671
      if (_local_flow) delete _flow_result;
kpeter@2581
   672
      if (_local_potential) delete _potential_result;
kpeter@2581
   673
    }
kpeter@2581
   674
kpeter@2581
   675
    /// \brief Sets the flow map.
kpeter@2581
   676
    ///
kpeter@2581
   677
    /// Sets the flow map.
kpeter@2581
   678
    ///
kpeter@2581
   679
    /// \return \c (*this)
kpeter@2581
   680
    NetworkSimplex& flowMap(FlowMap &map) {
kpeter@2581
   681
      if (_local_flow) {
kpeter@2581
   682
        delete _flow_result;
kpeter@2581
   683
        _local_flow = false;
kpeter@2581
   684
      }
kpeter@2581
   685
      _flow_result = &map;
kpeter@2581
   686
      return *this;
kpeter@2581
   687
    }
kpeter@2581
   688
kpeter@2581
   689
    /// \brief Sets the potential map.
kpeter@2581
   690
    ///
kpeter@2581
   691
    /// Sets the potential map.
kpeter@2581
   692
    ///
kpeter@2581
   693
    /// \return \c (*this)
kpeter@2581
   694
    NetworkSimplex& potentialMap(PotentialMap &map) {
kpeter@2581
   695
      if (_local_potential) {
kpeter@2581
   696
        delete _potential_result;
kpeter@2581
   697
        _local_potential = false;
kpeter@2581
   698
      }
kpeter@2581
   699
      _potential_result = &map;
kpeter@2581
   700
      return *this;
kpeter@2581
   701
    }
kpeter@2581
   702
kpeter@2581
   703
    /// \name Execution control
kpeter@2581
   704
    /// The only way to execute the algorithm is to call the run()
kpeter@2581
   705
    /// function.
kpeter@2581
   706
kpeter@2581
   707
    /// @{
kpeter@2581
   708
kpeter@2556
   709
    /// \brief Runs the algorithm.
kpeter@2556
   710
    ///
kpeter@2556
   711
    /// Runs the algorithm.
kpeter@2556
   712
    ///
kpeter@2575
   713
    /// \param pivot_rule The pivot rule that is used during the
kpeter@2575
   714
    /// algorithm.
kpeter@2575
   715
    ///
kpeter@2575
   716
    /// The available pivot rules:
kpeter@2575
   717
    ///
kpeter@2575
   718
    /// - FIRST_ELIGIBLE_PIVOT The next eligible edge is selected in
kpeter@2575
   719
    /// a wraparound fashion in every iteration
kpeter@2575
   720
    /// (\ref FirstEligiblePivotRule).
kpeter@2575
   721
    ///
kpeter@2575
   722
    /// - BEST_ELIGIBLE_PIVOT The best eligible edge is selected in
kpeter@2575
   723
    /// every iteration (\ref BestEligiblePivotRule).
kpeter@2575
   724
    ///
kpeter@2575
   725
    /// - BLOCK_SEARCH_PIVOT A specified number of edges are examined in
kpeter@2575
   726
    /// every iteration in a wraparound fashion and the best eligible
kpeter@2575
   727
    /// edge is selected from this block (\ref BlockSearchPivotRule).
kpeter@2575
   728
    ///
kpeter@2575
   729
    /// - LIMITED_SEARCH_PIVOT A specified number of eligible edges are
kpeter@2575
   730
    /// examined in every iteration in a wraparound fashion and the best
kpeter@2575
   731
    /// one is selected from them (\ref LimitedSearchPivotRule).
kpeter@2575
   732
    ///
kpeter@2575
   733
    /// - CANDIDATE_LIST_PIVOT In major iterations a candidate list is
kpeter@2575
   734
    /// built from eligible edges and it is used for edge selection in
kpeter@2575
   735
    /// the following minor iterations (\ref CandidateListPivotRule).
kpeter@2575
   736
    ///
kpeter@2575
   737
    /// - COMBINED_PIVOT This is a combined version of the two fastest
kpeter@2575
   738
    /// pivot rules.
kpeter@2575
   739
    /// For rather sparse graphs \ref LimitedSearchPivotRule
kpeter@2575
   740
    /// "Limited Search" implementation is used, otherwise
kpeter@2575
   741
    /// \ref BlockSearchPivotRule "Block Search" pivot rule is used.
kpeter@2575
   742
    /// According to our benchmark tests this combined method is the
kpeter@2575
   743
    /// most efficient.
kpeter@2575
   744
    ///
kpeter@2556
   745
    /// \return \c true if a feasible flow can be found.
kpeter@2575
   746
    bool run(PivotRuleEnum pivot_rule = COMBINED_PIVOT) {
kpeter@2575
   747
      return init() && start(pivot_rule);
kpeter@2556
   748
    }
kpeter@2556
   749
kpeter@2581
   750
    /// @}
kpeter@2581
   751
kpeter@2581
   752
    /// \name Query Functions
kpeter@2581
   753
    /// The result of the algorithm can be obtained using these
kpeter@2581
   754
    /// functions.
kpeter@2581
   755
    /// \n run() must be called before using them.
kpeter@2581
   756
kpeter@2581
   757
    /// @{
kpeter@2581
   758
kpeter@2575
   759
    /// \brief Returns a const reference to the edge map storing the
kpeter@2575
   760
    /// found flow.
deba@2440
   761
    ///
kpeter@2575
   762
    /// Returns a const reference to the edge map storing the found flow.
deba@2440
   763
    ///
deba@2440
   764
    /// \pre \ref run() must be called before using this function.
deba@2440
   765
    const FlowMap& flowMap() const {
kpeter@2581
   766
      return *_flow_result;
deba@2440
   767
    }
deba@2440
   768
kpeter@2575
   769
    /// \brief Returns a const reference to the node map storing the
kpeter@2575
   770
    /// found potentials (the dual solution).
deba@2440
   771
    ///
kpeter@2575
   772
    /// Returns a const reference to the node map storing the found
kpeter@2575
   773
    /// potentials (the dual solution).
deba@2440
   774
    ///
deba@2440
   775
    /// \pre \ref run() must be called before using this function.
deba@2440
   776
    const PotentialMap& potentialMap() const {
kpeter@2581
   777
      return *_potential_result;
kpeter@2581
   778
    }
kpeter@2581
   779
kpeter@2588
   780
    /// \brief Returns the flow on the given edge.
kpeter@2581
   781
    ///
kpeter@2588
   782
    /// Returns the flow on the given edge.
kpeter@2581
   783
    ///
kpeter@2581
   784
    /// \pre \ref run() must be called before using this function.
kpeter@2581
   785
    Capacity flow(const typename Graph::Edge& edge) const {
kpeter@2581
   786
      return (*_flow_result)[edge];
kpeter@2581
   787
    }
kpeter@2581
   788
kpeter@2588
   789
    /// \brief Returns the potential of the given node.
kpeter@2581
   790
    ///
kpeter@2588
   791
    /// Returns the potential of the given node.
kpeter@2581
   792
    ///
kpeter@2581
   793
    /// \pre \ref run() must be called before using this function.
kpeter@2581
   794
    Cost potential(const typename Graph::Node& node) const {
kpeter@2581
   795
      return (*_potential_result)[node];
deba@2440
   796
    }
deba@2440
   797
deba@2440
   798
    /// \brief Returns the total cost of the found flow.
deba@2440
   799
    ///
deba@2440
   800
    /// Returns the total cost of the found flow. The complexity of the
deba@2440
   801
    /// function is \f$ O(e) \f$.
deba@2440
   802
    ///
deba@2440
   803
    /// \pre \ref run() must be called before using this function.
deba@2440
   804
    Cost totalCost() const {
deba@2440
   805
      Cost c = 0;
kpeter@2575
   806
      for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e)
kpeter@2581
   807
        c += (*_flow_result)[e] * _cost[_edge_ref[e]];
deba@2440
   808
      return c;
deba@2440
   809
    }
deba@2440
   810
kpeter@2581
   811
    /// @}
kpeter@2581
   812
kpeter@2575
   813
  private:
deba@2440
   814
deba@2440
   815
    /// \brief Extends the underlaying graph and initializes all the
deba@2440
   816
    /// node and edge maps.
deba@2440
   817
    bool init() {
kpeter@2575
   818
      if (!_valid_supply) return false;
deba@2440
   819
kpeter@2581
   820
      // Initializing result maps
kpeter@2581
   821
      if (!_flow_result) {
kpeter@2581
   822
        _flow_result = new FlowMap(_graph_ref);
kpeter@2581
   823
        _local_flow = true;
kpeter@2581
   824
      }
kpeter@2581
   825
      if (!_potential_result) {
kpeter@2581
   826
        _potential_result = new PotentialMap(_graph_ref);
kpeter@2581
   827
        _local_potential = true;
kpeter@2581
   828
      }
kpeter@2581
   829
deba@2440
   830
      // Initializing state and flow maps
kpeter@2575
   831
      for (EdgeIt e(_graph); e != INVALID; ++e) {
kpeter@2575
   832
        _flow[e] = 0;
kpeter@2575
   833
        _state[e] = STATE_LOWER;
deba@2440
   834
      }
deba@2440
   835
deba@2440
   836
      // Adding an artificial root node to the graph
kpeter@2575
   837
      _root = _graph.addNode();
kpeter@2575
   838
      _parent[_root] = INVALID;
kpeter@2575
   839
      _pred_edge[_root] = INVALID;
kpeter@2575
   840
      _depth[_root] = 0;
kpeter@2575
   841
      _supply[_root] = 0;
kpeter@2575
   842
      _potential[_root] = 0;
deba@2440
   843
deba@2440
   844
      // Adding artificial edges to the graph and initializing the node
deba@2440
   845
      // maps of the spanning tree data structure
kpeter@2575
   846
      Node last = _root;
deba@2440
   847
      Edge e;
deba@2440
   848
      Cost max_cost = std::numeric_limits<Cost>::max() / 4;
kpeter@2575
   849
      for (NodeIt u(_graph); u != INVALID; ++u) {
kpeter@2575
   850
        if (u == _root) continue;
kpeter@2575
   851
        _thread[last] = u;
kpeter@2556
   852
        last = u;
kpeter@2575
   853
        _parent[u] = _root;
kpeter@2575
   854
        _depth[u] = 1;
kpeter@2575
   855
        if (_supply[u] >= 0) {
kpeter@2575
   856
          e = _graph.addEdge(u, _root);
kpeter@2575
   857
          _flow[e] = _supply[u];
kpeter@2575
   858
          _forward[u] = true;
kpeter@2575
   859
          _potential[u] = -max_cost;
kpeter@2556
   860
        } else {
kpeter@2575
   861
          e = _graph.addEdge(_root, u);
kpeter@2575
   862
          _flow[e] = -_supply[u];
kpeter@2575
   863
          _forward[u] = false;
kpeter@2575
   864
          _potential[u] = max_cost;
kpeter@2556
   865
        }
kpeter@2575
   866
        _cost[e] = max_cost;
kpeter@2575
   867
        _capacity[e] = std::numeric_limits<Capacity>::max();
kpeter@2575
   868
        _state[e] = STATE_TREE;
kpeter@2575
   869
        _pred_edge[u] = e;
deba@2440
   870
      }
kpeter@2575
   871
      _thread[last] = _root;
deba@2440
   872
kpeter@2575
   873
      return true;
deba@2440
   874
    }
deba@2440
   875
kpeter@2575
   876
    /// Finds the join node.
kpeter@2575
   877
    Node findJoinNode() {
kpeter@2575
   878
      Node u = _graph.source(_in_edge);
kpeter@2575
   879
      Node v = _graph.target(_in_edge);
kpeter@2575
   880
      while (u != v) {
kpeter@2575
   881
        if (_depth[u] == _depth[v]) {
kpeter@2575
   882
          u = _parent[u];
kpeter@2575
   883
          v = _parent[v];
kpeter@2556
   884
        }
kpeter@2575
   885
        else if (_depth[u] > _depth[v]) u = _parent[u];
kpeter@2575
   886
        else v = _parent[v];
deba@2440
   887
      }
deba@2440
   888
      return u;
deba@2440
   889
    }
deba@2440
   890
deba@2440
   891
    /// \brief Finds the leaving edge of the cycle. Returns \c true if
deba@2440
   892
    /// the leaving edge is not the same as the entering edge.
deba@2440
   893
    bool findLeavingEdge() {
deba@2440
   894
      // Initializing first and second nodes according to the direction
deba@2440
   895
      // of the cycle
kpeter@2575
   896
      if (_state[_in_edge] == STATE_LOWER) {
kpeter@2575
   897
        first  = _graph.source(_in_edge);
kpeter@2575
   898
        second = _graph.target(_in_edge);
deba@2440
   899
      } else {
kpeter@2575
   900
        first  = _graph.target(_in_edge);
kpeter@2575
   901
        second = _graph.source(_in_edge);
deba@2440
   902
      }
kpeter@2575
   903
      delta = _capacity[_in_edge];
deba@2440
   904
      bool result = false;
deba@2440
   905
      Capacity d;
deba@2440
   906
      Edge e;
deba@2440
   907
deba@2440
   908
      // Searching the cycle along the path form the first node to the
deba@2440
   909
      // root node
kpeter@2575
   910
      for (Node u = first; u != join; u = _parent[u]) {
kpeter@2575
   911
        e = _pred_edge[u];
kpeter@2575
   912
        d = _forward[u] ? _flow[e] : _capacity[e] - _flow[e];
kpeter@2556
   913
        if (d < delta) {
kpeter@2556
   914
          delta = d;
kpeter@2556
   915
          u_out = u;
kpeter@2556
   916
          u_in = first;
kpeter@2556
   917
          v_in = second;
kpeter@2556
   918
          result = true;
kpeter@2556
   919
        }
deba@2440
   920
      }
deba@2440
   921
      // Searching the cycle along the path form the second node to the
deba@2440
   922
      // root node
kpeter@2575
   923
      for (Node u = second; u != join; u = _parent[u]) {
kpeter@2575
   924
        e = _pred_edge[u];
kpeter@2575
   925
        d = _forward[u] ? _capacity[e] - _flow[e] : _flow[e];
kpeter@2556
   926
        if (d <= delta) {
kpeter@2556
   927
          delta = d;
kpeter@2556
   928
          u_out = u;
kpeter@2556
   929
          u_in = second;
kpeter@2556
   930
          v_in = first;
kpeter@2556
   931
          result = true;
kpeter@2556
   932
        }
deba@2440
   933
      }
deba@2440
   934
      return result;
deba@2440
   935
    }
deba@2440
   936
kpeter@2575
   937
    /// Changes \c flow and \c state edge maps.
deba@2440
   938
    void changeFlows(bool change) {
deba@2440
   939
      // Augmenting along the cycle
deba@2440
   940
      if (delta > 0) {
kpeter@2575
   941
        Capacity val = _state[_in_edge] * delta;
kpeter@2575
   942
        _flow[_in_edge] += val;
kpeter@2575
   943
        for (Node u = _graph.source(_in_edge); u != join; u = _parent[u]) {
kpeter@2575
   944
          _flow[_pred_edge[u]] += _forward[u] ? -val : val;
kpeter@2556
   945
        }
kpeter@2575
   946
        for (Node u = _graph.target(_in_edge); u != join; u = _parent[u]) {
kpeter@2575
   947
          _flow[_pred_edge[u]] += _forward[u] ? val : -val;
kpeter@2556
   948
        }
deba@2440
   949
      }
deba@2440
   950
      // Updating the state of the entering and leaving edges
deba@2440
   951
      if (change) {
kpeter@2575
   952
        _state[_in_edge] = STATE_TREE;
kpeter@2575
   953
        _state[_pred_edge[u_out]] =
kpeter@2575
   954
          (_flow[_pred_edge[u_out]] == 0) ? STATE_LOWER : STATE_UPPER;
deba@2440
   955
      } else {
kpeter@2575
   956
        _state[_in_edge] = -_state[_in_edge];
deba@2440
   957
      }
deba@2440
   958
    }
deba@2440
   959
kpeter@2575
   960
    /// Updates \c thread and \c parent node maps.
deba@2440
   961
    void updateThreadParent() {
deba@2440
   962
      Node u;
kpeter@2575
   963
      v_out = _parent[u_out];
deba@2440
   964
deba@2440
   965
      // Handling the case when join and v_out coincide
deba@2440
   966
      bool par_first = false;
deba@2440
   967
      if (join == v_out) {
kpeter@2575
   968
        for (u = join; u != u_in && u != v_in; u = _thread[u]) ;
kpeter@2556
   969
        if (u == v_in) {
kpeter@2556
   970
          par_first = true;
kpeter@2575
   971
          while (_thread[u] != u_out) u = _thread[u];
kpeter@2556
   972
          first = u;
kpeter@2556
   973
        }
deba@2440
   974
      }
deba@2440
   975
deba@2440
   976
      // Finding the last successor of u_in (u) and the node after it
deba@2440
   977
      // (right) according to the thread index
kpeter@2575
   978
      for (u = u_in; _depth[_thread[u]] > _depth[u_in]; u = _thread[u]) ;
kpeter@2575
   979
      right = _thread[u];
kpeter@2575
   980
      if (_thread[v_in] == u_out) {
kpeter@2575
   981
        for (last = u; _depth[last] > _depth[u_out]; last = _thread[last]) ;
kpeter@2575
   982
        if (last == u_out) last = _thread[last];
deba@2440
   983
      }
kpeter@2575
   984
      else last = _thread[v_in];
deba@2440
   985
deba@2440
   986
      // Updating stem nodes
kpeter@2575
   987
      _thread[v_in] = stem = u_in;
deba@2440
   988
      par_stem = v_in;
deba@2440
   989
      while (stem != u_out) {
kpeter@2575
   990
        _thread[u] = new_stem = _parent[stem];
deba@2440
   991
kpeter@2556
   992
        // Finding the node just before the stem node (u) according to
kpeter@2556
   993
        // the original thread index
kpeter@2575
   994
        for (u = new_stem; _thread[u] != stem; u = _thread[u]) ;
kpeter@2575
   995
        _thread[u] = right;
deba@2440
   996
kpeter@2556
   997
        // Changing the parent node of stem and shifting stem and
kpeter@2556
   998
        // par_stem nodes
kpeter@2575
   999
        _parent[stem] = par_stem;
kpeter@2556
  1000
        par_stem = stem;
kpeter@2556
  1001
        stem = new_stem;
deba@2440
  1002
kpeter@2556
  1003
        // Finding the last successor of stem (u) and the node after it
kpeter@2556
  1004
        // (right) according to the thread index
kpeter@2575
  1005
        for (u = stem; _depth[_thread[u]] > _depth[stem]; u = _thread[u]) ;
kpeter@2575
  1006
        right = _thread[u];
deba@2440
  1007
      }
kpeter@2575
  1008
      _parent[u_out] = par_stem;
kpeter@2575
  1009
      _thread[u] = last;
deba@2440
  1010
deba@2440
  1011
      if (join == v_out && par_first) {
kpeter@2575
  1012
        if (first != v_in) _thread[first] = right;
deba@2440
  1013
      } else {
kpeter@2575
  1014
        for (u = v_out; _thread[u] != u_out; u = _thread[u]) ;
kpeter@2575
  1015
        _thread[u] = right;
deba@2440
  1016
      }
deba@2440
  1017
    }
deba@2440
  1018
kpeter@2575
  1019
    /// Updates \c pred_edge and \c forward node maps.
deba@2440
  1020
    void updatePredEdge() {
deba@2440
  1021
      Node u = u_out, v;
deba@2440
  1022
      while (u != u_in) {
kpeter@2575
  1023
        v = _parent[u];
kpeter@2575
  1024
        _pred_edge[u] = _pred_edge[v];
kpeter@2575
  1025
        _forward[u] = !_forward[v];
kpeter@2556
  1026
        u = v;
deba@2440
  1027
      }
kpeter@2575
  1028
      _pred_edge[u_in] = _in_edge;
kpeter@2575
  1029
      _forward[u_in] = (u_in == _graph.source(_in_edge));
deba@2440
  1030
    }
deba@2440
  1031
kpeter@2575
  1032
    /// Updates \c depth and \c potential node maps.
deba@2440
  1033
    void updateDepthPotential() {
kpeter@2575
  1034
      _depth[u_in] = _depth[v_in] + 1;
kpeter@2575
  1035
      _potential[u_in] = _forward[u_in] ?
kpeter@2575
  1036
        _potential[v_in] - _cost[_pred_edge[u_in]] :
kpeter@2575
  1037
        _potential[v_in] + _cost[_pred_edge[u_in]];
deba@2440
  1038
kpeter@2575
  1039
      Node u = _thread[u_in], v;
deba@2440
  1040
      while (true) {
kpeter@2575
  1041
        v = _parent[u];
kpeter@2556
  1042
        if (v == INVALID) break;
kpeter@2575
  1043
        _depth[u] = _depth[v] + 1;
kpeter@2575
  1044
        _potential[u] = _forward[u] ?
kpeter@2575
  1045
          _potential[v] - _cost[_pred_edge[u]] :
kpeter@2575
  1046
          _potential[v] + _cost[_pred_edge[u]];
kpeter@2575
  1047
        if (_depth[u] <= _depth[v_in]) break;
kpeter@2575
  1048
        u = _thread[u];
deba@2440
  1049
      }
deba@2440
  1050
    }
deba@2440
  1051
kpeter@2575
  1052
    /// Executes the algorithm.
kpeter@2575
  1053
    bool start(PivotRuleEnum pivot_rule) {
kpeter@2575
  1054
      switch (pivot_rule) {
kpeter@2575
  1055
        case FIRST_ELIGIBLE_PIVOT:
kpeter@2575
  1056
          return start<FirstEligiblePivotRule>();
kpeter@2575
  1057
        case BEST_ELIGIBLE_PIVOT:
kpeter@2575
  1058
          return start<BestEligiblePivotRule>();
kpeter@2575
  1059
        case BLOCK_SEARCH_PIVOT:
kpeter@2575
  1060
          return start<BlockSearchPivotRule>();
kpeter@2575
  1061
        case LIMITED_SEARCH_PIVOT:
kpeter@2575
  1062
          return start<LimitedSearchPivotRule>();
kpeter@2575
  1063
        case CANDIDATE_LIST_PIVOT:
kpeter@2575
  1064
          return start<CandidateListPivotRule>();
kpeter@2575
  1065
        case COMBINED_PIVOT:
kpeter@2575
  1066
          if ( countEdges(_graph) / countNodes(_graph) <=
kpeter@2575
  1067
               COMBINED_PIVOT_MAX_DEG )
kpeter@2575
  1068
            return start<LimitedSearchPivotRule>();
kpeter@2575
  1069
          else
kpeter@2575
  1070
            return start<BlockSearchPivotRule>();
kpeter@2575
  1071
      }
kpeter@2575
  1072
      return false;
kpeter@2575
  1073
    }
kpeter@2575
  1074
kpeter@2575
  1075
    template<class PivotRuleImplementation>
deba@2440
  1076
    bool start() {
kpeter@2575
  1077
      PivotRuleImplementation pivot(*this);
kpeter@2575
  1078
kpeter@2575
  1079
      // Executing the network simplex algorithm
kpeter@2575
  1080
      while (pivot.findEnteringEdge()) {
kpeter@2556
  1081
        join = findJoinNode();
kpeter@2556
  1082
        bool change = findLeavingEdge();
kpeter@2556
  1083
        changeFlows(change);
kpeter@2556
  1084
        if (change) {
kpeter@2556
  1085
          updateThreadParent();
kpeter@2556
  1086
          updatePredEdge();
kpeter@2556
  1087
          updateDepthPotential();
kpeter@2556
  1088
        }
deba@2440
  1089
      }
deba@2440
  1090
kpeter@2575
  1091
      // Checking if the flow amount equals zero on all the artificial
kpeter@2575
  1092
      // edges
kpeter@2575
  1093
      for (InEdgeIt e(_graph, _root); e != INVALID; ++e)
kpeter@2575
  1094
        if (_flow[e] > 0) return false;
kpeter@2575
  1095
      for (OutEdgeIt e(_graph, _root); e != INVALID; ++e)
kpeter@2575
  1096
        if (_flow[e] > 0) return false;
deba@2440
  1097
kpeter@2575
  1098
      // Copying flow values to _flow_result
kpeter@2575
  1099
      if (_lower) {
kpeter@2575
  1100
        for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e)
kpeter@2581
  1101
          (*_flow_result)[e] = (*_lower)[e] + _flow[_edge_ref[e]];
deba@2440
  1102
      } else {
kpeter@2575
  1103
        for (typename Graph::EdgeIt e(_graph_ref); e != INVALID; ++e)
kpeter@2581
  1104
          (*_flow_result)[e] = _flow[_edge_ref[e]];
deba@2440
  1105
      }
kpeter@2575
  1106
      // Copying potential values to _potential_result
kpeter@2575
  1107
      for (typename Graph::NodeIt n(_graph_ref); n != INVALID; ++n)
kpeter@2581
  1108
        (*_potential_result)[n] = _potential[_node_ref[n]];
deba@2440
  1109
deba@2440
  1110
      return true;
deba@2440
  1111
    }
deba@2440
  1112
deba@2440
  1113
  }; //class NetworkSimplex
deba@2440
  1114
deba@2440
  1115
  ///@}
deba@2440
  1116
deba@2440
  1117
} //namespace lemon
deba@2440
  1118
deba@2440
  1119
#endif //LEMON_NETWORK_SIMPLEX_H