lemon/karp_mmc.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 936 ddd3c0d3d9bf
parent 864 d3ea191c3412
child 1002 f63ba40a60f4
permissions -rw-r--r--
Implement the scaling Price Refinement heuristic in CostScaling (#417)
instead of Early Termination.

These two heuristics are similar, but the newer one is faster
and not only makes it possible to skip some epsilon phases, but
it can improve the performance of the other phases, as well.
     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-2010
     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_KARP_MMC_H
    20 #define LEMON_KARP_MMC_H
    21 
    22 /// \ingroup min_mean_cycle
    23 ///
    24 /// \file
    25 /// \brief Karp'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 KarpMmc class.
    37   ///
    38   /// Default traits class of KarpMmc class.
    39   /// \tparam GR The type of the digraph.
    40   /// \tparam CM The type of the cost map.
    41   /// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
    42 #ifdef DOXYGEN
    43   template <typename GR, typename CM>
    44 #else
    45   template <typename GR, typename CM,
    46     bool integer = std::numeric_limits<typename CM::Value>::is_integer>
    47 #endif
    48   struct KarpMmcDefaultTraits
    49   {
    50     /// The type of the digraph
    51     typedef GR Digraph;
    52     /// The type of the cost map
    53     typedef CM CostMap;
    54     /// The type of the arc costs
    55     typedef typename CostMap::Value Cost;
    56 
    57     /// \brief The large cost type used for internal computations
    58     ///
    59     /// The large cost type used for internal computations.
    60     /// It is \c long \c long if the \c Cost type is integer,
    61     /// otherwise it is \c double.
    62     /// \c Cost must be convertible to \c LargeCost.
    63     typedef double LargeCost;
    64 
    65     /// The tolerance type used for internal computations
    66     typedef lemon::Tolerance<LargeCost> 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 cost types
    77   template <typename GR, typename CM>
    78   struct KarpMmcDefaultTraits<GR, CM, true>
    79   {
    80     typedef GR Digraph;
    81     typedef CM CostMap;
    82     typedef typename CostMap::Value Cost;
    83 #ifdef LEMON_HAVE_LONG_LONG
    84     typedef long long LargeCost;
    85 #else
    86     typedef long LargeCost;
    87 #endif
    88     typedef lemon::Tolerance<LargeCost> Tolerance;
    89     typedef lemon::Path<Digraph> Path;
    90   };
    91 
    92 
    93   /// \addtogroup min_mean_cycle
    94   /// @{
    95 
    96   /// \brief Implementation of Karp's algorithm for finding a minimum
    97   /// mean cycle.
    98   ///
    99   /// This class implements Karp's algorithm for finding a directed
   100   /// cycle of minimum mean cost in a digraph
   101   /// \ref amo93networkflows, \ref dasdan98minmeancycle.
   102   /// It runs in time O(ne) and uses space O(n<sup>2</sup>+e).
   103   ///
   104   /// \tparam GR The type of the digraph the algorithm runs on.
   105   /// \tparam CM The type of the cost map. The default
   106   /// map type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
   107   /// \tparam TR The traits class that defines various types used by the
   108   /// algorithm. By default, it is \ref KarpMmcDefaultTraits
   109   /// "KarpMmcDefaultTraits<GR, CM>".
   110   /// In most cases, this parameter should not be set directly,
   111   /// consider to use the named template parameters instead.
   112 #ifdef DOXYGEN
   113   template <typename GR, typename CM, typename TR>
   114 #else
   115   template < typename GR,
   116              typename CM = typename GR::template ArcMap<int>,
   117              typename TR = KarpMmcDefaultTraits<GR, CM> >
   118 #endif
   119   class KarpMmc
   120   {
   121   public:
   122 
   123     /// The type of the digraph
   124     typedef typename TR::Digraph Digraph;
   125     /// The type of the cost map
   126     typedef typename TR::CostMap CostMap;
   127     /// The type of the arc costs
   128     typedef typename TR::Cost Cost;
   129 
   130     /// \brief The large cost type
   131     ///
   132     /// The large cost type used for internal computations.
   133     /// By default, it is \c long \c long if the \c Cost type is integer,
   134     /// otherwise it is \c double.
   135     typedef typename TR::LargeCost LargeCost;
   136 
   137     /// The tolerance type
   138     typedef typename TR::Tolerance Tolerance;
   139 
   140     /// \brief The path type of the found cycles
   141     ///
   142     /// The path type of the found cycles.
   143     /// Using the \ref KarpMmcDefaultTraits "default traits class",
   144     /// it is \ref lemon::Path "Path<Digraph>".
   145     typedef typename TR::Path Path;
   146 
   147     /// The \ref KarpMmcDefaultTraits "traits class" of the algorithm
   148     typedef TR Traits;
   149 
   150   private:
   151 
   152     TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
   153 
   154     // Data sturcture for path data
   155     struct PathData
   156     {
   157       LargeCost dist;
   158       Arc pred;
   159       PathData(LargeCost d, Arc p = INVALID) :
   160         dist(d), pred(p) {}
   161     };
   162 
   163     typedef typename Digraph::template NodeMap<std::vector<PathData> >
   164       PathDataNodeMap;
   165 
   166   private:
   167 
   168     // The digraph the algorithm runs on
   169     const Digraph &_gr;
   170     // The cost of the arcs
   171     const CostMap &_cost;
   172 
   173     // Data for storing the strongly connected components
   174     int _comp_num;
   175     typename Digraph::template NodeMap<int> _comp;
   176     std::vector<std::vector<Node> > _comp_nodes;
   177     std::vector<Node>* _nodes;
   178     typename Digraph::template NodeMap<std::vector<Arc> > _out_arcs;
   179 
   180     // Data for the found cycle
   181     LargeCost _cycle_cost;
   182     int _cycle_size;
   183     Node _cycle_node;
   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 LargeCost INF;
   197 
   198   public:
   199 
   200     /// \name Named Template Parameters
   201     /// @{
   202 
   203     template <typename T>
   204     struct SetLargeCostTraits : public Traits {
   205       typedef T LargeCost;
   206       typedef lemon::Tolerance<T> Tolerance;
   207     };
   208 
   209     /// \brief \ref named-templ-param "Named parameter" for setting
   210     /// \c LargeCost type.
   211     ///
   212     /// \ref named-templ-param "Named parameter" for setting \c LargeCost
   213     /// type. It is used for internal computations in the algorithm.
   214     template <typename T>
   215     struct SetLargeCost
   216       : public KarpMmc<GR, CM, SetLargeCostTraits<T> > {
   217       typedef KarpMmc<GR, CM, SetLargeCostTraits<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 KarpMmc<GR, CM, SetPathTraits<T> > {
   235       typedef KarpMmc<GR, CM, SetPathTraits<T> > Create;
   236     };
   237 
   238     /// @}
   239 
   240   protected:
   241 
   242     KarpMmc() {}
   243 
   244   public:
   245 
   246     /// \brief Constructor.
   247     ///
   248     /// The constructor of the class.
   249     ///
   250     /// \param digraph The digraph the algorithm runs on.
   251     /// \param cost The costs of the arcs.
   252     KarpMmc( const Digraph &digraph,
   253              const CostMap &cost ) :
   254       _gr(digraph), _cost(cost), _comp(digraph), _out_arcs(digraph),
   255       _cycle_cost(0), _cycle_size(1), _cycle_node(INVALID),
   256       _cycle_path(NULL), _local_path(false), _data(digraph),
   257       INF(std::numeric_limits<LargeCost>::has_infinity ?
   258           std::numeric_limits<LargeCost>::infinity() :
   259           std::numeric_limits<LargeCost>::max())
   260     {}
   261 
   262     /// Destructor.
   263     ~KarpMmc() {
   264       if (_local_path) delete _cycle_path;
   265     }
   266 
   267     /// \brief Set the path structure for storing the found cycle.
   268     ///
   269     /// This function sets an external path structure for storing the
   270     /// found cycle.
   271     ///
   272     /// If you don't call this function before calling \ref run() or
   273     /// \ref findCycleMean(), it will allocate a local \ref Path "path"
   274     /// structure. The destuctor deallocates this automatically
   275     /// allocated object, of course.
   276     ///
   277     /// \note The algorithm calls only the \ref lemon::Path::addFront()
   278     /// "addFront()" function of the given path structure.
   279     ///
   280     /// \return <tt>(*this)</tt>
   281     KarpMmc& cycle(Path &path) {
   282       if (_local_path) {
   283         delete _cycle_path;
   284         _local_path = false;
   285       }
   286       _cycle_path = &path;
   287       return *this;
   288     }
   289 
   290     /// \brief Set the tolerance used by the algorithm.
   291     ///
   292     /// This function sets the tolerance object used by the algorithm.
   293     ///
   294     /// \return <tt>(*this)</tt>
   295     KarpMmc& tolerance(const Tolerance& tolerance) {
   296       _tolerance = tolerance;
   297       return *this;
   298     }
   299 
   300     /// \brief Return a const reference to the tolerance.
   301     ///
   302     /// This function returns a const reference to the tolerance object
   303     /// used by the algorithm.
   304     const Tolerance& tolerance() const {
   305       return _tolerance;
   306     }
   307 
   308     /// \name Execution control
   309     /// The simplest way to execute the algorithm is to call the \ref run()
   310     /// function.\n
   311     /// If you only need the minimum mean cost, you may call
   312     /// \ref findCycleMean().
   313 
   314     /// @{
   315 
   316     /// \brief Run the algorithm.
   317     ///
   318     /// This function runs the algorithm.
   319     /// It can be called more than once (e.g. if the underlying digraph
   320     /// and/or the arc costs have been modified).
   321     ///
   322     /// \return \c true if a directed cycle exists in the digraph.
   323     ///
   324     /// \note <tt>mmc.run()</tt> is just a shortcut of the following code.
   325     /// \code
   326     ///   return mmc.findCycleMean() && mmc.findCycle();
   327     /// \endcode
   328     bool run() {
   329       return findCycleMean() && findCycle();
   330     }
   331 
   332     /// \brief Find the minimum cycle mean.
   333     ///
   334     /// This function finds the minimum mean cost of the directed
   335     /// cycles in the digraph.
   336     ///
   337     /// \return \c true if a directed cycle exists in the digraph.
   338     bool findCycleMean() {
   339       // Initialization and find strongly connected components
   340       init();
   341       findComponents();
   342 
   343       // Find the minimum cycle mean in the components
   344       for (int comp = 0; comp < _comp_num; ++comp) {
   345         if (!initComponent(comp)) continue;
   346         processRounds();
   347         updateMinMean();
   348       }
   349       return (_cycle_node != INVALID);
   350     }
   351 
   352     /// \brief Find a minimum mean directed cycle.
   353     ///
   354     /// This function finds a directed cycle of minimum mean cost
   355     /// in the digraph using the data computed by findCycleMean().
   356     ///
   357     /// \return \c true if a directed cycle exists in the digraph.
   358     ///
   359     /// \pre \ref findCycleMean() must be called before using this function.
   360     bool findCycle() {
   361       if (_cycle_node == INVALID) return false;
   362       IntNodeMap reached(_gr, -1);
   363       int r = _data[_cycle_node].size();
   364       Node u = _cycle_node;
   365       while (reached[u] < 0) {
   366         reached[u] = --r;
   367         u = _gr.source(_data[u][r].pred);
   368       }
   369       r = reached[u];
   370       Arc e = _data[u][r].pred;
   371       _cycle_path->addFront(e);
   372       _cycle_cost = _cost[e];
   373       _cycle_size = 1;
   374       Node v;
   375       while ((v = _gr.source(e)) != u) {
   376         e = _data[v][--r].pred;
   377         _cycle_path->addFront(e);
   378         _cycle_cost += _cost[e];
   379         ++_cycle_size;
   380       }
   381       return true;
   382     }
   383 
   384     /// @}
   385 
   386     /// \name Query Functions
   387     /// The results of the algorithm can be obtained using these
   388     /// functions.\n
   389     /// The algorithm should be executed before using them.
   390 
   391     /// @{
   392 
   393     /// \brief Return the total cost of the found cycle.
   394     ///
   395     /// This function returns the total cost of the found cycle.
   396     ///
   397     /// \pre \ref run() or \ref findCycleMean() must be called before
   398     /// using this function.
   399     Cost cycleCost() const {
   400       return static_cast<Cost>(_cycle_cost);
   401     }
   402 
   403     /// \brief Return the number of arcs on the found cycle.
   404     ///
   405     /// This function returns the number of arcs on the found cycle.
   406     ///
   407     /// \pre \ref run() or \ref findCycleMean() must be called before
   408     /// using this function.
   409     int cycleSize() const {
   410       return _cycle_size;
   411     }
   412 
   413     /// \brief Return the mean cost of the found cycle.
   414     ///
   415     /// This function returns the mean cost of the found cycle.
   416     ///
   417     /// \note <tt>alg.cycleMean()</tt> is just a shortcut of the
   418     /// following code.
   419     /// \code
   420     ///   return static_cast<double>(alg.cycleCost()) / alg.cycleSize();
   421     /// \endcode
   422     ///
   423     /// \pre \ref run() or \ref findCycleMean() must be called before
   424     /// using this function.
   425     double cycleMean() const {
   426       return static_cast<double>(_cycle_cost) / _cycle_size;
   427     }
   428 
   429     /// \brief Return the found cycle.
   430     ///
   431     /// This function returns a const reference to the path structure
   432     /// storing the found cycle.
   433     ///
   434     /// \pre \ref run() or \ref findCycle() must be called before using
   435     /// this function.
   436     const Path& cycle() const {
   437       return *_cycle_path;
   438     }
   439 
   440     ///@}
   441 
   442   private:
   443 
   444     // Initialization
   445     void init() {
   446       if (!_cycle_path) {
   447         _local_path = true;
   448         _cycle_path = new Path;
   449       }
   450       _cycle_path->clear();
   451       _cycle_cost = 0;
   452       _cycle_size = 1;
   453       _cycle_node = INVALID;
   454       for (NodeIt u(_gr); u != INVALID; ++u)
   455         _data[u].clear();
   456     }
   457 
   458     // Find strongly connected components and initialize _comp_nodes
   459     // and _out_arcs
   460     void findComponents() {
   461       _comp_num = stronglyConnectedComponents(_gr, _comp);
   462       _comp_nodes.resize(_comp_num);
   463       if (_comp_num == 1) {
   464         _comp_nodes[0].clear();
   465         for (NodeIt n(_gr); n != INVALID; ++n) {
   466           _comp_nodes[0].push_back(n);
   467           _out_arcs[n].clear();
   468           for (OutArcIt a(_gr, n); a != INVALID; ++a) {
   469             _out_arcs[n].push_back(a);
   470           }
   471         }
   472       } else {
   473         for (int i = 0; i < _comp_num; ++i)
   474           _comp_nodes[i].clear();
   475         for (NodeIt n(_gr); n != INVALID; ++n) {
   476           int k = _comp[n];
   477           _comp_nodes[k].push_back(n);
   478           _out_arcs[n].clear();
   479           for (OutArcIt a(_gr, n); a != INVALID; ++a) {
   480             if (_comp[_gr.target(a)] == k) _out_arcs[n].push_back(a);
   481           }
   482         }
   483       }
   484     }
   485 
   486     // Initialize path data for the current component
   487     bool initComponent(int comp) {
   488       _nodes = &(_comp_nodes[comp]);
   489       int n = _nodes->size();
   490       if (n < 1 || (n == 1 && _out_arcs[(*_nodes)[0]].size() == 0)) {
   491         return false;
   492       }
   493       for (int i = 0; i < n; ++i) {
   494         _data[(*_nodes)[i]].resize(n + 1, PathData(INF));
   495       }
   496       return true;
   497     }
   498 
   499     // Process all rounds of computing path data for the current component.
   500     // _data[v][k] is the cost of a shortest directed walk from the root
   501     // node to node v containing exactly k arcs.
   502     void processRounds() {
   503       Node start = (*_nodes)[0];
   504       _data[start][0] = PathData(0);
   505       _process.clear();
   506       _process.push_back(start);
   507 
   508       int k, n = _nodes->size();
   509       for (k = 1; k <= n && int(_process.size()) < n; ++k) {
   510         processNextBuildRound(k);
   511       }
   512       for ( ; k <= n; ++k) {
   513         processNextFullRound(k);
   514       }
   515     }
   516 
   517     // Process one round and rebuild _process
   518     void processNextBuildRound(int k) {
   519       std::vector<Node> next;
   520       Node u, v;
   521       Arc e;
   522       LargeCost d;
   523       for (int i = 0; i < int(_process.size()); ++i) {
   524         u = _process[i];
   525         for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
   526           e = _out_arcs[u][j];
   527           v = _gr.target(e);
   528           d = _data[u][k-1].dist + _cost[e];
   529           if (_tolerance.less(d, _data[v][k].dist)) {
   530             if (_data[v][k].dist == INF) next.push_back(v);
   531             _data[v][k] = PathData(d, e);
   532           }
   533         }
   534       }
   535       _process.swap(next);
   536     }
   537 
   538     // Process one round using _nodes instead of _process
   539     void processNextFullRound(int k) {
   540       Node u, v;
   541       Arc e;
   542       LargeCost d;
   543       for (int i = 0; i < int(_nodes->size()); ++i) {
   544         u = (*_nodes)[i];
   545         for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
   546           e = _out_arcs[u][j];
   547           v = _gr.target(e);
   548           d = _data[u][k-1].dist + _cost[e];
   549           if (_tolerance.less(d, _data[v][k].dist)) {
   550             _data[v][k] = PathData(d, e);
   551           }
   552         }
   553       }
   554     }
   555 
   556     // Update the minimum cycle mean
   557     void updateMinMean() {
   558       int n = _nodes->size();
   559       for (int i = 0; i < n; ++i) {
   560         Node u = (*_nodes)[i];
   561         if (_data[u][n].dist == INF) continue;
   562         LargeCost cost, max_cost = 0;
   563         int size, max_size = 1;
   564         bool found_curr = false;
   565         for (int k = 0; k < n; ++k) {
   566           if (_data[u][k].dist == INF) continue;
   567           cost = _data[u][n].dist - _data[u][k].dist;
   568           size = n - k;
   569           if (!found_curr || cost * max_size > max_cost * size) {
   570             found_curr = true;
   571             max_cost = cost;
   572             max_size = size;
   573           }
   574         }
   575         if ( found_curr && (_cycle_node == INVALID ||
   576              max_cost * _cycle_size < _cycle_cost * max_size) ) {
   577           _cycle_cost = max_cost;
   578           _cycle_size = max_size;
   579           _cycle_node = u;
   580         }
   581       }
   582     }
   583 
   584   }; //class KarpMmc
   585 
   586   ///@}
   587 
   588 } //namespace lemon
   589 
   590 #endif //LEMON_KARP_MMC_H