In C++98 array size shall be an integral constant expression. Fixes
ticket 12.
3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2008
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 shortest_path
25 /// \brief Howard's algorithm for finding a minimum mean directed cycle.
28 #include <lemon/graph_utils.h>
29 #include <lemon/path.h>
30 #include <lemon/tolerance.h>
31 #include <lemon/topology.h>
35 /// \addtogroup shortest_path
38 /// \brief Implementation of Howard's algorithm for finding a minimum
39 /// mean directed cycle.
41 /// \ref MinMeanCycle implements Howard's algorithm for finding a
42 /// minimum mean directed cycle.
44 /// \tparam Graph The directed graph type the algorithm runs on.
45 /// \tparam LengthMap The type of the length (cost) map.
47 /// \warning \c LengthMap::Value must be convertible to \c double.
49 /// \author Peter Kovacs
51 template < typename Graph,
52 typename LengthMap = typename Graph::template EdgeMap<int> >
55 GRAPH_TYPEDEFS(typename Graph);
57 typedef typename LengthMap::Value Length;
58 typedef Path<Graph> Path;
62 // The directed graph the algorithm runs on
64 // The length of the edges
65 const LengthMap &_length;
67 // The total length of the found cycle
69 // The number of edges on the found cycle
78 typename Graph::template NodeMap<bool> _reached;
79 typename Graph::template NodeMap<double> _dist;
80 typename Graph::template NodeMap<Edge> _policy;
82 typename Graph::template NodeMap<int> _component;
85 std::vector<Node> _nodes;
86 std::vector<Edge> _edges;
87 Tolerance<double> _tolerance;
91 /// \brief The constructor of the class.
93 /// The constructor of the class.
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), _cycle_length(0), _cycle_size(-1),
100 _cycle_path(NULL), _local_path(false), _reached(graph),
101 _dist(graph), _policy(graph), _component(graph)
104 /// The destructor of the class.
106 if (_local_path) delete _cycle_path;
109 /// \brief Sets the \ref Path "path" structure for storing the found
112 /// Sets an external \ref Path "path" structure for storing the
115 /// If you don't call this function before calling \ref run() or
116 /// \ref init(), it will allocate a local \ref Path "path"
118 /// The destuctor deallocates this automatically allocated map,
121 /// \note The algorithm calls only the \ref lemon::Path::addBack()
122 /// "addBack()" function of the given \ref Path "path" structure.
124 /// \return <tt>(*this)</tt>
127 MinMeanCycle& cyclePath(Path &path) {
136 /// \name Execution control
137 /// The simplest way to execute the algorithm is to call the run()
140 /// If you only need the minimum mean value, you may call init()
141 /// and findMinMean().
143 /// If you would like to run the algorithm again (e.g. the
144 /// underlaying graph and/or the edge costs were modified), you may
145 /// not create a new instance of the class, rather call reset(),
146 /// findMinMean(), and findCycle() instead.
150 /// \brief Runs the algorithm.
152 /// Runs the algorithm.
154 /// \return Returns \c true if a directed cycle exists in the graph.
156 /// \note Apart from the return value, <tt>mmc.run()</tt> is just a
157 /// shortcut of the following code.
160 /// mmc.findMinMean();
165 return findMinMean() && findCycle();
168 /// \brief Initializes the internal data structures.
170 /// Initializes the internal data structures.
174 _tolerance.epsilon(1e-6);
177 _cycle_path = new Path;
179 _cycle_found = false;
180 _component_num = stronglyConnectedComponents(_graph, _component);
183 /// \brief Resets the internal data structures.
185 /// Resets the internal data structures so that \ref findMinMean()
186 /// and \ref findCycle() can be called again (e.g. when the
187 /// underlaying graph has been modified).
191 if (_cycle_path) _cycle_path->clear();
192 _cycle_found = false;
193 _component_num = stronglyConnectedComponents(_graph, _component);
196 /// \brief Finds the minimum cycle mean length in the graph.
198 /// Computes all the required data and finds the minimum cycle mean
199 /// length in the graph.
201 /// \return Returns \c true if a directed cycle exists in the graph.
203 /// \pre \ref init() must be called before using this function.
205 // Finding the minimum mean cycle in the components
206 for (int comp = 0; comp < _component_num; ++comp) {
207 if (!initCurrentComponent(comp)) continue;
209 if (!findPolicyCycles()) break;
210 contractPolicyGraph(comp);
211 if (!computeNodeDistances(comp)) break;
217 /// \brief Finds a critical (minimum mean) directed cycle.
219 /// Finds a critical (minimum mean) directed cycle using the data
220 /// computed in the \ref findMinMean() function.
222 /// \return Returns \c true if a directed cycle exists in the graph.
224 /// \pre \ref init() and \ref findMinMean() must be called before
225 /// using this function.
227 if (!_cycle_found) return false;
228 _cycle_path->addBack(_policy[_cycle_node]);
229 for ( Node v = _cycle_node;
230 (v = _graph.target(_policy[v])) != _cycle_node; ) {
231 _cycle_path->addBack(_policy[v]);
238 /// \name Query Functions
239 /// The result of the algorithm can be obtained using these
241 /// \n The algorithm should be executed before using them.
245 /// \brief Returns the total length of the found cycle.
247 /// Returns the total length of the found cycle.
249 /// \pre \ref run() or \ref findMinMean() must be called before
250 /// using this function.
251 Length cycleLength() const {
252 return _cycle_length;
255 /// \brief Returns the number of edges on the found cycle.
257 /// Returns the number of edges on the found cycle.
259 /// \pre \ref run() or \ref findMinMean() must be called before
260 /// using this function.
261 int cycleEdgeNum() const {
265 /// \brief Returns the mean length of the found cycle.
267 /// Returns the mean length of the found cycle.
269 /// \pre \ref run() or \ref findMinMean() must be called before
270 /// using this function.
272 /// \note <tt>mmc.cycleMean()</tt> is just a shortcut of the
275 /// return double(mmc.cycleLength()) / mmc.cycleEdgeNum();
277 double cycleMean() const {
278 return double(_cycle_length) / _cycle_size;
281 /// \brief Returns a const reference to the \ref Path "path"
282 /// structure storing the found cycle.
284 /// Returns a const reference to the \ref Path "path"
285 /// structure storing the found cycle.
287 /// \pre \ref run() or \ref findCycle() must be called before using
291 const Path& cycle() const {
299 // Initializes the internal data structures for the current strongly
300 // connected component and creating the policy graph.
301 // The policy graph can be represented by the _policy map because
302 // the out degree of every node is 1.
303 bool initCurrentComponent(int comp) {
304 // Finding the nodes of the current component
306 for (NodeIt n(_graph); n != INVALID; ++n) {
307 if (_component[n] == comp) _nodes.push_back(n);
309 if (_nodes.size() <= 1) return false;
310 // Finding the edges of the current component
312 for (EdgeIt e(_graph); e != INVALID; ++e) {
313 if ( _component[_graph.source(e)] == comp &&
314 _component[_graph.target(e)] == comp )
317 // Initializing _reached, _dist, _policy maps
318 for (int i = 0; i < int(_nodes.size()); ++i) {
319 _reached[_nodes[i]] = false;
320 _policy[_nodes[i]] = INVALID;
323 for (int j = 0; j < int(_edges.size()); ++j) {
325 u = _graph.source(e);
326 if (!_reached[u] || _length[e] < _dist[u]) {
327 _dist[u] = _length[e];
335 // Finds all cycles in the policy graph.
336 // Sets _cycle_found to true if a cycle is found and sets
337 // _cycle_length, _cycle_size, _cycle_node to represent the minimum
338 // mean cycle in the policy graph.
339 bool findPolicyCycles() {
340 typename Graph::template NodeMap<int> level(_graph, -1);
341 bool curr_cycle_found = false;
346 // Searching for cycles
347 for (int i = 0; i < int(_nodes.size()); ++i) {
348 if (level[_nodes[i]] < 0) {
351 while (level[u = _graph.target(_policy[u])] < 0)
353 if (level[u] == path_cnt) {
355 curr_cycle_found = true;
356 clength = _length[_policy[u]];
358 for (v = u; (v = _graph.target(_policy[v])) != u; ) {
359 clength += _length[_policy[v]];
362 if ( !_cycle_found ||
363 clength * _cycle_size < _cycle_length * csize ) {
365 _cycle_length = clength;
373 return curr_cycle_found;
376 // Contracts the policy graph to be connected by cutting all cycles
377 // except for the main cycle (i.e. the minimum mean cycle).
378 void contractPolicyGraph(int comp) {
379 // Finding the component of the main cycle using
380 // reverse BFS search
381 typename Graph::template NodeMap<int> found(_graph, false);
382 std::deque<Node> queue;
383 queue.push_back(_cycle_node);
384 found[_cycle_node] = true;
386 while (!queue.empty()) {
387 v = queue.front(); queue.pop_front();
388 for (InEdgeIt e(_graph, v); e != INVALID; ++e) {
389 u = _graph.source(e);
390 if (_component[u] == comp && !found[u] && _policy[u] == e) {
396 // Connecting all other nodes to this component using
397 // reverse BFS search
399 for (int i = 0; i < int(_nodes.size()); ++i)
400 if (found[_nodes[i]]) queue.push_back(_nodes[i]);
401 int found_cnt = queue.size();
402 while (found_cnt < int(_nodes.size()) && !queue.empty()) {
403 v = queue.front(); queue.pop_front();
404 for (InEdgeIt e(_graph, v); e != INVALID; ++e) {
405 u = _graph.source(e);
406 if (_component[u] == comp && !found[u]) {
416 // Computes node distances in the policy graph and updates the
417 // policy graph if the node distances can be improved.
418 bool computeNodeDistances(int comp) {
419 // Computing node distances using reverse BFS search
420 double cycle_mean = double(_cycle_length) / _cycle_size;
421 typename Graph::template NodeMap<int> found(_graph, false);
422 std::deque<Node> queue;
423 queue.push_back(_cycle_node);
424 found[_cycle_node] = true;
425 _dist[_cycle_node] = 0;
427 while (!queue.empty()) {
428 v = queue.front(); queue.pop_front();
429 for (InEdgeIt e(_graph, v); e != INVALID; ++e) {
430 u = _graph.source(e);
431 if (_component[u] == comp && !found[u] && _policy[u] == e) {
433 _dist[u] = _dist[v] + _length[e] - cycle_mean;
438 // Improving node distances
439 bool improved = false;
440 for (int j = 0; j < int(_edges.size()); ++j) {
442 u = _graph.source(e); v = _graph.target(e);
443 double delta = _dist[v] + _length[e] - cycle_mean;
444 if (_tolerance.less(delta, _dist[u])) {
453 }; //class MinMeanCycle
459 #endif //LEMON_MIN_MEAN_CYCLE_H