lemon/min_mean_cycle.h
author deba
Sat, 17 Nov 2007 20:58:11 +0000
changeset 2514 57143c09dc20
parent 2437 02c7076bf894
child 2517 d9cfac072869
permissions -rw-r--r--
Redesign the maximum flow algorithms

Redesigned interface
Preflow changed to use elevator
Edmonds-Karp does not use the ResGraphAdaptor
Goldberg-Tarjan algorithm (Preflow with Dynamic Trees)
Dinitz-Sleator-Tarjan (Blocking flow with Dynamic Tree)
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2007
     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 min_cost_flow
    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 min_cost_flow
    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, m.run() is just a shortcut
   254     /// 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     void init() {
   268       comp_num = stronglyConnectedComponents(graph, comp);
   269       if (!cycle_path) {
   270 	local_path = true;
   271 	cycle_path = new Path;
   272       }
   273     }
   274 
   275     /// \brief Finds the minimum cycle mean value in the graph.
   276     ///
   277     /// Computes all the required path data and finds the minimum cycle
   278     /// mean value in the graph.
   279     ///
   280     /// \return \c true if a cycle exists in the graph.
   281     ///
   282     /// \pre \ref init() must be called before using this function.
   283     bool findMinMean() {
   284       cycle_node = INVALID;
   285       for (comp_cnt = 0; comp_cnt < comp_num; ++comp_cnt) {
   286 	initCurrent();
   287 	processRounds();
   288 
   289 	Length min_length;
   290 	int min_size;
   291 	Node min_node;
   292 	bool found_min = findCurrentMin(min_length, min_size, min_node);
   293 
   294 	if ( found_min && (cycle_node == INVALID ||
   295 	     min_length * cycle_size < cycle_length * min_size) ) {
   296 	  cycle_length = min_length;
   297 	  cycle_size = min_size;
   298 	  cycle_node = min_node;
   299 	}
   300       }
   301       return (cycle_node != INVALID);
   302     }
   303 
   304     /// \brief Finds a critical (minimum mean) cycle.
   305     ///
   306     /// Finds a critical (minimum mean) cycle using the path data
   307     /// stored in \ref dmap.
   308     ///
   309     /// \return \c true if a cycle exists in the graph.
   310     ///
   311     /// \pre \ref init() and \ref findMinMean() must be called before
   312     /// using this function.
   313     bool findCycle() {
   314       if (cycle_node == INVALID) return false;
   315       cycle_length = 0;
   316       cycle_size = 0;
   317       IntNodeMap reached(graph, -1);
   318       int r = reached[cycle_node] = dmap[cycle_node].size() - 1;
   319       Node u = graph.source(dmap[cycle_node][r].pred);
   320       while (reached[u] < 0) {
   321 	reached[u] = --r;
   322 	u = graph.source(dmap[u][r].pred);
   323       }
   324       r = reached[u];
   325       Edge e = dmap[u][r].pred;
   326       cycle_path->addFront(e);
   327       cycle_length = cycle_length + length[e];
   328       ++cycle_size;
   329       Node v;
   330       while ((v = graph.source(e)) != u) {
   331 	e = dmap[v][--r].pred;
   332 	cycle_path->addFront(e);
   333 	cycle_length = cycle_length + length[e];
   334 	++cycle_size;
   335       }
   336       return true;
   337     }
   338 
   339     /// \brief Resets the internal data structures.
   340     ///
   341     /// Resets the internal data structures so that \ref findMinMean()
   342     /// and \ref findCycle() can be called again (e.g. when the
   343     /// underlaying graph has been modified).
   344     void reset() {
   345       for (NodeIt u(graph); u != INVALID; ++u)
   346 	dmap[u].clear();
   347       cycle_node = INVALID;
   348       if (cycle_path) cycle_path->clear();
   349       comp_num = stronglyConnectedComponents(graph, comp);
   350     }
   351 
   352     /// \brief Returns the total length of the found cycle.
   353     ///
   354     /// Returns the total length of the found cycle.
   355     ///
   356     /// \pre \ref run() must be called before using this function.
   357     Length cycleLength() const {
   358       return cycle_length;
   359     }
   360 
   361     /// \brief Returns the number of edges in the found cycle.
   362     ///
   363     /// Returns the number of edges in the found cycle.
   364     ///
   365     /// \pre \ref run() must be called before using this function.
   366     int cycleEdgeNum() const {
   367       return cycle_size;
   368     }
   369 
   370     /// \brief Returns the mean length of the found cycle.
   371     ///
   372     /// Returns the mean length of the found cycle.
   373     ///
   374     /// \pre \ref run() must be called before using this function.
   375     ///
   376     /// \warning LengthMap::Value must be convertible to double.
   377     ///
   378     /// \note m.minMean() is just a shortcut of the following code.
   379     /// \code
   380     ///   return m.cycleEdgeNum() / double(m.cycleLength());
   381     /// \endcode
   382     double minMean() const {
   383       return cycle_length / (double)cycle_size;
   384     }
   385 
   386     /// \brief Returns a const reference to the \ref lemon::Path "Path"
   387     /// structure of the found cycle.
   388     ///
   389     /// Returns a const reference to the \ref lemon::Path "Path"
   390     /// structure of the found cycle.
   391     ///
   392     /// \pre \ref run() must be called before using this function.
   393     ///
   394     /// \sa \ref cyclePath()
   395     const Path& cycle() const {
   396       return *cycle_path;
   397     }
   398 
   399     /// \brief Sets the \ref lemon::Path "Path" structure storing the
   400     /// found cycle.
   401     ///
   402     /// Sets the \ref lemon::Path "Path" structure storing the found
   403     /// cycle. If you don't use this function before calling
   404     /// \ref run(), it will allocate one. The destuctor deallocates
   405     /// this automatically allocated map, of course.
   406     ///
   407     /// \note The algorithm calls only the \ref lemon::Path::addFront()
   408     /// "addFront()" method of the given \ref lemon::Path "Path"
   409     /// structure.
   410     ///
   411     /// \return \c (*this)
   412     MinMeanCycle& cyclePath(Path &path) {
   413       if (local_path) {
   414 	delete cycle_path;
   415 	local_path = false;
   416       }
   417       cycle_path = &path;
   418       return *this;
   419     }
   420 
   421   }; //class MinMeanCycle
   422 
   423   ///@}
   424 
   425 } //namespace lemon
   426 
   427 #endif //LEMON_MIN_MEAN_CYCLE_H