COIN-OR::LEMON - Graph Library

Ticket #234: ns-port-7f07ddefb52d.patch

File ns-port-7f07ddefb52d.patch, 55.0 KB (added by Peter Kovacs, 15 years ago)

The same as [697d61bb33f4] with better commit log

  • new file lemon/network_simplex.h

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

    diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
    a b  
    3030  maps_test
    3131  max_matching_test
    3232  min_cost_arborescence_test
     33  min_cost_flow_test
    3334  path_test
    3435  preflow_test
    3536  radix_sort_test
  • test/Makefile.am

    diff --git a/test/Makefile.am b/test/Makefile.am
    a b  
    2626        test/maps_test \
    2727        test/max_matching_test \
    2828        test/min_cost_arborescence_test \
     29        test/min_cost_flow_test \
    2930        test/path_test \
    3031        test/preflow_test \
    3132        test/radix_sort_test \
     
    6869test_mip_test_SOURCES = test/mip_test.cc
    6970test_max_matching_test_SOURCES = test/max_matching_test.cc
    7071test_min_cost_arborescence_test_SOURCES = test/min_cost_arborescence_test.cc
     72test_min_cost_flow_test_SOURCES = test/min_cost_flow_test.cc
    7173test_path_test_SOURCES = test/path_test.cc
    7274test_preflow_test_SOURCES = test/preflow_test.cc
    7375test_radix_sort_test_SOURCES = test/radix_sort_test.cc
  • new file test/min_cost_flow_test.cc

    diff --git a/test/min_cost_flow_test.cc b/test/min_cost_flow_test.cc
    new file mode 100644
    - +  
     1/* -*- mode: C++; indent-tabs-mode: nil; -*-
     2 *
     3 * This file is a part of LEMON, a generic C++ optimization library.
     4 *
     5 * Copyright (C) 2003-2009
     6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8 *
     9 * Permission to use, modify and distribute this software is granted
     10 * provided that this copyright notice appears in all copies. For
     11 * precise terms see the accompanying LICENSE file.
     12 *
     13 * This software is provided "AS IS" with no warranty of any kind,
     14 * express or implied, and with no claim as to its suitability for any
     15 * purpose.
     16 *
     17 */
     18
     19#include <iostream>
     20#include <fstream>
     21
     22#include <lemon/list_graph.h>
     23#include <lemon/smart_graph.h>
     24#include <lemon/lgf_reader.h>
     25
     26//#include <lemon/cycle_canceling.h>
     27//#include <lemon/capacity_scaling.h>
     28//#include <lemon/cost_scaling.h>
     29#include <lemon/network_simplex.h>
     30//#include <lemon/min_cost_flow.h>
     31//#include <lemon/min_cost_max_flow.h>
     32
     33#include <lemon/concepts/digraph.h>
     34#include <lemon/concept_check.h>
     35
     36#include "test_tools.h"
     37
     38using namespace lemon;
     39
     40char test_lgf[] =
     41  "@nodes\n"
     42  "label  sup1 sup2 sup3\n"
     43  "    1    20   27    0\n"
     44  "    2    -4    0    0\n"
     45  "    3     0    0    0\n"
     46  "    4     0    0    0\n"
     47  "    5     9    0    0\n"
     48  "    6    -6    0    0\n"
     49  "    7     0    0    0\n"
     50  "    8     0    0    0\n"
     51  "    9     3    0    0\n"
     52  "   10    -2    0    0\n"
     53  "   11     0    0    0\n"
     54  "   12   -20  -27    0\n"
     55  "\n"
     56  "@arcs\n"
     57  "       cost  cap low1 low2\n"
     58  " 1  2    70   11    0    8\n"
     59  " 1  3   150    3    0    1\n"
     60  " 1  4    80   15    0    2\n"
     61  " 2  8    80   12    0    0\n"
     62  " 3  5   140    5    0    3\n"
     63  " 4  6    60   10    0    1\n"
     64  " 4  7    80    2    0    0\n"
     65  " 4  8   110    3    0    0\n"
     66  " 5  7    60   14    0    0\n"
     67  " 5 11   120   12    0    0\n"
     68  " 6  3     0    3    0    0\n"
     69  " 6  9   140    4    0    0\n"
     70  " 6 10    90    8    0    0\n"
     71  " 7  1    30    5    0    0\n"
     72  " 8 12    60   16    0    4\n"
     73  " 9 12    50    6    0    0\n"
     74  "10 12    70   13    0    5\n"
     75  "10  2   100    7    0    0\n"
     76  "10  7    60   10    0    0\n"
     77  "11 10    20   14    0    6\n"
     78  "12 11    30   10    0    0\n"
     79  "\n"
     80  "@attributes\n"
     81  "source 1\n"
     82  "target 12\n";
     83
     84
     85// Check the interface of an MCF algorithm
     86template <typename GR, typename Value>
     87class McfClassConcept
     88{
     89public:
     90
     91  template <typename MCF>
     92  struct Constraints {
     93    void constraints() {
     94      checkConcept<concepts::Digraph, GR>();
     95
     96      MCF mcf_test1(g, lower, upper, cost, sup);
     97      MCF mcf_test2(g, upper, cost, sup);
     98      MCF mcf_test3(g, lower, upper, cost, n, n, k);
     99      MCF mcf_test4(g, upper, cost, n, n, k);
     100
     101      // TODO: This part should be enabled and the next part
     102      // should be removed if map copying is supported
     103/*
     104      flow = mcf_test1.flowMap();
     105      mcf_test1.flowMap(flow);
     106
     107      pot = mcf_test1.potentialMap();
     108      mcf_test1.potentialMap(pot);
     109*/
     110/**/
     111      const typename MCF::FlowMap &fm =
     112        mcf_test1.flowMap();
     113      mcf_test1.flowMap(flow);
     114      const typename MCF::PotentialMap &pm =
     115        mcf_test1.potentialMap();
     116      mcf_test1.potentialMap(pot);
     117      ignore_unused_variable_warning(fm);
     118      ignore_unused_variable_warning(pm);
     119/**/
     120
     121      mcf_test1.run();
     122
     123      v = mcf_test1.totalCost();
     124      v = mcf_test1.flow(a);
     125      v = mcf_test1.potential(n);
     126    }
     127
     128    typedef typename GR::Node Node;
     129    typedef typename GR::Arc Arc;
     130    typedef concepts::ReadMap<Node, Value> NM;
     131    typedef concepts::ReadMap<Arc, Value> AM;
     132
     133    const GR &g;
     134    const AM &lower;
     135    const AM &upper;
     136    const AM &cost;
     137    const NM &sup;
     138    const Node &n;
     139    const Arc &a;
     140    const Value &k;
     141    Value v;
     142
     143    typename MCF::FlowMap &flow;
     144    typename MCF::PotentialMap &pot;
     145  };
     146
     147};
     148
     149
     150// Check the feasibility of the given flow (primal soluiton)
     151template < typename GR, typename LM, typename UM,
     152           typename SM, typename FM >
     153bool checkFlow( const GR& gr, const LM& lower, const UM& upper,
     154                const SM& supply, const FM& flow )
     155{
     156  TEMPLATE_DIGRAPH_TYPEDEFS(GR);
     157
     158  for (ArcIt e(gr); e != INVALID; ++e) {
     159    if (flow[e] < lower[e] || flow[e] > upper[e]) return false;
     160  }
     161
     162  for (NodeIt n(gr); n != INVALID; ++n) {
     163    typename SM::Value sum = 0;
     164    for (OutArcIt e(gr, n); e != INVALID; ++e)
     165      sum += flow[e];
     166    for (InArcIt e(gr, n); e != INVALID; ++e)
     167      sum -= flow[e];
     168    if (sum != supply[n]) return false;
     169  }
     170
     171  return true;
     172}
     173
     174// Check the feasibility of the given potentials (dual soluiton)
     175// using the Complementary Slackness optimality condition
     176template < typename GR, typename LM, typename UM,
     177           typename CM, typename FM, typename PM >
     178bool checkPotential( const GR& gr, const LM& lower, const UM& upper,
     179                     const CM& cost, const FM& flow, const PM& pi )
     180{
     181  TEMPLATE_DIGRAPH_TYPEDEFS(GR);
     182
     183  bool opt = true;
     184  for (ArcIt e(gr); opt && e != INVALID; ++e) {
     185    typename CM::Value red_cost =
     186      cost[e] + pi[gr.source(e)] - pi[gr.target(e)];
     187    opt = red_cost == 0 ||
     188          (red_cost > 0 && flow[e] == lower[e]) ||
     189          (red_cost < 0 && flow[e] == upper[e]);
     190  }
     191  return opt;
     192}
     193
     194// Run a minimum cost flow algorithm and check the results
     195template < typename MCF, typename GR,
     196           typename LM, typename UM,
     197           typename CM, typename SM >
     198void checkMcf( const MCF& mcf, bool mcf_result,
     199               const GR& gr, const LM& lower, const UM& upper,
     200               const CM& cost, const SM& supply,
     201               bool result, typename CM::Value total,
     202               const std::string &test_id = "" )
     203{
     204  check(mcf_result == result, "Wrong result " + test_id);
     205  if (result) {
     206    check(checkFlow(gr, lower, upper, supply, mcf.flowMap()),
     207          "The flow is not feasible " + test_id);
     208    check(mcf.totalCost() == total, "The flow is not optimal " + test_id);
     209    check(checkPotential(gr, lower, upper, cost, mcf.flowMap(),
     210                         mcf.potentialMap()),
     211          "Wrong potentials " + test_id);
     212  }
     213}
     214
     215int main()
     216{
     217  // Check the interfaces
     218  {
     219    typedef int Value;
     220    // This typedef should be enabled if the standard maps are
     221    // reference maps in the graph concepts
     222    //typedef concepts::Digraph GR;
     223    typedef ListDigraph GR;
     224    typedef concepts::ReadMap<GR::Node, Value> NM;
     225    typedef concepts::ReadMap<GR::Arc, Value> AM;
     226
     227    //checkConcept< McfClassConcept<GR, Value>,
     228    //              CycleCanceling<GR, AM, AM, AM, NM> >();
     229    //checkConcept< McfClassConcept<GR, Value>,
     230    //              CapacityScaling<GR, AM, AM, AM, NM> >();
     231    //checkConcept< McfClassConcept<GR, Value>,
     232    //              CostScaling<GR, AM, AM, AM, NM> >();
     233    checkConcept< McfClassConcept<GR, Value>,
     234                  NetworkSimplex<GR, AM, AM, AM, NM> >();
     235    //checkConcept< MinCostFlow<GR, Value>,
     236    //              NetworkSimplex<GR, AM, AM, AM, NM> >();
     237  }
     238
     239  // Run various MCF tests
     240  typedef ListDigraph Digraph;
     241  DIGRAPH_TYPEDEFS(ListDigraph);
     242
     243  // Read the test digraph
     244  Digraph gr;
     245  Digraph::ArcMap<int> c(gr), l1(gr), l2(gr), u(gr);
     246  Digraph::NodeMap<int> s1(gr), s2(gr), s3(gr);
     247  Node v, w;
     248
     249  std::istringstream input(test_lgf);
     250  DigraphReader<Digraph>(gr, input)
     251    .arcMap("cost", c)
     252    .arcMap("cap", u)
     253    .arcMap("low1", l1)
     254    .arcMap("low2", l2)
     255    .nodeMap("sup1", s1)
     256    .nodeMap("sup2", s2)
     257    .nodeMap("sup3", s3)
     258    .node("source", v)
     259    .node("target", w)
     260    .run();
     261
     262/*
     263  // A. Test CapacityScaling with scaling
     264  {
     265    CapacityScaling<Digraph> mcf1(gr, u, c, s1);
     266    CapacityScaling<Digraph> mcf2(gr, u, c, v, w, 27);
     267    CapacityScaling<Digraph> mcf3(gr, u, c, s3);
     268    CapacityScaling<Digraph> mcf4(gr, l2, u, c, s1);
     269    CapacityScaling<Digraph> mcf5(gr, l2, u, c, v, w, 27);
     270    CapacityScaling<Digraph> mcf6(gr, l2, u, c, s3);
     271
     272    checkMcf(mcf1, mcf1.run(), gr, l1, u, c, s1, true,  5240, "#A1");
     273    checkMcf(mcf2, mcf2.run(), gr, l1, u, c, s2, true,  7620, "#A2");
     274    checkMcf(mcf3, mcf3.run(), gr, l1, u, c, s3, true,     0, "#A3");
     275    checkMcf(mcf4, mcf4.run(), gr, l2, u, c, s1, true,  5970, "#A4");
     276    checkMcf(mcf5, mcf5.run(), gr, l2, u, c, s2, true,  8010, "#A5");
     277    checkMcf(mcf6, mcf6.run(), gr, l2, u, c, s3, false,    0, "#A6");
     278  }
     279
     280  // B. Test CapacityScaling without scaling
     281  {
     282    CapacityScaling<Digraph> mcf1(gr, u, c, s1);
     283    CapacityScaling<Digraph> mcf2(gr, u, c, v, w, 27);
     284    CapacityScaling<Digraph> mcf3(gr, u, c, s3);
     285    CapacityScaling<Digraph> mcf4(gr, l2, u, c, s1);
     286    CapacityScaling<Digraph> mcf5(gr, l2, u, c, v, w, 27);
     287    CapacityScaling<Digraph> mcf6(gr, l2, u, c, s3);
     288
     289    checkMcf(mcf1, mcf1.run(false), gr, l1, u, c, s1, true,  5240, "#B1");
     290    checkMcf(mcf2, mcf2.run(false), gr, l1, u, c, s2, true,  7620, "#B2");
     291    checkMcf(mcf3, mcf3.run(false), gr, l1, u, c, s3, true,     0, "#B3");
     292    checkMcf(mcf4, mcf4.run(false), gr, l2, u, c, s1, true,  5970, "#B4");
     293    checkMcf(mcf5, mcf5.run(false), gr, l2, u, c, s2, true,  8010, "#B5");
     294    checkMcf(mcf6, mcf6.run(false), gr, l2, u, c, s3, false,    0, "#B6");
     295  }
     296
     297  // C. Test CostScaling using partial augment-relabel method
     298  {
     299    CostScaling<Digraph> mcf1(gr, u, c, s1);
     300    CostScaling<Digraph> mcf2(gr, u, c, v, w, 27);
     301    CostScaling<Digraph> mcf3(gr, u, c, s3);
     302    CostScaling<Digraph> mcf4(gr, l2, u, c, s1);
     303    CostScaling<Digraph> mcf5(gr, l2, u, c, v, w, 27);
     304    CostScaling<Digraph> mcf6(gr, l2, u, c, s3);
     305
     306    checkMcf(mcf1, mcf1.run(), gr, l1, u, c, s1, true,  5240, "#C1");
     307    checkMcf(mcf2, mcf2.run(), gr, l1, u, c, s2, true,  7620, "#C2");
     308    checkMcf(mcf3, mcf3.run(), gr, l1, u, c, s3, true,     0, "#C3");
     309    checkMcf(mcf4, mcf4.run(), gr, l2, u, c, s1, true,  5970, "#C4");
     310    checkMcf(mcf5, mcf5.run(), gr, l2, u, c, s2, true,  8010, "#C5");
     311    checkMcf(mcf6, mcf6.run(), gr, l2, u, c, s3, false,    0, "#C6");
     312  }
     313
     314  // D. Test CostScaling using push-relabel method
     315  {
     316    CostScaling<Digraph> mcf1(gr, u, c, s1);
     317    CostScaling<Digraph> mcf2(gr, u, c, v, w, 27);
     318    CostScaling<Digraph> mcf3(gr, u, c, s3);
     319    CostScaling<Digraph> mcf4(gr, l2, u, c, s1);
     320    CostScaling<Digraph> mcf5(gr, l2, u, c, v, w, 27);
     321    CostScaling<Digraph> mcf6(gr, l2, u, c, s3);
     322
     323    checkMcf(mcf1, mcf1.run(false), gr, l1, u, c, s1, true,  5240, "#D1");
     324    checkMcf(mcf2, mcf2.run(false), gr, l1, u, c, s2, true,  7620, "#D2");
     325    checkMcf(mcf3, mcf3.run(false), gr, l1, u, c, s3, true,     0, "#D3");
     326    checkMcf(mcf4, mcf4.run(false), gr, l2, u, c, s1, true,  5970, "#D4");
     327    checkMcf(mcf5, mcf5.run(false), gr, l2, u, c, s2, true,  8010, "#D5");
     328    checkMcf(mcf6, mcf6.run(false), gr, l2, u, c, s3, false,    0, "#D6");
     329  }
     330*/
     331
     332  // E. Test NetworkSimplex with FIRST_ELIGIBLE_PIVOT
     333  {
     334    NetworkSimplex<Digraph>::PivotRuleEnum pr =
     335      NetworkSimplex<Digraph>::FIRST_ELIGIBLE_PIVOT;
     336    NetworkSimplex<Digraph> mcf1(gr, u, c, s1);
     337    NetworkSimplex<Digraph> mcf2(gr, u, c, v, w, 27);
     338    NetworkSimplex<Digraph> mcf3(gr, u, c, s3);
     339    NetworkSimplex<Digraph> mcf4(gr, l2, u, c, s1);
     340    NetworkSimplex<Digraph> mcf5(gr, l2, u, c, v, w, 27);
     341    NetworkSimplex<Digraph> mcf6(gr, l2, u, c, s3);
     342
     343    checkMcf(mcf1, mcf1.run(pr), gr, l1, u, c, s1, true,  5240, "#E1");
     344    checkMcf(mcf2, mcf2.run(pr), gr, l1, u, c, s2, true,  7620, "#E2");
     345    checkMcf(mcf3, mcf3.run(pr), gr, l1, u, c, s3, true,     0, "#E3");
     346    checkMcf(mcf4, mcf4.run(pr), gr, l2, u, c, s1, true,  5970, "#E4");
     347    checkMcf(mcf5, mcf5.run(pr), gr, l2, u, c, s2, true,  8010, "#E5");
     348    checkMcf(mcf6, mcf6.run(pr), gr, l2, u, c, s3, false,    0, "#E6");
     349  }
     350
     351  // F. Test NetworkSimplex with BEST_ELIGIBLE_PIVOT
     352  {
     353    NetworkSimplex<Digraph>::PivotRuleEnum pr =
     354      NetworkSimplex<Digraph>::BEST_ELIGIBLE_PIVOT;
     355    NetworkSimplex<Digraph> mcf1(gr, u, c, s1);
     356    NetworkSimplex<Digraph> mcf2(gr, u, c, v, w, 27);
     357    NetworkSimplex<Digraph> mcf3(gr, u, c, s3);
     358    NetworkSimplex<Digraph> mcf4(gr, l2, u, c, s1);
     359    NetworkSimplex<Digraph> mcf5(gr, l2, u, c, v, w, 27);
     360    NetworkSimplex<Digraph> mcf6(gr, l2, u, c, s3);
     361
     362    checkMcf(mcf1, mcf1.run(pr), gr, l1, u, c, s1, true,  5240, "#F1");
     363    checkMcf(mcf2, mcf2.run(pr), gr, l1, u, c, s2, true,  7620, "#F2");
     364    checkMcf(mcf3, mcf3.run(pr), gr, l1, u, c, s3, true,     0, "#F3");
     365    checkMcf(mcf4, mcf4.run(pr), gr, l2, u, c, s1, true,  5970, "#F4");
     366    checkMcf(mcf5, mcf5.run(pr), gr, l2, u, c, s2, true,  8010, "#F5");
     367    checkMcf(mcf6, mcf6.run(pr), gr, l2, u, c, s3, false,    0, "#F6");
     368  }
     369
     370  // G. Test NetworkSimplex with BLOCK_SEARCH_PIVOT
     371  {
     372    NetworkSimplex<Digraph>::PivotRuleEnum pr =
     373      NetworkSimplex<Digraph>::BLOCK_SEARCH_PIVOT;
     374    NetworkSimplex<Digraph> mcf1(gr, u, c, s1);
     375    NetworkSimplex<Digraph> mcf2(gr, u, c, v, w, 27);
     376    NetworkSimplex<Digraph> mcf3(gr, u, c, s3);
     377    NetworkSimplex<Digraph> mcf4(gr, l2, u, c, s1);
     378    NetworkSimplex<Digraph> mcf5(gr, l2, u, c, v, w, 27);
     379    NetworkSimplex<Digraph> mcf6(gr, l2, u, c, s3);
     380
     381    checkMcf(mcf1, mcf1.run(pr), gr, l1, u, c, s1, true,  5240, "#G1");
     382    checkMcf(mcf2, mcf2.run(pr), gr, l1, u, c, s2, true,  7620, "#G2");
     383    checkMcf(mcf3, mcf3.run(pr), gr, l1, u, c, s3, true,     0, "#G3");
     384    checkMcf(mcf4, mcf4.run(pr), gr, l2, u, c, s1, true,  5970, "#G4");
     385    checkMcf(mcf5, mcf5.run(pr), gr, l2, u, c, s2, true,  8010, "#G5");
     386    checkMcf(mcf6, mcf6.run(pr), gr, l2, u, c, s3, false,    0, "#G6");
     387  }
     388
     389  // H. Test NetworkSimplex with CANDIDATE_LIST_PIVOT
     390  {
     391    NetworkSimplex<Digraph>::PivotRuleEnum pr =
     392      NetworkSimplex<Digraph>::CANDIDATE_LIST_PIVOT;
     393    NetworkSimplex<Digraph> mcf1(gr, u, c, s1);
     394    NetworkSimplex<Digraph> mcf2(gr, u, c, v, w, 27);
     395    NetworkSimplex<Digraph> mcf3(gr, u, c, s3);
     396    NetworkSimplex<Digraph> mcf4(gr, l2, u, c, s1);
     397    NetworkSimplex<Digraph> mcf5(gr, l2, u, c, v, w, 27);
     398    NetworkSimplex<Digraph> mcf6(gr, l2, u, c, s3);
     399
     400    checkMcf(mcf1, mcf1.run(pr), gr, l1, u, c, s1, true,  5240, "#H1");
     401    checkMcf(mcf2, mcf2.run(pr), gr, l1, u, c, s2, true,  7620, "#H2");
     402    checkMcf(mcf3, mcf3.run(pr), gr, l1, u, c, s3, true,     0, "#H3");
     403    checkMcf(mcf4, mcf4.run(pr), gr, l2, u, c, s1, true,  5970, "#H4");
     404    checkMcf(mcf5, mcf5.run(pr), gr, l2, u, c, s2, true,  8010, "#H5");
     405    checkMcf(mcf6, mcf6.run(pr), gr, l2, u, c, s3, false,    0, "#H6");
     406  }
     407
     408  // I. Test NetworkSimplex with ALTERING_LIST_PIVOT
     409  {
     410    NetworkSimplex<Digraph>::PivotRuleEnum pr =
     411      NetworkSimplex<Digraph>::ALTERING_LIST_PIVOT;
     412    NetworkSimplex<Digraph> mcf1(gr, u, c, s1);
     413    NetworkSimplex<Digraph> mcf2(gr, u, c, v, w, 27);
     414    NetworkSimplex<Digraph> mcf3(gr, u, c, s3);
     415    NetworkSimplex<Digraph> mcf4(gr, l2, u, c, s1);
     416    NetworkSimplex<Digraph> mcf5(gr, l2, u, c, v, w, 27);
     417    NetworkSimplex<Digraph> mcf6(gr, l2, u, c, s3);
     418
     419    checkMcf(mcf1, mcf1.run(pr), gr, l1, u, c, s1, true,  5240, "#I1");
     420    checkMcf(mcf2, mcf2.run(pr), gr, l1, u, c, s2, true,  7620, "#I2");
     421    checkMcf(mcf3, mcf3.run(pr), gr, l1, u, c, s3, true,     0, "#I3");
     422    checkMcf(mcf4, mcf4.run(pr), gr, l2, u, c, s1, true,  5970, "#I4");
     423    checkMcf(mcf5, mcf5.run(pr), gr, l2, u, c, s2, true,  8010, "#I5");
     424    checkMcf(mcf6, mcf6.run(pr), gr, l2, u, c, s3, false,    0, "#I6");
     425  }
     426
     427/*
     428  // J. Test MinCostFlow
     429  {
     430    MinCostFlow<Digraph> mcf1(gr, u, c, s1);
     431    MinCostFlow<Digraph> mcf2(gr, u, c, v, w, 27);
     432    MinCostFlow<Digraph> mcf3(gr, u, c, s3);
     433    MinCostFlow<Digraph> mcf4(gr, l2, u, c, s1);
     434    MinCostFlow<Digraph> mcf5(gr, l2, u, c, v, w, 27);
     435    MinCostFlow<Digraph> mcf6(gr, l2, u, c, s3);
     436
     437    checkMcf(mcf1, mcf1.run(), gr, l1, u, c, s1, true,  5240, "#J1");
     438    checkMcf(mcf2, mcf2.run(), gr, l1, u, c, s2, true,  7620, "#J2");
     439    checkMcf(mcf3, mcf3.run(), gr, l1, u, c, s3, true,     0, "#J3");
     440    checkMcf(mcf4, mcf4.run(), gr, l2, u, c, s1, true,  5970, "#J4");
     441    checkMcf(mcf5, mcf5.run(), gr, l2, u, c, s2, true,  8010, "#J5");
     442    checkMcf(mcf6, mcf6.run(), gr, l2, u, c, s3, false,    0, "#J6");
     443  }
     444*/
     445/*
     446  // K. Test MinCostMaxFlow
     447  {
     448    MinCostMaxFlow<Digraph> mcmf(gr, u, c, v, w);
     449    mcmf.run();
     450    checkMcf(mcmf, true, gr, l1, u, c, s3, true, 7620, "#K1");
     451  }
     452*/
     453
     454  return 0;
     455}