COIN-OR::LEMON - Graph Library

source: lemon-main/lemon/network_simplex.h @ 604:8c3112a66878

Last change on this file since 604:8c3112a66878 was 604:8c3112a66878, checked in by Peter Kovacs <kpeter@…>, 15 years ago

Use XTI implementation instead of ATI in NetworkSimplex? (#234)

XTI (eXtended Threaded Index) is an imporved version of the widely
known ATI (Augmented Threaded Index) method for storing and updating
the spanning tree structure in Network Simplex algorithms.

In the ATI data structure three indices are stored for each node:
predecessor, thread and depth. In the XTI data structure depth is
replaced by the number of successors and the last successor
(according to the thread index).

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