3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2007
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
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.
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
19 #ifndef LEMON_MIN_MEAN_CYCLE_H
20 #define LEMON_MIN_MEAN_CYCLE_H
22 /// \ingroup min_cost_flow
25 /// \brief Karp algorithm for finding a minimum mean cycle.
27 #include <lemon/graph_utils.h>
28 #include <lemon/topology.h>
29 #include <lemon/path.h>
33 /// \addtogroup min_cost_flow
36 /// \brief Implementation of Karp's algorithm for finding a
37 /// minimum mean (directed) cycle.
39 /// The \ref lemon::MinMeanCycle "MinMeanCycle" implements Karp's
40 /// algorithm for finding a minimum mean (directed) cycle.
42 /// \param Graph The directed graph type the algorithm runs on.
43 /// \param LengthMap The type of the length (cost) map.
45 /// \author Peter Kovacs
47 template <typename Graph,
48 typename LengthMap = typename Graph::template EdgeMap<int> >
51 typedef typename Graph::Node Node;
52 typedef typename Graph::NodeIt NodeIt;
53 typedef typename Graph::Edge Edge;
54 typedef typename Graph::EdgeIt EdgeIt;
55 typedef typename Graph::OutEdgeIt OutEdgeIt;
57 typedef typename LengthMap::Value Length;
59 typedef typename Graph::template NodeMap<int> IntNodeMap;
60 typedef typename Graph::template NodeMap<Edge> PredNodeMap;
61 typedef Path<Graph> Path;
62 typedef std::vector<Node> NodeVector;
66 /// \brief Data sturcture for path data.
72 PathData(bool _found = false, Length _dist = 0) :
73 found(_found), dist(_dist), pred(INVALID) {}
74 PathData(bool _found, Length _dist, Edge _pred) :
75 found(_found), dist(_dist), pred(_pred) {}
80 typedef typename Graph::template NodeMap<std::vector<PathData> >
85 /// \brief Node map for storing path data.
87 /// Node map for storing path data of all nodes in the current
88 /// component. dmap[v][k] is the length of a shortest directed walk
89 /// to node v from the starting node containing exactly k edges.
92 /// \brief The directed graph the algorithm runs on.
94 /// \brief The length of the edges.
95 const LengthMap &length;
97 /// \brief The total length of the found cycle.
99 /// \brief The number of edges in the found cycle.
101 /// \brief A node for obtaining a minimum mean cycle.
104 /// \brief The found cycle.
106 /// \brief The algorithm uses local \ref lemon::Path "Path"
107 /// structure to store the found cycle.
110 /// \brief Node map for identifying strongly connected components.
112 /// \brief The number of strongly connected components.
114 /// \brief Counter for identifying the current component.
116 /// \brief Nodes of the current component.
118 /// \brief The processed nodes in the last round.
123 /// \brief The constructor of the class.
125 /// The constructor of the class.
127 /// \param _graph The directed graph the algorithm runs on.
128 /// \param _length The length (cost) of the edges.
129 MinMeanCycle( const Graph &_graph,
130 const LengthMap &_length ) :
131 graph(_graph), length(_length), dmap(_graph), comp(_graph),
132 cycle_length(0), cycle_size(-1), cycle_node(INVALID),
133 cycle_path(NULL), local_path(false)
136 /// \brief The destructor of the class.
138 if (local_path) delete cycle_path;
143 /// \brief Initializes the internal data structures for the current
147 // Finding the nodes of the current component
148 for (NodeIt v(graph); v != INVALID; ++v) {
149 if (comp[v] == comp_cnt) nodes.push_back(v);
151 // Creating vectors for all nodes
152 int n = nodes.size();
153 for (int i = 0; i < nodes.size(); ++i) {
154 dmap[nodes[i]].resize(n + 1);
158 /// \brief Processes all rounds of computing required path data for
159 /// the current component.
160 void processRounds() {
161 dmap[nodes[0]][0] = PathData(true, 0);
163 // Processing the first round
164 for (OutEdgeIt e(graph, nodes[0]); e != INVALID; ++e) {
165 Node v = graph.target(e);
166 if (comp[v] != comp_cnt || v == nodes[0]) continue;
167 dmap[v][1] = PathData(true, length[e], e);
168 process.push_back(v);
170 // Processing other rounds
171 int n = nodes.size(), k;
172 for (k = 2; k <= n && process.size() < n; ++k)
173 processNextBuildRound(k);
175 processNextFullRound(k);
178 /// \brief Processes one round of computing required path data and
179 /// rebuilds \ref process vector.
180 void processNextBuildRound(int k) {
182 for (int i = 0; i < process.size(); ++i) {
183 for (OutEdgeIt e(graph, process[i]); e != INVALID; ++e) {
184 Node v = graph.target(e);
185 if (comp[v] != comp_cnt) continue;
186 if (!dmap[v][k].found) {
188 dmap[v][k] = PathData(true, dmap[process[i]][k-1].dist + length[e], e);
190 else if (dmap[process[i]][k-1].dist + length[e] < dmap[v][k].dist) {
191 dmap[v][k] = PathData(true, dmap[process[i]][k-1].dist + length[e], e);
198 /// \brief Processes one round of computing required path data
199 /// using \ref nodes vector instead of \ref process vector.
200 void processNextFullRound(int k) {
201 for (int i = 0; i < nodes.size(); ++i) {
202 for (OutEdgeIt e(graph, nodes[i]); e != INVALID; ++e) {
203 Node v = graph.target(e);
204 if (comp[v] != comp_cnt) continue;
205 if ( !dmap[v][k].found ||
206 dmap[nodes[i]][k-1].dist + length[e] < dmap[v][k].dist ) {
207 dmap[v][k] = PathData(true, dmap[nodes[i]][k-1].dist + length[e], e);
213 /// \brief Finds the minimum cycle mean value in the current
215 bool findCurrentMin(Length &min_length, int &min_size, Node &min_node) {
216 bool found_min = false;
217 for (int i = 0; i < nodes.size(); ++i) {
218 int n = nodes.size();
219 if (!dmap[nodes[i]][n].found) continue;
222 bool found_one = false;
223 for (int k = 0; k < n; ++k) {
224 if (!dmap[nodes[i]][k].found) continue;
225 Length _len = dmap[nodes[i]][n].dist - dmap[nodes[i]][k].dist;
227 if (!found_one || len * _size < _len * size) {
234 (!found_min || len * min_size < min_length * size) ) {
246 /// \brief Runs the algorithm.
248 /// Runs the algorithm.
250 /// \return \c true if a cycle exists in the graph.
252 /// \note Apart from the return value, m.run() is just a shortcut
253 /// of the following code.
265 /// \brief Initializes the internal data structures.
267 comp_num = stronglyConnectedComponents(graph, comp);
270 cycle_path = new Path;
274 /// \brief Finds the minimum cycle mean value in the graph.
276 /// Computes all the required path data and finds the minimum cycle
277 /// mean value in the graph.
279 /// \return \c true if a cycle exists in the graph.
281 /// \pre \ref init() must be called before using this function.
283 cycle_node = INVALID;
284 for (comp_cnt = 0; comp_cnt < comp_num; ++comp_cnt) {
291 bool found_min = findCurrentMin(min_length, min_size, min_node);
293 if ( found_min && (cycle_node == INVALID ||
294 min_length * cycle_size < cycle_length * min_size) ) {
295 cycle_length = min_length;
296 cycle_size = min_size;
297 cycle_node = min_node;
300 return (cycle_node != INVALID);
303 /// \brief Finds a critical (minimum mean) cycle.
305 /// Finds a critical (minimum mean) cycle using the path data
306 /// stored in \ref dmap.
308 /// \return \c true if a cycle exists in the graph.
310 /// \pre \ref init() and \ref findMinMean() must be called before
311 /// using this function.
313 if (cycle_node == INVALID) return false;
316 IntNodeMap reached(graph, -1);
317 int r = reached[cycle_node] = dmap[cycle_node].size() - 1;
318 Node u = graph.source(dmap[cycle_node][r].pred);
319 while (reached[u] < 0) {
321 u = graph.source(dmap[u][r].pred);
324 Edge e = dmap[u][r].pred;
325 cycle_path->addFront(e);
326 cycle_length = cycle_length + length[e];
329 while ((v = graph.source(e)) != u) {
330 e = dmap[v][--r].pred;
331 cycle_path->addFront(e);
332 cycle_length = cycle_length + length[e];
338 /// \brief Resets the internal data structures.
340 /// Resets the internal data structures so that \ref findMinMean()
341 /// and \ref findCycle() can be called again (e.g. when the
342 /// underlaying graph has been modified).
344 for (NodeIt u(graph); u != INVALID; ++u)
346 cycle_node = INVALID;
347 if (cycle_path) cycle_path->clear();
348 comp_num = stronglyConnectedComponents(graph, comp);
351 /// \brief Returns the total length of the found cycle.
353 /// Returns the total length of the found cycle.
355 /// \pre \ref run() must be called before using this function.
356 Length cycleLength() const {
360 /// \brief Returns the number of edges in the found cycle.
362 /// Returns the number of edges in the found cycle.
364 /// \pre \ref run() must be called before using this function.
365 int cycleEdgeNum() const {
369 /// \brief Returns the mean length of the found cycle.
371 /// Returns the mean length of the found cycle.
373 /// \pre \ref run() must be called before using this function.
375 /// \warning LengthMap::Value must be convertible to double.
377 /// \note m.minMean() is just a shortcut of the following code.
379 /// return m.cycleEdgeNum() / double(m.cycleLength());
381 double minMean() const {
382 return cycle_length / (double)cycle_size;
385 /// \brief Returns a const reference to the \ref lemon::Path "Path"
386 /// structure of the found cycle.
388 /// Returns a const reference to the \ref lemon::Path "Path"
389 /// structure of the found cycle.
391 /// \pre \ref run() must be called before using this function.
393 /// \sa \ref cyclePath()
394 const Path& cycle() const {
398 /// \brief Sets the \ref lemon::Path "Path" structure storing the
401 /// Sets the \ref lemon::Path "Path" structure storing the found
402 /// cycle. If you don't use this function before calling
403 /// \ref run(), it will allocate one. The destuctor deallocates
404 /// this automatically allocated map, of course.
406 /// \note The algorithm calls only the \ref lemon::Path::addFront()
407 /// "addFront()" method of the given \ref lemon::Path "Path"
410 /// \return \c (*this)
411 MinMeanCycle& cyclePath(Path &path) {
420 }; //class MinMeanCycle
426 #endif //LEMON_MIN_MEAN_CYCLE_H