Major improvements in NetworkSimplex.
Main changes:
- Use -potenital[] instead of potential[] to conform to the usual
terminology.
- Use function parameter instead of #define commands to select pivot rule.
- Use much faster implementation for the candidate list pivot rule.
It is about 5-20 times faster now.
- Add a new pivot rule called "Limited Search" that is a modified
version of "Block Search". It is about 25 percent faster on rather
sparse graphs.
- By default "Limited Search" is used for sparse graphs and
"Block Search" is used otherwise. This combined method is the most
efficient on every input class.
- Change the name of private members to start with "_".
- Change the name of function parameters not to start with "_".
- Remove unnecessary documentation for private members.
- Many doc improvements.
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/topology.h>
30 #include <lemon/path.h>
31 #include <lemon/tolerance.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 /// \param Graph The directed graph type the algorithm runs on.
45 /// \param 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 typename Graph::template NodeMap<bool> _reached;
63 typename Graph::template NodeMap<double> _dist;
64 typename Graph::template NodeMap<Edge> _policy;
66 /// The directed graph the algorithm runs on.
68 /// The length of the edges.
69 const LengthMap &_length;
71 /// The total length of the found cycle.
73 /// The number of edges on the found cycle.
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), _dist(graph), _reached(graph),
100 _policy(graph), _component(graph), _cycle_length(0),
101 _cycle_size(-1), _cycle_path(NULL), _local_path(false)
104 /// The destructor of the class.
106 if (_local_path) delete _cycle_path;
111 // Initializes the internal data structures for the current strongly
112 // connected component and creating the policy graph.
113 // The policy graph can be represented by the _policy map because
114 // the out degree of every node is 1.
115 bool initCurrentComponent(int comp) {
116 // Finding the nodes of the current component
118 for (NodeIt n(_graph); n != INVALID; ++n) {
119 if (_component[n] == comp) _nodes.push_back(n);
121 if (_nodes.size() <= 1) return false;
122 // Finding the edges of the current component
124 for (EdgeIt e(_graph); e != INVALID; ++e) {
125 if ( _component[_graph.source(e)] == comp &&
126 _component[_graph.target(e)] == comp )
129 // Initializing _reached, _dist, _policy maps
130 for (int i = 0; i < _nodes.size(); ++i) {
131 _reached[_nodes[i]] = false;
132 _policy[_nodes[i]] = INVALID;
135 for (int j = 0; j < _edges.size(); ++j) {
137 u = _graph.source(e);
138 if (!_reached[u] || _length[e] < _dist[u]) {
139 _dist[u] = _length[e];
147 // Finds all cycles in the policy graph.
148 // Sets _cycle_found to true if a cycle is found and sets
149 // _cycle_length, _cycle_size, _cycle_node to represent the minimum
150 // mean cycle in the policy graph.
151 bool findPolicyCycles(int comp) {
152 typename Graph::template NodeMap<int> level(_graph, -1);
153 _cycle_found = false;
158 // Searching for cycles
159 for (int i = 0; i < _nodes.size(); ++i) {
160 if (level[_nodes[i]] < 0) {
163 while (level[u = _graph.target(_policy[u])] < 0)
165 if (level[u] == path_cnt) {
167 clength = _length[_policy[u]];
169 for (v = u; (v = _graph.target(_policy[v])) != u; ) {
170 clength += _length[_policy[v]];
173 if ( !_cycle_found ||
174 clength * _cycle_size < _cycle_length * csize ) {
176 _cycle_length = clength;
187 // Contracts the policy graph to be connected by cutting all cycles
188 // except for the main cycle (i.e. the minimum mean cycle).
189 void contractPolicyGraph(int comp) {
190 // Finding the component of the main cycle using
191 // reverse BFS search
192 typename Graph::template NodeMap<int> found(_graph, false);
193 std::deque<Node> queue;
194 queue.push_back(_cycle_node);
195 found[_cycle_node] = true;
197 while (!queue.empty()) {
198 v = queue.front(); queue.pop_front();
199 for (InEdgeIt e(_graph, v); e != INVALID; ++e) {
200 u = _graph.source(e);
201 if (_component[u] == comp && !found[u] && _policy[u] == e) {
207 // Connecting all other nodes to this component using
208 // reverse BFS search
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]) {
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;
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) {
243 _dist[u] = _dist[v] + _length[e] - cycle_mean;
248 // Improving node distances
249 bool improved = false;
250 for (int j = 0; j < _edges.size(); ++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])) {
265 /// \brief Runs the algorithm.
267 /// Runs the algorithm.
269 /// \return Returns \c true if a directed cycle exists in the graph.
271 /// \note Apart from the return value, <tt>mmc.run()</tt> is just a
272 /// shortcut of the following code.
275 /// mmc.findMinMean();
280 return findMinMean() && findCycle();
283 /// \brief Initializes the internal data structures.
285 /// Initializes the internal data structures.
289 _tolerance.epsilon(1e-8);
292 _cycle_path = new Path;
294 _cycle_found = false;
295 _component_num = stronglyConnectedComponents(_graph, _component);
298 /// \brief Resets the internal data structures.
300 /// Resets the internal data structures so that \ref findMinMean()
301 /// and \ref findCycle() can be called again (e.g. when the
302 /// underlaying graph has been modified).
306 if (_cycle_path) _cycle_path->clear();
307 _cycle_found = false;
308 _component_num = stronglyConnectedComponents(_graph, _component);
311 /// \brief Finds the minimum cycle mean length in the graph.
313 /// Computes all the required data and finds the minimum cycle mean
314 /// length in the graph.
316 /// \return Returns \c true if a directed cycle exists in the graph.
318 /// \pre \ref init() must be called before using this function.
320 // Finding the minimum mean cycle in the components
321 for (int comp = 0; comp < _component_num; ++comp) {
322 if (!initCurrentComponent(comp)) continue;
324 if (!findPolicyCycles(comp)) return false;
325 contractPolicyGraph(comp);
326 if (!computeNodeDistances(comp)) return true;
331 /// \brief Finds a critical (minimum mean) directed cycle.
333 /// Finds a critical (minimum mean) directed cycle using the data
334 /// computed in the \ref findMinMean() function.
336 /// \return Returns \c true if a directed cycle exists in the graph.
338 /// \pre \ref init() and \ref findMinMean() must be called before
339 /// using this function.
341 if (!_cycle_found) return false;
342 _cycle_path->addBack(_policy[_cycle_node]);
343 for ( Node v = _cycle_node;
344 (v = _graph.target(_policy[v])) != _cycle_node; ) {
345 _cycle_path->addBack(_policy[v]);
350 /// \brief Returns the total length of the found cycle.
352 /// Returns the total length of the found cycle.
354 /// \pre \ref run() or \ref findMinMean() must be called before
355 /// using this function.
356 Length cycleLength() const {
357 return _cycle_length;
360 /// \brief Returns the number of edges on the found cycle.
362 /// Returns the number of edges on the found cycle.
364 /// \pre \ref run() or \ref findMinMean() must be called before
365 /// using this function.
366 int cycleEdgeNum() const {
370 /// \brief Returns the mean length of the found cycle.
372 /// Returns the mean length of the found cycle.
374 /// \pre \ref run() or \ref findMinMean() must be called before
375 /// using this function.
377 /// \note <tt>mmc.cycleMean()</tt> is just a shortcut of the
380 /// return double(mmc.cycleLength()) / mmc.cycleEdgeNum();
382 double cycleMean() const {
383 return (double)_cycle_length / _cycle_size;
386 /// \brief Returns a const reference to the \ref Path "path"
387 /// structure storing the found cycle.
389 /// Returns a const reference to the \ref Path "path"
390 /// structure storing the found cycle.
392 /// \pre \ref run() or \ref findCycle() must be called before using
396 const Path& cycle() const {
400 /// \brief Sets the \ref Path "path" structure for storing the found
403 /// Sets an external \ref Path "path" structure for storing the
406 /// If you don't call this function before calling \ref run() or
407 /// \ref init(), it will allocate a local \ref Path "path"
409 /// The destuctor deallocates this automatically allocated map,
412 /// \note The algorithm calls only the \ref lemon::Path::addBack()
413 /// "addBack()" function of the given \ref Path "path" structure.
415 /// \return <tt>(*this)</tt>
418 MinMeanCycle& cyclePath(Path &path) {
427 }; //class MinMeanCycle
433 #endif //LEMON_MIN_MEAN_CYCLE_H