COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/min_mean_cycle.h @ 2511:a99186a9b6b0

Last change on this file since 2511:a99186a9b6b0 was 2509:a8081c9cd96a, checked in by Peter Kovacs, 16 years ago

Small changes in the min. cost flow classes.

File size: 12.3 KB
Line 
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
32namespace 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
Note: See TracBrowser for help on using the repository browser.