COIN-OR::LEMON - Graph Library

source: lemon-1.2/lemon/network_simplex.h @ 605:5232721b3f14

Last change on this file since 605:5232721b3f14 was 605:5232721b3f14, checked in by Peter Kovacs <kpeter@…>, 16 years ago

Rework the interface of NetworkSimplex? (#234)

The parameters of the problem can be set with separate functions
instead of different constructors.

File size: 39.6 KB
RevLine 
[601]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
[605]25/// \brief Network Simplex algorithm for finding a minimum cost flow.
[601]26
27#include <vector>
28#include <limits>
29#include <algorithm>
30
[603]31#include <lemon/core.h>
[601]32#include <lemon/math.h>
33
34namespace lemon {
35
36  /// \addtogroup min_cost_flow
37  /// @{
38
[605]39  /// \brief Implementation of the primal Network Simplex algorithm
[601]40  /// for finding a \ref min_cost_flow "minimum cost flow".
41  ///
[605]42  /// \ref NetworkSimplex implements the primal Network Simplex algorithm
[601]43  /// for finding a \ref min_cost_flow "minimum cost flow".
44  ///
[605]45  /// \tparam GR The digraph type the algorithm runs on.
46  /// \tparam V The value type used in the algorithm.
47  /// By default it is \c int.
[601]48  ///
[605]49  /// \warning \c V must be a signed integer type.
[601]50  ///
[605]51  /// \note %NetworkSimplex provides five different pivot rule
52  /// implementations. For more information see \ref PivotRule.
53  template <typename GR, typename V = int>
[601]54  class NetworkSimplex
55  {
[605]56  public:
[601]57
[605]58    /// The value type of the algorithm
59    typedef V Value;
60    /// The type of the flow map
61    typedef typename GR::template ArcMap<Value> FlowMap;
62    /// The type of the potential map
63    typedef typename GR::template NodeMap<Value> PotentialMap;
64
65  public:
66
67    /// \brief Enum type for selecting the pivot rule.
68    ///
69    /// Enum type for selecting the pivot rule for the \ref run()
70    /// function.
71    ///
72    /// \ref NetworkSimplex provides five different pivot rule
73    /// implementations that significantly affect the running time
74    /// of the algorithm.
75    /// By default \ref BLOCK_SEARCH "Block Search" is used, which
76    /// proved to be the most efficient and the most robust on various
77    /// test inputs according to our benchmark tests.
78    /// However another pivot rule can be selected using the \ref run()
79    /// function with the proper parameter.
80    enum PivotRule {
81
82      /// The First Eligible pivot rule.
83      /// The next eligible arc is selected in a wraparound fashion
84      /// in every iteration.
85      FIRST_ELIGIBLE,
86
87      /// The Best Eligible pivot rule.
88      /// The best eligible arc is selected in every iteration.
89      BEST_ELIGIBLE,
90
91      /// The Block Search pivot rule.
92      /// A specified number of arcs are examined in every iteration
93      /// in a wraparound fashion and the best eligible arc is selected
94      /// from this block.
95      BLOCK_SEARCH,
96
97      /// The Candidate List pivot rule.
98      /// In a major iteration a candidate list is built from eligible arcs
99      /// in a wraparound fashion and in the following minor iterations
100      /// the best eligible arc is selected from this list.
101      CANDIDATE_LIST,
102
103      /// The Altering Candidate List pivot rule.
104      /// It is a modified version of the Candidate List method.
105      /// It keeps only the several best eligible arcs from the former
106      /// candidate list and extends this list in every iteration.
107      ALTERING_LIST
108    };
109
110  private:
111
112    TEMPLATE_DIGRAPH_TYPEDEFS(GR);
113
114    typedef typename GR::template ArcMap<Value> ValueArcMap;
115    typedef typename GR::template NodeMap<Value> ValueNodeMap;
[601]116
117    typedef std::vector<Arc> ArcVector;
118    typedef std::vector<Node> NodeVector;
119    typedef std::vector<int> IntVector;
120    typedef std::vector<bool> BoolVector;
[605]121    typedef std::vector<Value> ValueVector;
[601]122
123    // State constants for arcs
124    enum ArcStateEnum {
125      STATE_UPPER = -1,
126      STATE_TREE  =  0,
127      STATE_LOWER =  1
128    };
129
130  private:
131
[605]132    // Data related to the underlying digraph
133    const GR &_graph;
134    int _node_num;
135    int _arc_num;
136
137    // Parameters of the problem
138    ValueArcMap *_plower;
139    ValueArcMap *_pupper;
140    ValueArcMap *_pcost;
141    ValueNodeMap *_psupply;
142    bool _pstsup;
143    Node _psource, _ptarget;
144    Value _pstflow;
[601]145
146    // Result maps
[603]147    FlowMap *_flow_map;
148    PotentialMap *_potential_map;
[601]149    bool _local_flow;
150    bool _local_potential;
151
[605]152    // Data structures for storing the digraph
[603]153    IntNodeMap _node_id;
154    ArcVector _arc_ref;
155    IntVector _source;
156    IntVector _target;
157
[605]158    // Node and arc data
159    ValueVector _cap;
160    ValueVector _cost;
161    ValueVector _supply;
162    ValueVector _flow;
163    ValueVector _pi;
[601]164
[603]165    // Data for storing the spanning tree structure
[601]166    IntVector _parent;
167    IntVector _pred;
168    IntVector _thread;
[604]169    IntVector _rev_thread;
170    IntVector _succ_num;
171    IntVector _last_succ;
172    IntVector _dirty_revs;
[601]173    BoolVector _forward;
174    IntVector _state;
175    int _root;
176
177    // Temporary data used in the current pivot iteration
[603]178    int in_arc, join, u_in, v_in, u_out, v_out;
179    int first, second, right, last;
[601]180    int stem, par_stem, new_stem;
[605]181    Value delta;
[601]182
183  private:
184
[605]185    // Implementation of the First Eligible pivot rule
[601]186    class FirstEligiblePivotRule
187    {
188    private:
189
190      // References to the NetworkSimplex class
191      const IntVector  &_source;
192      const IntVector  &_target;
[605]193      const ValueVector &_cost;
[601]194      const IntVector  &_state;
[605]195      const ValueVector &_pi;
[601]196      int &_in_arc;
197      int _arc_num;
198
199      // Pivot rule data
200      int _next_arc;
201
202    public:
203
[605]204      // Constructor
[601]205      FirstEligiblePivotRule(NetworkSimplex &ns) :
[603]206        _source(ns._source), _target(ns._target),
[601]207        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
[603]208        _in_arc(ns.in_arc), _arc_num(ns._arc_num), _next_arc(0)
[601]209      {}
210
[605]211      // Find next entering arc
[601]212      bool findEnteringArc() {
[605]213        Value c;
[601]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
[605]236    // Implementation of the Best Eligible pivot rule
[601]237    class BestEligiblePivotRule
238    {
239    private:
240
241      // References to the NetworkSimplex class
242      const IntVector  &_source;
243      const IntVector  &_target;
[605]244      const ValueVector &_cost;
[601]245      const IntVector  &_state;
[605]246      const ValueVector &_pi;
[601]247      int &_in_arc;
248      int _arc_num;
249
250    public:
251
[605]252      // Constructor
[601]253      BestEligiblePivotRule(NetworkSimplex &ns) :
[603]254        _source(ns._source), _target(ns._target),
[601]255        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
[603]256        _in_arc(ns.in_arc), _arc_num(ns._arc_num)
[601]257      {}
258
[605]259      // Find next entering arc
[601]260      bool findEnteringArc() {
[605]261        Value c, min = 0;
[601]262        for (int e = 0; e < _arc_num; ++e) {
263          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
264          if (c < min) {
265            min = c;
266            _in_arc = e;
267          }
268        }
269        return min < 0;
270      }
271
272    }; //class BestEligiblePivotRule
273
274
[605]275    // Implementation of the Block Search pivot rule
[601]276    class BlockSearchPivotRule
277    {
278    private:
279
280      // References to the NetworkSimplex class
281      const IntVector  &_source;
282      const IntVector  &_target;
[605]283      const ValueVector &_cost;
[601]284      const IntVector  &_state;
[605]285      const ValueVector &_pi;
[601]286      int &_in_arc;
287      int _arc_num;
288
289      // Pivot rule data
290      int _block_size;
291      int _next_arc;
292
293    public:
294
[605]295      // Constructor
[601]296      BlockSearchPivotRule(NetworkSimplex &ns) :
[603]297        _source(ns._source), _target(ns._target),
[601]298        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
[603]299        _in_arc(ns.in_arc), _arc_num(ns._arc_num), _next_arc(0)
[601]300      {
301        // The main parameters of the pivot rule
302        const double BLOCK_SIZE_FACTOR = 2.0;
303        const int MIN_BLOCK_SIZE = 10;
304
305        _block_size = std::max( int(BLOCK_SIZE_FACTOR * sqrt(_arc_num)),
306                                MIN_BLOCK_SIZE );
307      }
308
[605]309      // Find next entering arc
[601]310      bool findEnteringArc() {
[605]311        Value c, min = 0;
[601]312        int cnt = _block_size;
313        int e, min_arc = _next_arc;
314        for (e = _next_arc; e < _arc_num; ++e) {
315          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
316          if (c < min) {
317            min = c;
318            min_arc = e;
319          }
320          if (--cnt == 0) {
321            if (min < 0) break;
322            cnt = _block_size;
323          }
324        }
325        if (min == 0 || cnt > 0) {
326          for (e = 0; e < _next_arc; ++e) {
327            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
328            if (c < min) {
329              min = c;
330              min_arc = e;
331            }
332            if (--cnt == 0) {
333              if (min < 0) break;
334              cnt = _block_size;
335            }
336          }
337        }
338        if (min >= 0) return false;
339        _in_arc = min_arc;
340        _next_arc = e;
341        return true;
342      }
343
344    }; //class BlockSearchPivotRule
345
346
[605]347    // Implementation of the Candidate List pivot rule
[601]348    class CandidateListPivotRule
349    {
350    private:
351
352      // References to the NetworkSimplex class
353      const IntVector  &_source;
354      const IntVector  &_target;
[605]355      const ValueVector &_cost;
[601]356      const IntVector  &_state;
[605]357      const ValueVector &_pi;
[601]358      int &_in_arc;
359      int _arc_num;
360
361      // Pivot rule data
362      IntVector _candidates;
363      int _list_length, _minor_limit;
364      int _curr_length, _minor_count;
365      int _next_arc;
366
367    public:
368
369      /// Constructor
370      CandidateListPivotRule(NetworkSimplex &ns) :
[603]371        _source(ns._source), _target(ns._target),
[601]372        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
[603]373        _in_arc(ns.in_arc), _arc_num(ns._arc_num), _next_arc(0)
[601]374      {
375        // The main parameters of the pivot rule
376        const double LIST_LENGTH_FACTOR = 1.0;
377        const int MIN_LIST_LENGTH = 10;
378        const double MINOR_LIMIT_FACTOR = 0.1;
379        const int MIN_MINOR_LIMIT = 3;
380
381        _list_length = std::max( int(LIST_LENGTH_FACTOR * sqrt(_arc_num)),
382                                 MIN_LIST_LENGTH );
383        _minor_limit = std::max( int(MINOR_LIMIT_FACTOR * _list_length),
384                                 MIN_MINOR_LIMIT );
385        _curr_length = _minor_count = 0;
386        _candidates.resize(_list_length);
387      }
388
389      /// Find next entering arc
390      bool findEnteringArc() {
[605]391        Value min, c;
[601]392        int e, min_arc = _next_arc;
393        if (_curr_length > 0 && _minor_count < _minor_limit) {
394          // Minor iteration: select the best eligible arc from the
395          // current candidate list
396          ++_minor_count;
397          min = 0;
398          for (int i = 0; i < _curr_length; ++i) {
399            e = _candidates[i];
400            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
401            if (c < min) {
402              min = c;
403              min_arc = e;
404            }
405            if (c >= 0) {
406              _candidates[i--] = _candidates[--_curr_length];
407            }
408          }
409          if (min < 0) {
410            _in_arc = min_arc;
411            return true;
412          }
413        }
414
415        // Major iteration: build a new candidate list
416        min = 0;
417        _curr_length = 0;
418        for (e = _next_arc; e < _arc_num; ++e) {
419          c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
420          if (c < 0) {
421            _candidates[_curr_length++] = e;
422            if (c < min) {
423              min = c;
424              min_arc = e;
425            }
426            if (_curr_length == _list_length) break;
427          }
428        }
429        if (_curr_length < _list_length) {
430          for (e = 0; e < _next_arc; ++e) {
431            c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
432            if (c < 0) {
433              _candidates[_curr_length++] = e;
434              if (c < min) {
435                min = c;
436                min_arc = e;
437              }
438              if (_curr_length == _list_length) break;
439            }
440          }
441        }
442        if (_curr_length == 0) return false;
443        _minor_count = 1;
444        _in_arc = min_arc;
445        _next_arc = e;
446        return true;
447      }
448
449    }; //class CandidateListPivotRule
450
451
[605]452    // Implementation of the Altering Candidate List pivot rule
[601]453    class AlteringListPivotRule
454    {
455    private:
456
457      // References to the NetworkSimplex class
458      const IntVector  &_source;
459      const IntVector  &_target;
[605]460      const ValueVector &_cost;
[601]461      const IntVector  &_state;
[605]462      const ValueVector &_pi;
[601]463      int &_in_arc;
464      int _arc_num;
465
466      // Pivot rule data
467      int _block_size, _head_length, _curr_length;
468      int _next_arc;
469      IntVector _candidates;
[605]470      ValueVector _cand_cost;
[601]471
472      // Functor class to compare arcs during sort of the candidate list
473      class SortFunc
474      {
475      private:
[605]476        const ValueVector &_map;
[601]477      public:
[605]478        SortFunc(const ValueVector &map) : _map(map) {}
[601]479        bool operator()(int left, int right) {
480          return _map[left] > _map[right];
481        }
482      };
483
484      SortFunc _sort_func;
485
486    public:
487
[605]488      // Constructor
[601]489      AlteringListPivotRule(NetworkSimplex &ns) :
[603]490        _source(ns._source), _target(ns._target),
[601]491        _cost(ns._cost), _state(ns._state), _pi(ns._pi),
[603]492        _in_arc(ns.in_arc), _arc_num(ns._arc_num),
[601]493        _next_arc(0), _cand_cost(ns._arc_num), _sort_func(_cand_cost)
494      {
495        // The main parameters of the pivot rule
496        const double BLOCK_SIZE_FACTOR = 1.5;
497        const int MIN_BLOCK_SIZE = 10;
498        const double HEAD_LENGTH_FACTOR = 0.1;
499        const int MIN_HEAD_LENGTH = 3;
500
501        _block_size = std::max( int(BLOCK_SIZE_FACTOR * sqrt(_arc_num)),
502                                MIN_BLOCK_SIZE );
503        _head_length = std::max( int(HEAD_LENGTH_FACTOR * _block_size),
504                                 MIN_HEAD_LENGTH );
505        _candidates.resize(_head_length + _block_size);
506        _curr_length = 0;
507      }
508
[605]509      // Find next entering arc
[601]510      bool findEnteringArc() {
511        // Check the current candidate list
512        int e;
513        for (int i = 0; i < _curr_length; ++i) {
514          e = _candidates[i];
515          _cand_cost[e] = _state[e] *
516            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
517          if (_cand_cost[e] >= 0) {
518            _candidates[i--] = _candidates[--_curr_length];
519          }
520        }
521
522        // Extend the list
523        int cnt = _block_size;
[603]524        int last_arc = 0;
[601]525        int limit = _head_length;
526
527        for (int e = _next_arc; e < _arc_num; ++e) {
528          _cand_cost[e] = _state[e] *
529            (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
530          if (_cand_cost[e] < 0) {
531            _candidates[_curr_length++] = e;
[603]532            last_arc = e;
[601]533          }
534          if (--cnt == 0) {
535            if (_curr_length > limit) break;
536            limit = 0;
537            cnt = _block_size;
538          }
539        }
540        if (_curr_length <= limit) {
541          for (int e = 0; e < _next_arc; ++e) {
542            _cand_cost[e] = _state[e] *
543              (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
544            if (_cand_cost[e] < 0) {
545              _candidates[_curr_length++] = e;
[603]546              last_arc = e;
[601]547            }
548            if (--cnt == 0) {
549              if (_curr_length > limit) break;
550              limit = 0;
551              cnt = _block_size;
552            }
553          }
554        }
555        if (_curr_length == 0) return false;
[603]556        _next_arc = last_arc + 1;
[601]557
558        // Make heap of the candidate list (approximating a partial sort)
559        make_heap( _candidates.begin(), _candidates.begin() + _curr_length,
560                   _sort_func );
561
562        // Pop the first element of the heap
563        _in_arc = _candidates[0];
564        pop_heap( _candidates.begin(), _candidates.begin() + _curr_length,
565                  _sort_func );
566        _curr_length = std::min(_head_length, _curr_length - 1);
567        return true;
568      }
569
570    }; //class AlteringListPivotRule
571
572  public:
573
[605]574    /// \brief Constructor.
[601]575    ///
[605]576    /// Constructor.
[601]577    ///
[603]578    /// \param graph The digraph the algorithm runs on.
[605]579    NetworkSimplex(const GR& graph) :
580      _graph(graph),
581      _plower(NULL), _pupper(NULL), _pcost(NULL),
582      _psupply(NULL), _pstsup(false),
[603]583      _flow_map(NULL), _potential_map(NULL),
[601]584      _local_flow(false), _local_potential(false),
[603]585      _node_id(graph)
[605]586    {
587      LEMON_ASSERT(std::numeric_limits<Value>::is_integer &&
588                   std::numeric_limits<Value>::is_signed,
589        "The value type of NetworkSimplex must be a signed integer");
590    }
[601]591
592    /// Destructor.
593    ~NetworkSimplex() {
[603]594      if (_local_flow) delete _flow_map;
595      if (_local_potential) delete _potential_map;
[601]596    }
597
[605]598    /// \brief Set the lower bounds on the arcs.
599    ///
600    /// This function sets the lower bounds on the arcs.
601    /// If neither this function nor \ref boundMaps() is used before
602    /// calling \ref run(), the lower bounds will be set to zero
603    /// on all arcs.
604    ///
605    /// \param map An arc map storing the lower bounds.
606    /// Its \c Value type must be convertible to the \c Value type
607    /// of the algorithm.
608    ///
609    /// \return <tt>(*this)</tt>
610    template <typename LOWER>
611    NetworkSimplex& lowerMap(const LOWER& map) {
612      delete _plower;
613      _plower = new ValueArcMap(_graph);
614      for (ArcIt a(_graph); a != INVALID; ++a) {
615        (*_plower)[a] = map[a];
616      }
617      return *this;
618    }
619
620    /// \brief Set the upper bounds (capacities) on the arcs.
621    ///
622    /// This function sets the upper bounds (capacities) on the arcs.
623    /// If none of the functions \ref upperMap(), \ref capacityMap()
624    /// and \ref boundMaps() is used before calling \ref run(),
625    /// the upper bounds (capacities) will be set to
626    /// \c std::numeric_limits<Value>::max() on all arcs.
627    ///
628    /// \param map An arc map storing the upper bounds.
629    /// Its \c Value type must be convertible to the \c Value type
630    /// of the algorithm.
631    ///
632    /// \return <tt>(*this)</tt>
633    template<typename UPPER>
634    NetworkSimplex& upperMap(const UPPER& map) {
635      delete _pupper;
636      _pupper = new ValueArcMap(_graph);
637      for (ArcIt a(_graph); a != INVALID; ++a) {
638        (*_pupper)[a] = map[a];
639      }
640      return *this;
641    }
642
643    /// \brief Set the upper bounds (capacities) on the arcs.
644    ///
645    /// This function sets the upper bounds (capacities) on the arcs.
646    /// It is just an alias for \ref upperMap().
647    ///
648    /// \return <tt>(*this)</tt>
649    template<typename CAP>
650    NetworkSimplex& capacityMap(const CAP& map) {
651      return upperMap(map);
652    }
653
654    /// \brief Set the lower and upper bounds on the arcs.
655    ///
656    /// This function sets the lower and upper bounds on the arcs.
657    /// If neither this function nor \ref lowerMap() is used before
658    /// calling \ref run(), the lower bounds will be set to zero
659    /// on all arcs.
660    /// If none of the functions \ref upperMap(), \ref capacityMap()
661    /// and \ref boundMaps() is used before calling \ref run(),
662    /// the upper bounds (capacities) will be set to
663    /// \c std::numeric_limits<Value>::max() on all arcs.
664    ///
665    /// \param lower An arc map storing the lower bounds.
666    /// \param upper An arc map storing the upper bounds.
667    ///
668    /// The \c Value type of the maps must be convertible to the
669    /// \c Value type of the algorithm.
670    ///
671    /// \note This function is just a shortcut of calling \ref lowerMap()
672    /// and \ref upperMap() separately.
673    ///
674    /// \return <tt>(*this)</tt>
675    template <typename LOWER, typename UPPER>
676    NetworkSimplex& boundMaps(const LOWER& lower, const UPPER& upper) {
677      return lowerMap(lower).upperMap(upper);
678    }
679
680    /// \brief Set the costs of the arcs.
681    ///
682    /// This function sets the costs of the arcs.
683    /// If it is not used before calling \ref run(), the costs
684    /// will be set to \c 1 on all arcs.
685    ///
686    /// \param map An arc map storing the costs.
687    /// Its \c Value type must be convertible to the \c Value type
688    /// of the algorithm.
689    ///
690    /// \return <tt>(*this)</tt>
691    template<typename COST>
692    NetworkSimplex& costMap(const COST& map) {
693      delete _pcost;
694      _pcost = new ValueArcMap(_graph);
695      for (ArcIt a(_graph); a != INVALID; ++a) {
696        (*_pcost)[a] = map[a];
697      }
698      return *this;
699    }
700
701    /// \brief Set the supply values of the nodes.
702    ///
703    /// This function sets the supply values of the nodes.
704    /// If neither this function nor \ref stSupply() is used before
705    /// calling \ref run(), the supply of each node will be set to zero.
706    /// (It makes sense only if non-zero lower bounds are given.)
707    ///
708    /// \param map A node map storing the supply values.
709    /// Its \c Value type must be convertible to the \c Value type
710    /// of the algorithm.
711    ///
712    /// \return <tt>(*this)</tt>
713    template<typename SUP>
714    NetworkSimplex& supplyMap(const SUP& map) {
715      delete _psupply;
716      _pstsup = false;
717      _psupply = new ValueNodeMap(_graph);
718      for (NodeIt n(_graph); n != INVALID; ++n) {
719        (*_psupply)[n] = map[n];
720      }
721      return *this;
722    }
723
724    /// \brief Set single source and target nodes and a supply value.
725    ///
726    /// This function sets a single source node and a single target node
727    /// and the required flow value.
728    /// If neither this function nor \ref supplyMap() is used before
729    /// calling \ref run(), the supply of each node will be set to zero.
730    /// (It makes sense only if non-zero lower bounds are given.)
731    ///
732    /// \param s The source node.
733    /// \param t The target node.
734    /// \param k The required amount of flow from node \c s to node \c t
735    /// (i.e. the supply of \c s and the demand of \c t).
736    ///
737    /// \return <tt>(*this)</tt>
738    NetworkSimplex& stSupply(const Node& s, const Node& t, Value k) {
739      delete _psupply;
740      _psupply = NULL;
741      _pstsup = true;
742      _psource = s;
743      _ptarget = t;
744      _pstflow = k;
745      return *this;
746    }
747
[601]748    /// \brief Set the flow map.
749    ///
750    /// This function sets the flow map.
[605]751    /// If it is not used before calling \ref run(), an instance will
752    /// be allocated automatically. The destructor deallocates this
753    /// automatically allocated map, of course.
[601]754    ///
755    /// \return <tt>(*this)</tt>
[605]756    NetworkSimplex& flowMap(FlowMap& map) {
[601]757      if (_local_flow) {
[603]758        delete _flow_map;
[601]759        _local_flow = false;
760      }
[603]761      _flow_map = &map;
[601]762      return *this;
763    }
764
765    /// \brief Set the potential map.
766    ///
[605]767    /// This function sets the potential map, which is used for storing
768    /// the dual solution.
769    /// If it is not used before calling \ref run(), an instance will
770    /// be allocated automatically. The destructor deallocates this
771    /// automatically allocated map, of course.
[601]772    ///
773    /// \return <tt>(*this)</tt>
[605]774    NetworkSimplex& potentialMap(PotentialMap& map) {
[601]775      if (_local_potential) {
[603]776        delete _potential_map;
[601]777        _local_potential = false;
778      }
[603]779      _potential_map = &map;
[601]780      return *this;
781    }
782
[605]783    /// \name Execution Control
784    /// The algorithm can be executed using \ref run().
785
[601]786    /// @{
787
788    /// \brief Run the algorithm.
789    ///
790    /// This function runs the algorithm.
[605]791    /// The paramters can be specified using \ref lowerMap(),
792    /// \ref upperMap(), \ref capacityMap(), \ref boundMaps(),
793    /// \ref costMap(), \ref supplyMap() and \ref stSupply()
794    /// functions. For example,
795    /// \code
796    ///   NetworkSimplex<ListDigraph> ns(graph);
797    ///   ns.boundMaps(lower, upper).costMap(cost)
798    ///     .supplyMap(sup).run();
799    /// \endcode
[601]800    ///
[605]801    /// \param pivot_rule The pivot rule that will be used during the
802    /// algorithm. For more information see \ref PivotRule.
[601]803    ///
804    /// \return \c true if a feasible flow can be found.
[605]805    bool run(PivotRule pivot_rule = BLOCK_SEARCH) {
[601]806      return init() && start(pivot_rule);
807    }
808
809    /// @}
810
811    /// \name Query Functions
812    /// The results of the algorithm can be obtained using these
813    /// functions.\n
[605]814    /// The \ref run() function must be called before using them.
815
[601]816    /// @{
817
[605]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    /// \note The return type of the function can be specified as a
824    /// template parameter. For example,
825    /// \code
826    ///   ns.totalCost<double>();
827    /// \endcode
828    /// It is useful if the total cost cannot be stored in the \c Value
829    /// type of the algorithm, which is the default return type of the
830    /// function.
831    ///
832    /// \pre \ref run() must be called before using this function.
833    template <typename Num>
834    Num totalCost() const {
835      Num c = 0;
836      if (_pcost) {
837        for (ArcIt e(_graph); e != INVALID; ++e)
838          c += (*_flow_map)[e] * (*_pcost)[e];
839      } else {
840        for (ArcIt e(_graph); e != INVALID; ++e)
841          c += (*_flow_map)[e];
842      }
843      return c;
844    }
845
846#ifndef DOXYGEN
847    Value totalCost() const {
848      return totalCost<Value>();
849    }
850#endif
851
852    /// \brief Return the flow on the given arc.
853    ///
854    /// This function returns the flow on the given arc.
855    ///
856    /// \pre \ref run() must be called before using this function.
857    Value flow(const Arc& a) const {
858      return (*_flow_map)[a];
859    }
860
[601]861    /// \brief Return a const reference to the flow map.
862    ///
863    /// This function returns a const reference to an arc map storing
864    /// the found flow.
865    ///
866    /// \pre \ref run() must be called before using this function.
867    const FlowMap& flowMap() const {
[603]868      return *_flow_map;
[601]869    }
870
[605]871    /// \brief Return the potential (dual value) of the given node.
872    ///
873    /// This function returns the potential (dual value) of the
874    /// given node.
875    ///
876    /// \pre \ref run() must be called before using this function.
877    Value potential(const Node& n) const {
878      return (*_potential_map)[n];
879    }
880
[601]881    /// \brief Return a const reference to the potential map
882    /// (the dual solution).
883    ///
884    /// This function returns a const reference to a node map storing
[605]885    /// the found potentials, which form the dual solution of the
886    /// \ref min_cost_flow "minimum cost flow" problem.
[601]887    ///
888    /// \pre \ref run() must be called before using this function.
889    const PotentialMap& potentialMap() const {
[603]890      return *_potential_map;
[601]891    }
892
893    /// @}
894
895  private:
896
897    // Initialize internal data structures
898    bool init() {
899      // Initialize result maps
[603]900      if (!_flow_map) {
901        _flow_map = new FlowMap(_graph);
[601]902        _local_flow = true;
903      }
[603]904      if (!_potential_map) {
905        _potential_map = new PotentialMap(_graph);
[601]906        _local_potential = true;
907      }
908
909      // Initialize vectors
[603]910      _node_num = countNodes(_graph);
911      _arc_num = countArcs(_graph);
[601]912      int all_node_num = _node_num + 1;
[603]913      int all_arc_num = _arc_num + _node_num;
[605]914      if (_node_num == 0) return false;
[601]915
[603]916      _arc_ref.resize(_arc_num);
917      _source.resize(all_arc_num);
918      _target.resize(all_arc_num);
[601]919
[603]920      _cap.resize(all_arc_num);
921      _cost.resize(all_arc_num);
[601]922      _supply.resize(all_node_num);
[603]923      _flow.resize(all_arc_num, 0);
[601]924      _pi.resize(all_node_num, 0);
925
926      _parent.resize(all_node_num);
927      _pred.resize(all_node_num);
[603]928      _forward.resize(all_node_num);
[601]929      _thread.resize(all_node_num);
[604]930      _rev_thread.resize(all_node_num);
931      _succ_num.resize(all_node_num);
932      _last_succ.resize(all_node_num);
[603]933      _state.resize(all_arc_num, STATE_LOWER);
[601]934
935      // Initialize node related data
936      bool valid_supply = true;
[605]937      if (!_pstsup && !_psupply) {
938        _pstsup = true;
939        _psource = _ptarget = NodeIt(_graph);
940        _pstflow = 0;
941      }
942      if (_psupply) {
943        Value sum = 0;
[601]944        int i = 0;
[603]945        for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
[601]946          _node_id[n] = i;
[605]947          _supply[i] = (*_psupply)[n];
[601]948          sum += _supply[i];
949        }
950        valid_supply = (sum == 0);
951      } else {
952        int i = 0;
[603]953        for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
[601]954          _node_id[n] = i;
955          _supply[i] = 0;
956        }
[605]957        _supply[_node_id[_psource]] =  _pstflow;
958        _supply[_node_id[_ptarget]]   = -_pstflow;
[601]959      }
960      if (!valid_supply) return false;
961
962      // Set data for the artificial root node
963      _root = _node_num;
964      _parent[_root] = -1;
965      _pred[_root] = -1;
966      _thread[_root] = 0;
[604]967      _rev_thread[0] = _root;
968      _succ_num[_root] = all_node_num;
969      _last_succ[_root] = _root - 1;
[601]970      _supply[_root] = 0;
971      _pi[_root] = 0;
972
973      // Store the arcs in a mixed order
974      int k = std::max(int(sqrt(_arc_num)), 10);
975      int i = 0;
[603]976      for (ArcIt e(_graph); e != INVALID; ++e) {
977        _arc_ref[i] = e;
[601]978        if ((i += k) >= _arc_num) i = (i % k) + 1;
979      }
980
981      // Initialize arc maps
[605]982      if (_pupper && _pcost) {
983        for (int i = 0; i != _arc_num; ++i) {
984          Arc e = _arc_ref[i];
985          _source[i] = _node_id[_graph.source(e)];
986          _target[i] = _node_id[_graph.target(e)];
987          _cap[i] = (*_pupper)[e];
988          _cost[i] = (*_pcost)[e];
989        }
990      } else {
991        for (int i = 0; i != _arc_num; ++i) {
992          Arc e = _arc_ref[i];
993          _source[i] = _node_id[_graph.source(e)];
994          _target[i] = _node_id[_graph.target(e)];
995        }
996        if (_pupper) {
997          for (int i = 0; i != _arc_num; ++i)
998            _cap[i] = (*_pupper)[_arc_ref[i]];
999        } else {
1000          Value val = std::numeric_limits<Value>::max();
1001          for (int i = 0; i != _arc_num; ++i)
1002            _cap[i] = val;
1003        }
1004        if (_pcost) {
1005          for (int i = 0; i != _arc_num; ++i)
1006            _cost[i] = (*_pcost)[_arc_ref[i]];
1007        } else {
1008          for (int i = 0; i != _arc_num; ++i)
1009            _cost[i] = 1;
1010        }
[601]1011      }
1012
1013      // Remove non-zero lower bounds
[605]1014      if (_plower) {
[601]1015        for (int i = 0; i != _arc_num; ++i) {
[605]1016          Value c = (*_plower)[_arc_ref[i]];
[601]1017          if (c != 0) {
1018            _cap[i] -= c;
1019            _supply[_source[i]] -= c;
1020            _supply[_target[i]] += c;
1021          }
1022        }
1023      }
1024
1025      // Add artificial arcs and initialize the spanning tree data structure
[605]1026      Value max_cap = std::numeric_limits<Value>::max();
1027      Value max_cost = std::numeric_limits<Value>::max() / 4;
[601]1028      for (int u = 0, e = _arc_num; u != _node_num; ++u, ++e) {
1029        _thread[u] = u + 1;
[604]1030        _rev_thread[u + 1] = u;
1031        _succ_num[u] = 1;
1032        _last_succ[u] = u;
[601]1033        _parent[u] = _root;
1034        _pred[u] = e;
1035        if (_supply[u] >= 0) {
1036          _flow[e] = _supply[u];
1037          _forward[u] = true;
1038          _pi[u] = -max_cost;
1039        } else {
1040          _flow[e] = -_supply[u];
1041          _forward[u] = false;
1042          _pi[u] = max_cost;
1043        }
1044        _cost[e] = max_cost;
1045        _cap[e] = max_cap;
1046        _state[e] = STATE_TREE;
1047      }
1048
1049      return true;
1050    }
1051
1052    // Find the join node
1053    void findJoinNode() {
[603]1054      int u = _source[in_arc];
1055      int v = _target[in_arc];
[601]1056      while (u != v) {
[604]1057        if (_succ_num[u] < _succ_num[v]) {
1058          u = _parent[u];
1059        } else {
1060          v = _parent[v];
1061        }
[601]1062      }
1063      join = u;
1064    }
1065
1066    // Find the leaving arc of the cycle and returns true if the
1067    // leaving arc is not the same as the entering arc
1068    bool findLeavingArc() {
1069      // Initialize first and second nodes according to the direction
1070      // of the cycle
[603]1071      if (_state[in_arc] == STATE_LOWER) {
1072        first  = _source[in_arc];
1073        second = _target[in_arc];
[601]1074      } else {
[603]1075        first  = _target[in_arc];
1076        second = _source[in_arc];
[601]1077      }
[603]1078      delta = _cap[in_arc];
[601]1079      int result = 0;
[605]1080      Value d;
[601]1081      int e;
1082
1083      // Search the cycle along the path form the first node to the root
1084      for (int u = first; u != join; u = _parent[u]) {
1085        e = _pred[u];
1086        d = _forward[u] ? _flow[e] : _cap[e] - _flow[e];
1087        if (d < delta) {
1088          delta = d;
1089          u_out = u;
1090          result = 1;
1091        }
1092      }
1093      // Search the cycle along the path form the second node to the root
1094      for (int u = second; u != join; u = _parent[u]) {
1095        e = _pred[u];
1096        d = _forward[u] ? _cap[e] - _flow[e] : _flow[e];
1097        if (d <= delta) {
1098          delta = d;
1099          u_out = u;
1100          result = 2;
1101        }
1102      }
1103
1104      if (result == 1) {
1105        u_in = first;
1106        v_in = second;
1107      } else {
1108        u_in = second;
1109        v_in = first;
1110      }
1111      return result != 0;
1112    }
1113
1114    // Change _flow and _state vectors
1115    void changeFlow(bool change) {
1116      // Augment along the cycle
1117      if (delta > 0) {
[605]1118        Value val = _state[in_arc] * delta;
[603]1119        _flow[in_arc] += val;
1120        for (int u = _source[in_arc]; u != join; u = _parent[u]) {
[601]1121          _flow[_pred[u]] += _forward[u] ? -val : val;
1122        }
[603]1123        for (int u = _target[in_arc]; u != join; u = _parent[u]) {
[601]1124          _flow[_pred[u]] += _forward[u] ? val : -val;
1125        }
1126      }
1127      // Update the state of the entering and leaving arcs
1128      if (change) {
[603]1129        _state[in_arc] = STATE_TREE;
[601]1130        _state[_pred[u_out]] =
1131          (_flow[_pred[u_out]] == 0) ? STATE_LOWER : STATE_UPPER;
1132      } else {
[603]1133        _state[in_arc] = -_state[in_arc];
[601]1134      }
1135    }
1136
[604]1137    // Update the tree structure
1138    void updateTreeStructure() {
1139      int u, w;
1140      int old_rev_thread = _rev_thread[u_out];
1141      int old_succ_num = _succ_num[u_out];
1142      int old_last_succ = _last_succ[u_out];
[601]1143      v_out = _parent[u_out];
1144
[604]1145      u = _last_succ[u_in];  // the last successor of u_in
1146      right = _thread[u];    // the node after it
1147
1148      // Handle the case when old_rev_thread equals to v_in
1149      // (it also means that join and v_out coincide)
1150      if (old_rev_thread == v_in) {
1151        last = _thread[_last_succ[u_out]];
1152      } else {
1153        last = _thread[v_in];
[601]1154      }
1155
[604]1156      // Update _thread and _parent along the stem nodes (i.e. the nodes
1157      // between u_in and u_out, whose parent have to be changed)
[601]1158      _thread[v_in] = stem = u_in;
[604]1159      _dirty_revs.clear();
1160      _dirty_revs.push_back(v_in);
[601]1161      par_stem = v_in;
1162      while (stem != u_out) {
[604]1163        // Insert the next stem node into the thread list
1164        new_stem = _parent[stem];
1165        _thread[u] = new_stem;
1166        _dirty_revs.push_back(u);
[601]1167
[604]1168        // Remove the subtree of stem from the thread list
1169        w = _rev_thread[stem];
1170        _thread[w] = right;
1171        _rev_thread[right] = w;
[601]1172
[604]1173        // Change the parent node and shift stem nodes
[601]1174        _parent[stem] = par_stem;
1175        par_stem = stem;
1176        stem = new_stem;
1177
[604]1178        // Update u and right
1179        u = _last_succ[stem] == _last_succ[par_stem] ?
1180          _rev_thread[par_stem] : _last_succ[stem];
[601]1181        right = _thread[u];
1182      }
1183      _parent[u_out] = par_stem;
1184      _thread[u] = last;
[604]1185      _rev_thread[last] = u;
1186      _last_succ[u_out] = u;
[601]1187
[604]1188      // Remove the subtree of u_out from the thread list except for
1189      // the case when old_rev_thread equals to v_in
1190      // (it also means that join and v_out coincide)
1191      if (old_rev_thread != v_in) {
1192        _thread[old_rev_thread] = right;
1193        _rev_thread[right] = old_rev_thread;
1194      }
1195
1196      // Update _rev_thread using the new _thread values
1197      for (int i = 0; i < int(_dirty_revs.size()); ++i) {
1198        u = _dirty_revs[i];
1199        _rev_thread[_thread[u]] = u;
1200      }
1201
1202      // Update _pred, _forward, _last_succ and _succ_num for the
1203      // stem nodes from u_out to u_in
1204      int tmp_sc = 0, tmp_ls = _last_succ[u_out];
1205      u = u_out;
1206      while (u != u_in) {
1207        w = _parent[u];
1208        _pred[u] = _pred[w];
1209        _forward[u] = !_forward[w];
1210        tmp_sc += _succ_num[u] - _succ_num[w];
1211        _succ_num[u] = tmp_sc;
1212        _last_succ[w] = tmp_ls;
1213        u = w;
1214      }
1215      _pred[u_in] = in_arc;
1216      _forward[u_in] = (u_in == _source[in_arc]);
1217      _succ_num[u_in] = old_succ_num;
1218
1219      // Set limits for updating _last_succ form v_in and v_out
1220      // towards the root
1221      int up_limit_in = -1;
1222      int up_limit_out = -1;
1223      if (_last_succ[join] == v_in) {
1224        up_limit_out = join;
[601]1225      } else {
[604]1226        up_limit_in = join;
1227      }
1228
1229      // Update _last_succ from v_in towards the root
1230      for (u = v_in; u != up_limit_in && _last_succ[u] == v_in;
1231           u = _parent[u]) {
1232        _last_succ[u] = _last_succ[u_out];
1233      }
1234      // Update _last_succ from v_out towards the root
1235      if (join != old_rev_thread && v_in != old_rev_thread) {
1236        for (u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
1237             u = _parent[u]) {
1238          _last_succ[u] = old_rev_thread;
1239        }
1240      } else {
1241        for (u = v_out; u != up_limit_out && _last_succ[u] == old_last_succ;
1242             u = _parent[u]) {
1243          _last_succ[u] = _last_succ[u_out];
1244        }
1245      }
1246
1247      // Update _succ_num from v_in to join
1248      for (u = v_in; u != join; u = _parent[u]) {
1249        _succ_num[u] += old_succ_num;
1250      }
1251      // Update _succ_num from v_out to join
1252      for (u = v_out; u != join; u = _parent[u]) {
1253        _succ_num[u] -= old_succ_num;
[601]1254      }
1255    }
1256
[604]1257    // Update potentials
1258    void updatePotential() {
[605]1259      Value sigma = _forward[u_in] ?
[601]1260        _pi[v_in] - _pi[u_in] - _cost[_pred[u_in]] :
1261        _pi[v_in] - _pi[u_in] + _cost[_pred[u_in]];
[604]1262      if (_succ_num[u_in] > _node_num / 2) {
1263        // Update in the upper subtree (which contains the root)
1264        int before = _rev_thread[u_in];
1265        int after = _thread[_last_succ[u_in]];
1266        _thread[before] = after;
1267        _pi[_root] -= sigma;
1268        for (int u = _thread[_root]; u != _root; u = _thread[u]) {
1269          _pi[u] -= sigma;
1270        }
1271        _thread[before] = u_in;
1272      } else {
1273        // Update in the lower subtree (which has been moved)
1274        int end = _thread[_last_succ[u_in]];
1275        for (int u = u_in; u != end; u = _thread[u]) {
1276          _pi[u] += sigma;
1277        }
[601]1278      }
1279    }
1280
1281    // Execute the algorithm
[605]1282    bool start(PivotRule pivot_rule) {
[601]1283      // Select the pivot rule implementation
1284      switch (pivot_rule) {
[605]1285        case FIRST_ELIGIBLE:
[601]1286          return start<FirstEligiblePivotRule>();
[605]1287        case BEST_ELIGIBLE:
[601]1288          return start<BestEligiblePivotRule>();
[605]1289        case BLOCK_SEARCH:
[601]1290          return start<BlockSearchPivotRule>();
[605]1291        case CANDIDATE_LIST:
[601]1292          return start<CandidateListPivotRule>();
[605]1293        case ALTERING_LIST:
[601]1294          return start<AlteringListPivotRule>();
1295      }
1296      return false;
1297    }
1298
[605]1299    template <typename PivotRuleImpl>
[601]1300    bool start() {
[605]1301      PivotRuleImpl pivot(*this);
[601]1302
[605]1303      // Execute the Network Simplex algorithm
[601]1304      while (pivot.findEnteringArc()) {
1305        findJoinNode();
1306        bool change = findLeavingArc();
1307        changeFlow(change);
1308        if (change) {
[604]1309          updateTreeStructure();
1310          updatePotential();
[601]1311        }
1312      }
1313
1314      // Check if the flow amount equals zero on all the artificial arcs
1315      for (int e = _arc_num; e != _arc_num + _node_num; ++e) {
1316        if (_flow[e] > 0) return false;
1317      }
1318
[603]1319      // Copy flow values to _flow_map
[605]1320      if (_plower) {
[601]1321        for (int i = 0; i != _arc_num; ++i) {
[603]1322          Arc e = _arc_ref[i];
[605]1323          _flow_map->set(e, (*_plower)[e] + _flow[i]);
[601]1324        }
1325      } else {
1326        for (int i = 0; i != _arc_num; ++i) {
[603]1327          _flow_map->set(_arc_ref[i], _flow[i]);
[601]1328        }
1329      }
[603]1330      // Copy potential values to _potential_map
1331      for (NodeIt n(_graph); n != INVALID; ++n) {
1332        _potential_map->set(n, _pi[_node_id[n]]);
[601]1333      }
1334
1335      return true;
1336    }
1337
1338  }; //class NetworkSimplex
1339
1340  ///@}
1341
1342} //namespace lemon
1343
1344#endif //LEMON_NETWORK_SIMPLEX_H
Note: See TracBrowser for help on using the repository browser.