COIN-OR::LEMON - Graph Library

source: lemon-main/lemon/network_simplex.h @ 603:425cc8328c0e

Last change on this file since 603:425cc8328c0e was 603:425cc8328c0e, checked in by Peter Kovacs <kpeter@…>, 15 years ago

Internal restructuring and renamings in NetworkSimplex? (#234)

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