COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/network_simplex.h @ 2633:4f47c0f6be04

Last change on this file since 2633:4f47c0f6be04 was 2630:d239741cfd44, checked in by Peter Kovacs, 15 years ago

Various improvements in NetworkSimplex?.

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