lemon/hartmann_orlin.h
author Peter Kovacs <kpeter@inf.elte.hu>
Thu, 12 Nov 2009 23:26:13 +0100
changeset 806 fa6f37d7a25b
parent 772 f964a00b9068
child 825 75e6020b19b1
permissions -rw-r--r--
Entirely rework CapacityScaling (#180)

- Use the new interface similarly to NetworkSimplex.
- Rework the implementation using an efficient internal structure
for handling the residual network. This improvement made the
code much faster (up to 2-5 times faster on large graphs).
- Handle GEQ supply type (LEQ is not supported).
- Handle negative costs for arcs of finite capacity.
(Note that this algorithm cannot handle arcs of negative cost
and infinite upper bound, thus it returns UNBOUNDED if such
an arc exists.)
- Extend the documentation.
     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_HARTMANN_ORLIN_H
    20 #define LEMON_HARTMANN_ORLIN_H
    21 
    22 /// \ingroup min_mean_cycle
    23 ///
    24 /// \file
    25 /// \brief Hartmann-Orlin's algorithm for finding a minimum mean cycle.
    26 
    27 #include <vector>
    28 #include <limits>
    29 #include <lemon/core.h>
    30 #include <lemon/path.h>
    31 #include <lemon/tolerance.h>
    32 #include <lemon/connectivity.h>
    33 
    34 namespace lemon {
    35 
    36   /// \brief Default traits class of HartmannOrlin algorithm.
    37   ///
    38   /// Default traits class of HartmannOrlin algorithm.
    39   /// \tparam GR The type of the digraph.
    40   /// \tparam LEN The type of the length map.
    41   /// It must conform to the \ref concepts::Rea_data "Rea_data" concept.
    42 #ifdef DOXYGEN
    43   template <typename GR, typename LEN>
    44 #else
    45   template <typename GR, typename LEN,
    46     bool integer = std::numeric_limits<typename LEN::Value>::is_integer>
    47 #endif
    48   struct HartmannOrlinDefaultTraits
    49   {
    50     /// The type of the digraph
    51     typedef GR Digraph;
    52     /// The type of the length map
    53     typedef LEN LengthMap;
    54     /// The type of the arc lengths
    55     typedef typename LengthMap::Value Value;
    56 
    57     /// \brief The large value type used for internal computations
    58     ///
    59     /// The large value type used for internal computations.
    60     /// It is \c long \c long if the \c Value type is integer,
    61     /// otherwise it is \c double.
    62     /// \c Value must be convertible to \c LargeValue.
    63     typedef double LargeValue;
    64 
    65     /// The tolerance type used for internal computations
    66     typedef lemon::Tolerance<LargeValue> Tolerance;
    67 
    68     /// \brief The path type of the found cycles
    69     ///
    70     /// The path type of the found cycles.
    71     /// It must conform to the \ref lemon::concepts::Path "Path" concept
    72     /// and it must have an \c addFront() function.
    73     typedef lemon::Path<Digraph> Path;
    74   };
    75 
    76   // Default traits class for integer value types
    77   template <typename GR, typename LEN>
    78   struct HartmannOrlinDefaultTraits<GR, LEN, true>
    79   {
    80     typedef GR Digraph;
    81     typedef LEN LengthMap;
    82     typedef typename LengthMap::Value Value;
    83 #ifdef LEMON_HAVE_LONG_LONG
    84     typedef long long LargeValue;
    85 #else
    86     typedef long LargeValue;
    87 #endif
    88     typedef lemon::Tolerance<LargeValue> Tolerance;
    89     typedef lemon::Path<Digraph> Path;
    90   };
    91 
    92 
    93   /// \addtogroup min_mean_cycle
    94   /// @{
    95 
    96   /// \brief Implementation of the Hartmann-Orlin algorithm for finding
    97   /// a minimum mean cycle.
    98   ///
    99   /// This class implements the Hartmann-Orlin algorithm for finding
   100   /// a directed cycle of minimum mean length (cost) in a digraph
   101   /// \ref amo93networkflows, \ref dasdan98minmeancycle.
   102   /// It is an improved version of \ref Karp "Karp"'s original algorithm,
   103   /// it applies an efficient early termination scheme.
   104   /// It runs in time O(ne) and uses space O(n<sup>2</sup>+e).
   105   ///
   106   /// \tparam GR The type of the digraph the algorithm runs on.
   107   /// \tparam LEN The type of the length map. The default
   108   /// map type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
   109 #ifdef DOXYGEN
   110   template <typename GR, typename LEN, typename TR>
   111 #else
   112   template < typename GR,
   113              typename LEN = typename GR::template ArcMap<int>,
   114              typename TR = HartmannOrlinDefaultTraits<GR, LEN> >
   115 #endif
   116   class HartmannOrlin
   117   {
   118   public:
   119 
   120     /// The type of the digraph
   121     typedef typename TR::Digraph Digraph;
   122     /// The type of the length map
   123     typedef typename TR::LengthMap LengthMap;
   124     /// The type of the arc lengths
   125     typedef typename TR::Value Value;
   126 
   127     /// \brief The large value type
   128     ///
   129     /// The large value type used for internal computations.
   130     /// Using the \ref HartmannOrlinDefaultTraits "default traits class",
   131     /// it is \c long \c long if the \c Value type is integer,
   132     /// otherwise it is \c double.
   133     typedef typename TR::LargeValue LargeValue;
   134 
   135     /// The tolerance type
   136     typedef typename TR::Tolerance Tolerance;
   137 
   138     /// \brief The path type of the found cycles
   139     ///
   140     /// The path type of the found cycles.
   141     /// Using the \ref HartmannOrlinDefaultTraits "default traits class",
   142     /// it is \ref lemon::Path "Path<Digraph>".
   143     typedef typename TR::Path Path;
   144 
   145     /// The \ref HartmannOrlinDefaultTraits "traits class" of the algorithm
   146     typedef TR Traits;
   147 
   148   private:
   149 
   150     TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
   151 
   152     // Data sturcture for path data
   153     struct PathData
   154     {
   155       LargeValue dist;
   156       Arc pred;
   157       PathData(LargeValue d, Arc p = INVALID) :
   158         dist(d), pred(p) {}
   159     };
   160 
   161     typedef typename Digraph::template NodeMap<std::vector<PathData> >
   162       PathDataNodeMap;
   163 
   164   private:
   165 
   166     // The digraph the algorithm runs on
   167     const Digraph &_gr;
   168     // The length of the arcs
   169     const LengthMap &_length;
   170 
   171     // Data for storing the strongly connected components
   172     int _comp_num;
   173     typename Digraph::template NodeMap<int> _comp;
   174     std::vector<std::vector<Node> > _comp_nodes;
   175     std::vector<Node>* _nodes;
   176     typename Digraph::template NodeMap<std::vector<Arc> > _out_arcs;
   177 
   178     // Data for the found cycles
   179     bool _curr_found, _best_found;
   180     LargeValue _curr_length, _best_length;
   181     int _curr_size, _best_size;
   182     Node _curr_node, _best_node;
   183     int _curr_level, _best_level;
   184 
   185     Path *_cycle_path;
   186     bool _local_path;
   187 
   188     // Node map for storing path data
   189     PathDataNodeMap _data;
   190     // The processed nodes in the last round
   191     std::vector<Node> _process;
   192 
   193     Tolerance _tolerance;
   194 
   195     // Infinite constant
   196     const LargeValue INF;
   197 
   198   public:
   199 
   200     /// \name Named Template Parameters
   201     /// @{
   202 
   203     template <typename T>
   204     struct SetLargeValueTraits : public Traits {
   205       typedef T LargeValue;
   206       typedef lemon::Tolerance<T> Tolerance;
   207     };
   208 
   209     /// \brief \ref named-templ-param "Named parameter" for setting
   210     /// \c LargeValue type.
   211     ///
   212     /// \ref named-templ-param "Named parameter" for setting \c LargeValue
   213     /// type. It is used for internal computations in the algorithm.
   214     template <typename T>
   215     struct SetLargeValue
   216       : public HartmannOrlin<GR, LEN, SetLargeValueTraits<T> > {
   217       typedef HartmannOrlin<GR, LEN, SetLargeValueTraits<T> > Create;
   218     };
   219 
   220     template <typename T>
   221     struct SetPathTraits : public Traits {
   222       typedef T Path;
   223     };
   224 
   225     /// \brief \ref named-templ-param "Named parameter" for setting
   226     /// \c %Path type.
   227     ///
   228     /// \ref named-templ-param "Named parameter" for setting the \c %Path
   229     /// type of the found cycles.
   230     /// It must conform to the \ref lemon::concepts::Path "Path" concept
   231     /// and it must have an \c addFront() function.
   232     template <typename T>
   233     struct SetPath
   234       : public HartmannOrlin<GR, LEN, SetPathTraits<T> > {
   235       typedef HartmannOrlin<GR, LEN, SetPathTraits<T> > Create;
   236     };
   237 
   238     /// @}
   239 
   240   public:
   241 
   242     /// \brief Constructor.
   243     ///
   244     /// The constructor of the class.
   245     ///
   246     /// \param digraph The digraph the algorithm runs on.
   247     /// \param length The lengths (costs) of the arcs.
   248     HartmannOrlin( const Digraph &digraph,
   249                    const LengthMap &length ) :
   250       _gr(digraph), _length(length), _comp(digraph), _out_arcs(digraph),
   251       _best_found(false), _best_length(0), _best_size(1),
   252       _cycle_path(NULL), _local_path(false), _data(digraph),
   253       INF(std::numeric_limits<LargeValue>::has_infinity ?
   254           std::numeric_limits<LargeValue>::infinity() :
   255           std::numeric_limits<LargeValue>::max())
   256     {}
   257 
   258     /// Destructor.
   259     ~HartmannOrlin() {
   260       if (_local_path) delete _cycle_path;
   261     }
   262 
   263     /// \brief Set the path structure for storing the found cycle.
   264     ///
   265     /// This function sets an external path structure for storing the
   266     /// found cycle.
   267     ///
   268     /// If you don't call this function before calling \ref run() or
   269     /// \ref findMinMean(), it will allocate a local \ref Path "path"
   270     /// structure. The destuctor deallocates this automatically
   271     /// allocated object, of course.
   272     ///
   273     /// \note The algorithm calls only the \ref lemon::Path::addFront()
   274     /// "addFront()" function of the given path structure.
   275     ///
   276     /// \return <tt>(*this)</tt>
   277     HartmannOrlin& cycle(Path &path) {
   278       if (_local_path) {
   279         delete _cycle_path;
   280         _local_path = false;
   281       }
   282       _cycle_path = &path;
   283       return *this;
   284     }
   285 
   286     /// \brief Set the tolerance used by the algorithm.
   287     ///
   288     /// This function sets the tolerance object used by the algorithm.
   289     ///
   290     /// \return <tt>(*this)</tt>
   291     HartmannOrlin& tolerance(const Tolerance& tolerance) {
   292       _tolerance = tolerance;
   293       return *this;
   294     }
   295 
   296     /// \brief Return a const reference to the tolerance.
   297     ///
   298     /// This function returns a const reference to the tolerance object
   299     /// used by the algorithm.
   300     const Tolerance& tolerance() const {
   301       return _tolerance;
   302     }
   303 
   304     /// \name Execution control
   305     /// The simplest way to execute the algorithm is to call the \ref run()
   306     /// function.\n
   307     /// If you only need the minimum mean length, you may call
   308     /// \ref findMinMean().
   309 
   310     /// @{
   311 
   312     /// \brief Run the algorithm.
   313     ///
   314     /// This function runs the algorithm.
   315     /// It can be called more than once (e.g. if the underlying digraph
   316     /// and/or the arc lengths have been modified).
   317     ///
   318     /// \return \c true if a directed cycle exists in the digraph.
   319     ///
   320     /// \note <tt>mmc.run()</tt> is just a shortcut of the following code.
   321     /// \code
   322     ///   return mmc.findMinMean() && mmc.findCycle();
   323     /// \endcode
   324     bool run() {
   325       return findMinMean() && findCycle();
   326     }
   327 
   328     /// \brief Find the minimum cycle mean.
   329     ///
   330     /// This function finds the minimum mean length of the directed
   331     /// cycles in the digraph.
   332     ///
   333     /// \return \c true if a directed cycle exists in the digraph.
   334     bool findMinMean() {
   335       // Initialization and find strongly connected components
   336       init();
   337       findComponents();
   338       
   339       // Find the minimum cycle mean in the components
   340       for (int comp = 0; comp < _comp_num; ++comp) {
   341         if (!initComponent(comp)) continue;
   342         processRounds();
   343         
   344         // Update the best cycle (global minimum mean cycle)
   345         if ( _curr_found && (!_best_found || 
   346              _curr_length * _best_size < _best_length * _curr_size) ) {
   347           _best_found = true;
   348           _best_length = _curr_length;
   349           _best_size = _curr_size;
   350           _best_node = _curr_node;
   351           _best_level = _curr_level;
   352         }
   353       }
   354       return _best_found;
   355     }
   356 
   357     /// \brief Find a minimum mean directed cycle.
   358     ///
   359     /// This function finds a directed cycle of minimum mean length
   360     /// in the digraph using the data computed by findMinMean().
   361     ///
   362     /// \return \c true if a directed cycle exists in the digraph.
   363     ///
   364     /// \pre \ref findMinMean() must be called before using this function.
   365     bool findCycle() {
   366       if (!_best_found) return false;
   367       IntNodeMap reached(_gr, -1);
   368       int r = _best_level + 1;
   369       Node u = _best_node;
   370       while (reached[u] < 0) {
   371         reached[u] = --r;
   372         u = _gr.source(_data[u][r].pred);
   373       }
   374       r = reached[u];
   375       Arc e = _data[u][r].pred;
   376       _cycle_path->addFront(e);
   377       _best_length = _length[e];
   378       _best_size = 1;
   379       Node v;
   380       while ((v = _gr.source(e)) != u) {
   381         e = _data[v][--r].pred;
   382         _cycle_path->addFront(e);
   383         _best_length += _length[e];
   384         ++_best_size;
   385       }
   386       return true;
   387     }
   388 
   389     /// @}
   390 
   391     /// \name Query Functions
   392     /// The results of the algorithm can be obtained using these
   393     /// functions.\n
   394     /// The algorithm should be executed before using them.
   395 
   396     /// @{
   397 
   398     /// \brief Return the total length of the found cycle.
   399     ///
   400     /// This function returns the total length of the found cycle.
   401     ///
   402     /// \pre \ref run() or \ref findMinMean() must be called before
   403     /// using this function.
   404     LargeValue cycleLength() const {
   405       return _best_length;
   406     }
   407 
   408     /// \brief Return the number of arcs on the found cycle.
   409     ///
   410     /// This function returns the number of arcs on the found cycle.
   411     ///
   412     /// \pre \ref run() or \ref findMinMean() must be called before
   413     /// using this function.
   414     int cycleArcNum() const {
   415       return _best_size;
   416     }
   417 
   418     /// \brief Return the mean length of the found cycle.
   419     ///
   420     /// This function returns the mean length of the found cycle.
   421     ///
   422     /// \note <tt>alg.cycleMean()</tt> is just a shortcut of the
   423     /// following code.
   424     /// \code
   425     ///   return static_cast<double>(alg.cycleLength()) / alg.cycleArcNum();
   426     /// \endcode
   427     ///
   428     /// \pre \ref run() or \ref findMinMean() must be called before
   429     /// using this function.
   430     double cycleMean() const {
   431       return static_cast<double>(_best_length) / _best_size;
   432     }
   433 
   434     /// \brief Return the found cycle.
   435     ///
   436     /// This function returns a const reference to the path structure
   437     /// storing the found cycle.
   438     ///
   439     /// \pre \ref run() or \ref findCycle() must be called before using
   440     /// this function.
   441     const Path& cycle() const {
   442       return *_cycle_path;
   443     }
   444 
   445     ///@}
   446 
   447   private:
   448 
   449     // Initialization
   450     void init() {
   451       if (!_cycle_path) {
   452         _local_path = true;
   453         _cycle_path = new Path;
   454       }
   455       _cycle_path->clear();
   456       _best_found = false;
   457       _best_length = 0;
   458       _best_size = 1;
   459       _cycle_path->clear();
   460       for (NodeIt u(_gr); u != INVALID; ++u)
   461         _data[u].clear();
   462     }
   463 
   464     // Find strongly connected components and initialize _comp_nodes
   465     // and _out_arcs
   466     void findComponents() {
   467       _comp_num = stronglyConnectedComponents(_gr, _comp);
   468       _comp_nodes.resize(_comp_num);
   469       if (_comp_num == 1) {
   470         _comp_nodes[0].clear();
   471         for (NodeIt n(_gr); n != INVALID; ++n) {
   472           _comp_nodes[0].push_back(n);
   473           _out_arcs[n].clear();
   474           for (OutArcIt a(_gr, n); a != INVALID; ++a) {
   475             _out_arcs[n].push_back(a);
   476           }
   477         }
   478       } else {
   479         for (int i = 0; i < _comp_num; ++i)
   480           _comp_nodes[i].clear();
   481         for (NodeIt n(_gr); n != INVALID; ++n) {
   482           int k = _comp[n];
   483           _comp_nodes[k].push_back(n);
   484           _out_arcs[n].clear();
   485           for (OutArcIt a(_gr, n); a != INVALID; ++a) {
   486             if (_comp[_gr.target(a)] == k) _out_arcs[n].push_back(a);
   487           }
   488         }
   489       }
   490     }
   491 
   492     // Initialize path data for the current component
   493     bool initComponent(int comp) {
   494       _nodes = &(_comp_nodes[comp]);
   495       int n = _nodes->size();
   496       if (n < 1 || (n == 1 && _out_arcs[(*_nodes)[0]].size() == 0)) {
   497         return false;
   498       }      
   499       for (int i = 0; i < n; ++i) {
   500         _data[(*_nodes)[i]].resize(n + 1, PathData(INF));
   501       }
   502       return true;
   503     }
   504 
   505     // Process all rounds of computing path data for the current component.
   506     // _data[v][k] is the length of a shortest directed walk from the root
   507     // node to node v containing exactly k arcs.
   508     void processRounds() {
   509       Node start = (*_nodes)[0];
   510       _data[start][0] = PathData(0);
   511       _process.clear();
   512       _process.push_back(start);
   513 
   514       int k, n = _nodes->size();
   515       int next_check = 4;
   516       bool terminate = false;
   517       for (k = 1; k <= n && int(_process.size()) < n && !terminate; ++k) {
   518         processNextBuildRound(k);
   519         if (k == next_check || k == n) {
   520           terminate = checkTermination(k);
   521           next_check = next_check * 3 / 2;
   522         }
   523       }
   524       for ( ; k <= n && !terminate; ++k) {
   525         processNextFullRound(k);
   526         if (k == next_check || k == n) {
   527           terminate = checkTermination(k);
   528           next_check = next_check * 3 / 2;
   529         }
   530       }
   531     }
   532 
   533     // Process one round and rebuild _process
   534     void processNextBuildRound(int k) {
   535       std::vector<Node> next;
   536       Node u, v;
   537       Arc e;
   538       LargeValue d;
   539       for (int i = 0; i < int(_process.size()); ++i) {
   540         u = _process[i];
   541         for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
   542           e = _out_arcs[u][j];
   543           v = _gr.target(e);
   544           d = _data[u][k-1].dist + _length[e];
   545           if (_tolerance.less(d, _data[v][k].dist)) {
   546             if (_data[v][k].dist == INF) next.push_back(v);
   547             _data[v][k] = PathData(d, e);
   548           }
   549         }
   550       }
   551       _process.swap(next);
   552     }
   553 
   554     // Process one round using _nodes instead of _process
   555     void processNextFullRound(int k) {
   556       Node u, v;
   557       Arc e;
   558       LargeValue d;
   559       for (int i = 0; i < int(_nodes->size()); ++i) {
   560         u = (*_nodes)[i];
   561         for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
   562           e = _out_arcs[u][j];
   563           v = _gr.target(e);
   564           d = _data[u][k-1].dist + _length[e];
   565           if (_tolerance.less(d, _data[v][k].dist)) {
   566             _data[v][k] = PathData(d, e);
   567           }
   568         }
   569       }
   570     }
   571     
   572     // Check early termination
   573     bool checkTermination(int k) {
   574       typedef std::pair<int, int> Pair;
   575       typename GR::template NodeMap<Pair> level(_gr, Pair(-1, 0));
   576       typename GR::template NodeMap<LargeValue> pi(_gr);
   577       int n = _nodes->size();
   578       LargeValue length;
   579       int size;
   580       Node u;
   581       
   582       // Search for cycles that are already found
   583       _curr_found = false;
   584       for (int i = 0; i < n; ++i) {
   585         u = (*_nodes)[i];
   586         if (_data[u][k].dist == INF) continue;
   587         for (int j = k; j >= 0; --j) {
   588           if (level[u].first == i && level[u].second > 0) {
   589             // A cycle is found
   590             length = _data[u][level[u].second].dist - _data[u][j].dist;
   591             size = level[u].second - j;
   592             if (!_curr_found || length * _curr_size < _curr_length * size) {
   593               _curr_length = length;
   594               _curr_size = size;
   595               _curr_node = u;
   596               _curr_level = level[u].second;
   597               _curr_found = true;
   598             }
   599           }
   600           level[u] = Pair(i, j);
   601           if (j != 0) {
   602 	    u = _gr.source(_data[u][j].pred);
   603 	  }
   604         }
   605       }
   606 
   607       // If at least one cycle is found, check the optimality condition
   608       LargeValue d;
   609       if (_curr_found && k < n) {
   610         // Find node potentials
   611         for (int i = 0; i < n; ++i) {
   612           u = (*_nodes)[i];
   613           pi[u] = INF;
   614           for (int j = 0; j <= k; ++j) {
   615             if (_data[u][j].dist < INF) {
   616               d = _data[u][j].dist * _curr_size - j * _curr_length;
   617               if (_tolerance.less(d, pi[u])) pi[u] = d;
   618             }
   619           }
   620         }
   621 
   622         // Check the optimality condition for all arcs
   623         bool done = true;
   624         for (ArcIt a(_gr); a != INVALID; ++a) {
   625           if (_tolerance.less(_length[a] * _curr_size - _curr_length,
   626                               pi[_gr.target(a)] - pi[_gr.source(a)]) ) {
   627             done = false;
   628             break;
   629           }
   630         }
   631         return done;
   632       }
   633       return (k == n);
   634     }
   635 
   636   }; //class HartmannOrlin
   637 
   638   ///@}
   639 
   640 } //namespace lemon
   641 
   642 #endif //LEMON_HARTMANN_ORLIN_H