lemon/min_mean_cycle.h
author alpar
Mon, 07 Jan 2008 13:09:48 +0000
changeset 2553 bfced05fa852
parent 2529 93de38566e6c
child 2555 a84e52e99f57
permissions -rw-r--r--
Happy New Year to LEMON (+ better update-copyright-header script)
     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_MIN_MEAN_CYCLE_H
    20 #define LEMON_MIN_MEAN_CYCLE_H
    21 
    22 /// \ingroup shortest_path
    23 ///
    24 /// \file
    25 /// \brief Karp's algorithm for finding a minimum mean (directed) cycle.
    26 
    27 #include <vector>
    28 #include <lemon/graph_utils.h>
    29 #include <lemon/topology.h>
    30 #include <lemon/path.h>
    31 
    32 namespace lemon {
    33 
    34   /// \addtogroup shortest_path
    35   /// @{
    36 
    37   /// \brief Implementation of Karp's algorithm for finding a
    38   /// minimum mean (directed) cycle.
    39   ///
    40   /// The \ref lemon::MinMeanCycle "MinMeanCycle" implements Karp's
    41   /// algorithm for finding a minimum mean (directed) cycle.
    42   ///
    43   /// \param Graph The directed graph type the algorithm runs on.
    44   /// \param LengthMap The type of the length (cost) map.
    45   ///
    46   /// \author Peter Kovacs
    47 
    48   template <typename Graph,
    49     typename LengthMap = typename Graph::template EdgeMap<int> >
    50   class MinMeanCycle
    51   {
    52     typedef typename Graph::Node Node;
    53     typedef typename Graph::NodeIt NodeIt;
    54     typedef typename Graph::Edge Edge;
    55     typedef typename Graph::EdgeIt EdgeIt;
    56     typedef typename Graph::OutEdgeIt OutEdgeIt;
    57 
    58     typedef typename LengthMap::Value Length;
    59 
    60     typedef typename Graph::template NodeMap<int> IntNodeMap;
    61     typedef typename Graph::template NodeMap<Edge> PredNodeMap;
    62     typedef Path<Graph> Path;
    63     typedef std::vector<Node> NodeVector;
    64 
    65   protected:
    66 
    67     /// \brief Data structure for path data.
    68     struct PathData
    69     {
    70       bool found;
    71       Length dist;
    72       Edge pred;
    73       PathData(bool _found = false, Length _dist = 0) :
    74 	found(_found), dist(_dist), pred(INVALID) {}
    75       PathData(bool _found, Length _dist, Edge _pred) :
    76 	found(_found), dist(_dist), pred(_pred) {}
    77     };
    78 
    79   private:
    80 
    81     typedef typename Graph::template NodeMap<std::vector<PathData> >
    82       PathDataNodeMap;
    83 
    84   protected:
    85 
    86     /// \brief Node map for storing path data.
    87     ///
    88     /// Node map for storing path data of all nodes in the current
    89     /// component. dmap[v][k] is the length of a shortest directed walk
    90     /// to node v from the starting node containing exactly k edges.
    91     PathDataNodeMap dmap;
    92 
    93     /// \brief The directed graph the algorithm runs on.
    94     const Graph &graph;
    95     /// \brief The length of the edges.
    96     const LengthMap &length;
    97 
    98     /// \brief The total length of the found cycle.
    99     Length cycle_length;
   100     /// \brief The number of edges in the found cycle.
   101     int cycle_size;
   102     /// \brief A node for obtaining a minimum mean cycle.
   103     Node cycle_node;
   104 
   105     /// \brief The found cycle.
   106     Path *cycle_path;
   107     /// \brief The algorithm uses local \ref lemon::Path "Path"
   108     /// structure to store the found cycle.
   109     bool local_path;
   110 
   111     /// \brief Node map for identifying strongly connected components.
   112     IntNodeMap comp;
   113     /// \brief The number of strongly connected components.
   114     int comp_num;
   115     /// \brief Counter for identifying the current component.
   116     int comp_cnt;
   117     /// \brief Nodes of the current component.
   118     NodeVector nodes;
   119     /// \brief The processed nodes in the last round.
   120     NodeVector process;
   121 
   122   public :
   123 
   124     /// \brief The constructor of the class.
   125     ///
   126     /// The constructor of the class.
   127     ///
   128     /// \param _graph The directed graph the algorithm runs on.
   129     /// \param _length The length (cost) of the edges.
   130     MinMeanCycle( const Graph &_graph,
   131 		  const LengthMap &_length ) :
   132       graph(_graph), length(_length), dmap(_graph), comp(_graph),
   133       cycle_length(0), cycle_size(-1), cycle_node(INVALID),
   134       cycle_path(NULL), local_path(false)
   135     { }
   136 
   137     /// \brief The destructor of the class.
   138     ~MinMeanCycle() {
   139       if (local_path) delete cycle_path;
   140     }
   141 
   142   protected:
   143 
   144     /// \brief Initializes the internal data structures for the current
   145     /// component.
   146     void initCurrent() {
   147       nodes.clear();
   148       // Finding the nodes of the current component
   149       for (NodeIt v(graph); v != INVALID; ++v) {
   150 	if (comp[v] == comp_cnt) nodes.push_back(v);
   151       }
   152       // Creating vectors for all nodes
   153       int n = nodes.size();
   154       for (int i = 0; i < n; ++i) {
   155 	dmap[nodes[i]].resize(n + 1);
   156       }
   157     }
   158 
   159     /// \brief Processes all rounds of computing required path data for
   160     /// the current component.
   161     void processRounds() {
   162       dmap[nodes[0]][0] = PathData(true, 0);
   163       process.clear();
   164       // Processing the first round
   165       for (OutEdgeIt e(graph, nodes[0]); e != INVALID; ++e) {
   166 	Node v = graph.target(e);
   167 	if (comp[v] != comp_cnt || v == nodes[0]) continue;
   168 	dmap[v][1] = PathData(true, length[e], e);
   169 	process.push_back(v);
   170       }
   171       // Processing other rounds
   172       int n = nodes.size(), k;
   173       for (k = 2; k <= n && process.size() < n; ++k)
   174 	processNextBuildRound(k);
   175       for ( ; k <= n; ++k)
   176 	processNextFullRound(k);
   177     }
   178 
   179     /// \brief Processes one round of computing required path data and
   180     /// rebuilds \ref process vector.
   181     void processNextBuildRound(int k) {
   182       NodeVector next;
   183       for (int i = 0; i < process.size(); ++i) {
   184 	for (OutEdgeIt e(graph, process[i]); e != INVALID; ++e) {
   185 	  Node v = graph.target(e);
   186 	  if (comp[v] != comp_cnt) continue;
   187 	  if (!dmap[v][k].found) {
   188 	    next.push_back(v);
   189 	    dmap[v][k] = PathData(true, dmap[process[i]][k-1].dist + length[e], e);
   190 	  }
   191 	  else if (dmap[process[i]][k-1].dist + length[e] < dmap[v][k].dist) {
   192 	    dmap[v][k] = PathData(true, dmap[process[i]][k-1].dist + length[e], e);
   193 	  }
   194 	}
   195       }
   196       process.swap(next);
   197     }
   198 
   199     /// \brief Processes one round of computing required path data
   200     /// using \ref nodes vector instead of \ref process vector.
   201     void processNextFullRound(int k) {
   202       for (int i = 0; i < nodes.size(); ++i) {
   203 	for (OutEdgeIt e(graph, nodes[i]); e != INVALID; ++e) {
   204 	  Node v = graph.target(e);
   205 	  if (comp[v] != comp_cnt) continue;
   206 	  if ( !dmap[v][k].found ||
   207 	       dmap[nodes[i]][k-1].dist + length[e] < dmap[v][k].dist ) {
   208 	    dmap[v][k] = PathData(true, dmap[nodes[i]][k-1].dist + length[e], e);
   209 	  }
   210 	}
   211       }
   212     }
   213 
   214     /// \brief Finds the minimum cycle mean value in the current
   215     /// component.
   216     bool findCurrentMin(Length &min_length, int &min_size, Node &min_node) {
   217       bool found_min = false;
   218       for (int i = 0; i < nodes.size(); ++i) {
   219 	int n = nodes.size();
   220 	if (!dmap[nodes[i]][n].found) continue;
   221 	Length len;
   222 	int size;
   223 	bool found_one = false;
   224 	for (int k = 0; k < n; ++k) {
   225 	  if (!dmap[nodes[i]][k].found) continue;
   226 	  Length _len = dmap[nodes[i]][n].dist - dmap[nodes[i]][k].dist;
   227 	  int _size = n - k;
   228 	  if (!found_one || len * _size < _len * size) {
   229 	    found_one = true;
   230 	    len = _len;
   231 	    size = _size;
   232 	  }
   233 	}
   234 	if ( found_one &&
   235 	     (!found_min || len * min_size < min_length * size) ) {
   236 	  found_min = true;
   237 	  min_length = len;
   238 	  min_size = size;
   239 	  min_node = nodes[i];
   240 	}
   241       }
   242       return found_min;
   243     }
   244 
   245   public:
   246 
   247     /// \brief Runs the algorithm.
   248     ///
   249     /// Runs the algorithm.
   250     ///
   251     /// \return \c true if a cycle exists in the graph.
   252     ///
   253     /// \note Apart from the return value, <tt>m.run()</tt> is just a
   254     /// shortcut of the following code.
   255     /// \code
   256     ///   m.init();
   257     ///   m.findMinMean();
   258     ///   m.findCycle();
   259     /// \endcode
   260     bool run() {
   261       init();
   262       findMinMean();
   263       return findCycle();
   264     }
   265 
   266     /// \brief Initializes the internal data structures.
   267     ///
   268     /// Initializes the internal data structures.
   269     ///
   270     /// \sa reset()
   271     void init() {
   272       comp_num = stronglyConnectedComponents(graph, comp);
   273       if (!cycle_path) {
   274 	local_path = true;
   275 	cycle_path = new Path;
   276       }
   277     }
   278 
   279     /// \brief Finds the minimum cycle mean value in the graph.
   280     ///
   281     /// Computes all the required path data and finds the minimum cycle
   282     /// mean value in the graph.
   283     ///
   284     /// \return \c true if a cycle exists in the graph.
   285     ///
   286     /// \pre \ref init() must be called before using this function.
   287     bool findMinMean() {
   288       cycle_node = INVALID;
   289       for (comp_cnt = 0; comp_cnt < comp_num; ++comp_cnt) {
   290 	initCurrent();
   291 	processRounds();
   292 
   293 	Length min_length;
   294 	int min_size;
   295 	Node min_node;
   296 	bool found_min = findCurrentMin(min_length, min_size, min_node);
   297 
   298 	if ( found_min && (cycle_node == INVALID ||
   299 	     min_length * cycle_size < cycle_length * min_size) ) {
   300 	  cycle_length = min_length;
   301 	  cycle_size = min_size;
   302 	  cycle_node = min_node;
   303 	}
   304       }
   305       return (cycle_node != INVALID);
   306     }
   307 
   308     /// \brief Finds a critical (minimum mean) cycle.
   309     ///
   310     /// Finds a critical (minimum mean) cycle using the path data
   311     /// stored in \ref dmap.
   312     ///
   313     /// \return \c true if a cycle exists in the graph.
   314     ///
   315     /// \pre \ref init() and \ref findMinMean() must be called before
   316     /// using this function.
   317     bool findCycle() {
   318       if (cycle_node == INVALID) return false;
   319       cycle_length = 0;
   320       cycle_size = 0;
   321       IntNodeMap reached(graph, -1);
   322       int r = reached[cycle_node] = dmap[cycle_node].size() - 1;
   323       Node u = graph.source(dmap[cycle_node][r].pred);
   324       while (reached[u] < 0) {
   325 	reached[u] = --r;
   326 	u = graph.source(dmap[u][r].pred);
   327       }
   328       r = reached[u];
   329       Edge e = dmap[u][r].pred;
   330       cycle_path->addFront(e);
   331       cycle_length = cycle_length + length[e];
   332       ++cycle_size;
   333       Node v;
   334       while ((v = graph.source(e)) != u) {
   335 	e = dmap[v][--r].pred;
   336 	cycle_path->addFront(e);
   337 	cycle_length = cycle_length + length[e];
   338 	++cycle_size;
   339       }
   340       return true;
   341     }
   342 
   343     /// \brief Resets the internal data structures.
   344     ///
   345     /// Resets the internal data structures so that \ref findMinMean()
   346     /// and \ref findCycle() can be called again (e.g. when the
   347     /// underlaying graph has been modified).
   348     ///
   349     /// \sa init()
   350     void reset() {
   351       for (NodeIt u(graph); u != INVALID; ++u)
   352 	dmap[u].clear();
   353       cycle_node = INVALID;
   354       if (cycle_path) cycle_path->clear();
   355       comp_num = stronglyConnectedComponents(graph, comp);
   356     }
   357 
   358     /// \brief Returns the total length of the found cycle.
   359     ///
   360     /// Returns the total length of the found cycle.
   361     ///
   362     /// \pre \ref run() or \ref findCycle() must be called before
   363     /// using this function. If only \ref findMinMean() is called,
   364     /// the return value is not valid.
   365     Length cycleLength() const {
   366       return cycle_length;
   367     }
   368 
   369     /// \brief Returns the number of edges in the found cycle.
   370     ///
   371     /// Returns the number of edges in the found cycle.
   372     ///
   373     /// \pre \ref run() or \ref findCycle() must be called before
   374     /// using this function. If only \ref findMinMean() is called,
   375     /// the return value is not valid.
   376     int cycleEdgeNum() const {
   377       return cycle_size;
   378     }
   379 
   380     /// \brief Returns the mean length of the found cycle.
   381     ///
   382     /// Returns the mean length of the found cycle.
   383     ///
   384     /// \pre \ref run() or \ref findMinMean() must be called before
   385     /// using this function.
   386     ///
   387     /// \warning LengthMap::Value must be convertible to double.
   388     ///
   389     /// \note <tt>m.minMean()</tt> is just a shortcut of the following
   390     /// code.
   391     /// \code
   392     ///   return m.cycleLength() / double(m.cycleEdgeNum());
   393     /// \endcode
   394     /// However if only \ref findMinMean() is called before using this
   395     /// function, <tt>m.cycleLength()</tt> and <tt>m.cycleEdgeNum()</tt>
   396     /// are not valid alone, only their ratio is valid.
   397     double minMean() const {
   398       return cycle_length / (double)cycle_size;
   399     }
   400 
   401     /// \brief Returns a const reference to the \ref lemon::Path "Path"
   402     /// structure of the found cycle.
   403     ///
   404     /// Returns a const reference to the \ref lemon::Path "Path"
   405     /// structure of the found cycle.
   406     ///
   407     /// \pre \ref run() must be called before using this function.
   408     ///
   409     /// \sa \ref cyclePath()
   410     const Path& cycle() const {
   411       return *cycle_path;
   412     }
   413 
   414     /// \brief Sets the \ref lemon::Path "Path" structure storing the
   415     /// found cycle.
   416     ///
   417     /// Sets the \ref lemon::Path "Path" structure storing the found
   418     /// cycle. If you don't use this function before calling
   419     /// \ref run(), it will allocate one. The destuctor deallocates
   420     /// this automatically allocated map, of course.
   421     ///
   422     /// \note The algorithm calls only the \ref lemon::Path::addFront()
   423     /// "addFront()" method of the given \ref lemon::Path "Path"
   424     /// structure.
   425     ///
   426     /// \return \c (*this)
   427     MinMeanCycle& cyclePath(Path &path) {
   428       if (local_path) {
   429 	delete cycle_path;
   430 	local_path = false;
   431       }
   432       cycle_path = &path;
   433       return *this;
   434     }
   435 
   436   }; //class MinMeanCycle
   437 
   438   ///@}
   439 
   440 } //namespace lemon
   441 
   442 #endif //LEMON_MIN_MEAN_CYCLE_H