COIN-OR::LEMON - Graph Library

source: lemon/lemon/network_simplex.h @ 655:6ac5d9ae1d3d

Last change on this file since 655:6ac5d9ae1d3d was 655:6ac5d9ae1d3d, checked in by Peter Kovacs <kpeter@…>, 15 years ago

Support real types + numerical stability fix in NS (#254)

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