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