31 #include <lemon/tolerance.h> |
31 #include <lemon/tolerance.h> |
32 #include <lemon/connectivity.h> |
32 #include <lemon/connectivity.h> |
33 |
33 |
34 namespace lemon { |
34 namespace lemon { |
35 |
35 |
36 /// \brief Default traits class of Howard class. |
36 /// \brief Default traits class of HowardMmc class. |
37 /// |
37 /// |
38 /// Default traits class of Howard class. |
38 /// Default traits class of HowardMmc class. |
39 /// \tparam GR The type of the digraph. |
39 /// \tparam GR The type of the digraph. |
40 /// \tparam LEN The type of the length map. |
40 /// \tparam CM The type of the cost map. |
41 /// It must conform to the \ref concepts::ReadMap "ReadMap" concept. |
41 /// It must conform to the \ref concepts::ReadMap "ReadMap" concept. |
42 #ifdef DOXYGEN |
42 #ifdef DOXYGEN |
43 template <typename GR, typename LEN> |
43 template <typename GR, typename CM> |
44 #else |
44 #else |
45 template <typename GR, typename LEN, |
45 template <typename GR, typename CM, |
46 bool integer = std::numeric_limits<typename LEN::Value>::is_integer> |
46 bool integer = std::numeric_limits<typename CM::Value>::is_integer> |
47 #endif |
47 #endif |
48 struct HowardDefaultTraits |
48 struct HowardMmcDefaultTraits |
49 { |
49 { |
50 /// The type of the digraph |
50 /// The type of the digraph |
51 typedef GR Digraph; |
51 typedef GR Digraph; |
52 /// The type of the length map |
52 /// The type of the cost map |
53 typedef LEN LengthMap; |
53 typedef CM CostMap; |
54 /// The type of the arc lengths |
54 /// The type of the arc costs |
55 typedef typename LengthMap::Value Value; |
55 typedef typename CostMap::Value Cost; |
56 |
56 |
57 /// \brief The large value type used for internal computations |
57 /// \brief The large cost type used for internal computations |
58 /// |
58 /// |
59 /// The large value type used for internal computations. |
59 /// The large cost type used for internal computations. |
60 /// It is \c long \c long if the \c Value type is integer, |
60 /// It is \c long \c long if the \c Cost type is integer, |
61 /// otherwise it is \c double. |
61 /// otherwise it is \c double. |
62 /// \c Value must be convertible to \c LargeValue. |
62 /// \c Cost must be convertible to \c LargeCost. |
63 typedef double LargeValue; |
63 typedef double LargeCost; |
64 |
64 |
65 /// The tolerance type used for internal computations |
65 /// The tolerance type used for internal computations |
66 typedef lemon::Tolerance<LargeValue> Tolerance; |
66 typedef lemon::Tolerance<LargeCost> Tolerance; |
67 |
67 |
68 /// \brief The path type of the found cycles |
68 /// \brief The path type of the found cycles |
69 /// |
69 /// |
70 /// The path type of the found cycles. |
70 /// The path type of the found cycles. |
71 /// It must conform to the \ref lemon::concepts::Path "Path" concept |
71 /// It must conform to the \ref lemon::concepts::Path "Path" concept |
72 /// and it must have an \c addBack() function. |
72 /// and it must have an \c addBack() function. |
73 typedef lemon::Path<Digraph> Path; |
73 typedef lemon::Path<Digraph> Path; |
74 }; |
74 }; |
75 |
75 |
76 // Default traits class for integer value types |
76 // Default traits class for integer cost types |
77 template <typename GR, typename LEN> |
77 template <typename GR, typename CM> |
78 struct HowardDefaultTraits<GR, LEN, true> |
78 struct HowardMmcDefaultTraits<GR, CM, true> |
79 { |
79 { |
80 typedef GR Digraph; |
80 typedef GR Digraph; |
81 typedef LEN LengthMap; |
81 typedef CM CostMap; |
82 typedef typename LengthMap::Value Value; |
82 typedef typename CostMap::Value Cost; |
83 #ifdef LEMON_HAVE_LONG_LONG |
83 #ifdef LEMON_HAVE_LONG_LONG |
84 typedef long long LargeValue; |
84 typedef long long LargeCost; |
85 #else |
85 #else |
86 typedef long LargeValue; |
86 typedef long LargeCost; |
87 #endif |
87 #endif |
88 typedef lemon::Tolerance<LargeValue> Tolerance; |
88 typedef lemon::Tolerance<LargeCost> Tolerance; |
89 typedef lemon::Path<Digraph> Path; |
89 typedef lemon::Path<Digraph> Path; |
90 }; |
90 }; |
91 |
91 |
92 |
92 |
93 /// \addtogroup min_mean_cycle |
93 /// \addtogroup min_mean_cycle |
95 |
95 |
96 /// \brief Implementation of Howard's algorithm for finding a minimum |
96 /// \brief Implementation of Howard's algorithm for finding a minimum |
97 /// mean cycle. |
97 /// mean cycle. |
98 /// |
98 /// |
99 /// This class implements Howard's policy iteration algorithm for finding |
99 /// This class implements Howard's policy iteration algorithm for finding |
100 /// a directed cycle of minimum mean length (cost) in a digraph |
100 /// a directed cycle of minimum mean cost in a digraph |
101 /// \ref amo93networkflows, \ref dasdan98minmeancycle. |
101 /// \ref amo93networkflows, \ref dasdan98minmeancycle. |
102 /// This class provides the most efficient algorithm for the |
102 /// This class provides the most efficient algorithm for the |
103 /// minimum mean cycle problem, though the best known theoretical |
103 /// minimum mean cycle problem, though the best known theoretical |
104 /// bound on its running time is exponential. |
104 /// bound on its running time is exponential. |
105 /// |
105 /// |
106 /// \tparam GR The type of the digraph the algorithm runs on. |
106 /// \tparam GR The type of the digraph the algorithm runs on. |
107 /// \tparam LEN The type of the length map. The default |
107 /// \tparam CM The type of the cost map. The default |
108 /// map type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>". |
108 /// map type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>". |
109 /// \tparam TR The traits class that defines various types used by the |
109 /// \tparam TR The traits class that defines various types used by the |
110 /// algorithm. By default, it is \ref HowardDefaultTraits |
110 /// algorithm. By default, it is \ref HowardMmcDefaultTraits |
111 /// "HowardDefaultTraits<GR, LEN>". |
111 /// "HowardMmcDefaultTraits<GR, CM>". |
112 /// In most cases, this parameter should not be set directly, |
112 /// In most cases, this parameter should not be set directly, |
113 /// consider to use the named template parameters instead. |
113 /// consider to use the named template parameters instead. |
114 #ifdef DOXYGEN |
114 #ifdef DOXYGEN |
115 template <typename GR, typename LEN, typename TR> |
115 template <typename GR, typename CM, typename TR> |
116 #else |
116 #else |
117 template < typename GR, |
117 template < typename GR, |
118 typename LEN = typename GR::template ArcMap<int>, |
118 typename CM = typename GR::template ArcMap<int>, |
119 typename TR = HowardDefaultTraits<GR, LEN> > |
119 typename TR = HowardMmcDefaultTraits<GR, CM> > |
120 #endif |
120 #endif |
121 class Howard |
121 class HowardMmc |
122 { |
122 { |
123 public: |
123 public: |
124 |
124 |
125 /// The type of the digraph |
125 /// The type of the digraph |
126 typedef typename TR::Digraph Digraph; |
126 typedef typename TR::Digraph Digraph; |
127 /// The type of the length map |
127 /// The type of the cost map |
128 typedef typename TR::LengthMap LengthMap; |
128 typedef typename TR::CostMap CostMap; |
129 /// The type of the arc lengths |
129 /// The type of the arc costs |
130 typedef typename TR::Value Value; |
130 typedef typename TR::Cost Cost; |
131 |
131 |
132 /// \brief The large value type |
132 /// \brief The large cost type |
133 /// |
133 /// |
134 /// The large value type used for internal computations. |
134 /// The large cost type used for internal computations. |
135 /// By default, it is \c long \c long if the \c Value type is integer, |
135 /// By default, it is \c long \c long if the \c Cost type is integer, |
136 /// otherwise it is \c double. |
136 /// otherwise it is \c double. |
137 typedef typename TR::LargeValue LargeValue; |
137 typedef typename TR::LargeCost LargeCost; |
138 |
138 |
139 /// The tolerance type |
139 /// The tolerance type |
140 typedef typename TR::Tolerance Tolerance; |
140 typedef typename TR::Tolerance Tolerance; |
141 |
141 |
142 /// \brief The path type of the found cycles |
142 /// \brief The path type of the found cycles |
143 /// |
143 /// |
144 /// The path type of the found cycles. |
144 /// The path type of the found cycles. |
145 /// Using the \ref HowardDefaultTraits "default traits class", |
145 /// Using the \ref HowardMmcDefaultTraits "default traits class", |
146 /// it is \ref lemon::Path "Path<Digraph>". |
146 /// it is \ref lemon::Path "Path<Digraph>". |
147 typedef typename TR::Path Path; |
147 typedef typename TR::Path Path; |
148 |
148 |
149 /// The \ref HowardDefaultTraits "traits class" of the algorithm |
149 /// The \ref HowardMmcDefaultTraits "traits class" of the algorithm |
150 typedef TR Traits; |
150 typedef TR Traits; |
151 |
151 |
152 private: |
152 private: |
153 |
153 |
154 TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
154 TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
155 |
155 |
156 // The digraph the algorithm runs on |
156 // The digraph the algorithm runs on |
157 const Digraph &_gr; |
157 const Digraph &_gr; |
158 // The length of the arcs |
158 // The cost of the arcs |
159 const LengthMap &_length; |
159 const CostMap &_cost; |
160 |
160 |
161 // Data for the found cycles |
161 // Data for the found cycles |
162 bool _curr_found, _best_found; |
162 bool _curr_found, _best_found; |
163 LargeValue _curr_length, _best_length; |
163 LargeCost _curr_cost, _best_cost; |
164 int _curr_size, _best_size; |
164 int _curr_size, _best_size; |
165 Node _curr_node, _best_node; |
165 Node _curr_node, _best_node; |
166 |
166 |
167 Path *_cycle_path; |
167 Path *_cycle_path; |
168 bool _local_path; |
168 bool _local_path; |
169 |
169 |
170 // Internal data used by the algorithm |
170 // Internal data used by the algorithm |
171 typename Digraph::template NodeMap<Arc> _policy; |
171 typename Digraph::template NodeMap<Arc> _policy; |
172 typename Digraph::template NodeMap<bool> _reached; |
172 typename Digraph::template NodeMap<bool> _reached; |
173 typename Digraph::template NodeMap<int> _level; |
173 typename Digraph::template NodeMap<int> _level; |
174 typename Digraph::template NodeMap<LargeValue> _dist; |
174 typename Digraph::template NodeMap<LargeCost> _dist; |
175 |
175 |
176 // Data for storing the strongly connected components |
176 // Data for storing the strongly connected components |
177 int _comp_num; |
177 int _comp_num; |
178 typename Digraph::template NodeMap<int> _comp; |
178 typename Digraph::template NodeMap<int> _comp; |
179 std::vector<std::vector<Node> > _comp_nodes; |
179 std::vector<std::vector<Node> > _comp_nodes; |
185 int _qfront, _qback; |
185 int _qfront, _qback; |
186 |
186 |
187 Tolerance _tolerance; |
187 Tolerance _tolerance; |
188 |
188 |
189 // Infinite constant |
189 // Infinite constant |
190 const LargeValue INF; |
190 const LargeCost INF; |
191 |
191 |
192 public: |
192 public: |
193 |
193 |
194 /// \name Named Template Parameters |
194 /// \name Named Template Parameters |
195 /// @{ |
195 /// @{ |
196 |
196 |
197 template <typename T> |
197 template <typename T> |
198 struct SetLargeValueTraits : public Traits { |
198 struct SetLargeCostTraits : public Traits { |
199 typedef T LargeValue; |
199 typedef T LargeCost; |
200 typedef lemon::Tolerance<T> Tolerance; |
200 typedef lemon::Tolerance<T> Tolerance; |
201 }; |
201 }; |
202 |
202 |
203 /// \brief \ref named-templ-param "Named parameter" for setting |
203 /// \brief \ref named-templ-param "Named parameter" for setting |
204 /// \c LargeValue type. |
204 /// \c LargeCost type. |
205 /// |
205 /// |
206 /// \ref named-templ-param "Named parameter" for setting \c LargeValue |
206 /// \ref named-templ-param "Named parameter" for setting \c LargeCost |
207 /// type. It is used for internal computations in the algorithm. |
207 /// type. It is used for internal computations in the algorithm. |
208 template <typename T> |
208 template <typename T> |
209 struct SetLargeValue |
209 struct SetLargeCost |
210 : public Howard<GR, LEN, SetLargeValueTraits<T> > { |
210 : public HowardMmc<GR, CM, SetLargeCostTraits<T> > { |
211 typedef Howard<GR, LEN, SetLargeValueTraits<T> > Create; |
211 typedef HowardMmc<GR, CM, SetLargeCostTraits<T> > Create; |
212 }; |
212 }; |
213 |
213 |
214 template <typename T> |
214 template <typename T> |
215 struct SetPathTraits : public Traits { |
215 struct SetPathTraits : public Traits { |
216 typedef T Path; |
216 typedef T Path; |
223 /// type of the found cycles. |
223 /// type of the found cycles. |
224 /// It must conform to the \ref lemon::concepts::Path "Path" concept |
224 /// It must conform to the \ref lemon::concepts::Path "Path" concept |
225 /// and it must have an \c addBack() function. |
225 /// and it must have an \c addBack() function. |
226 template <typename T> |
226 template <typename T> |
227 struct SetPath |
227 struct SetPath |
228 : public Howard<GR, LEN, SetPathTraits<T> > { |
228 : public HowardMmc<GR, CM, SetPathTraits<T> > { |
229 typedef Howard<GR, LEN, SetPathTraits<T> > Create; |
229 typedef HowardMmc<GR, CM, SetPathTraits<T> > Create; |
230 }; |
230 }; |
231 |
231 |
232 /// @} |
232 /// @} |
233 |
233 |
234 protected: |
234 protected: |
235 |
235 |
236 Howard() {} |
236 HowardMmc() {} |
237 |
237 |
238 public: |
238 public: |
239 |
239 |
240 /// \brief Constructor. |
240 /// \brief Constructor. |
241 /// |
241 /// |
242 /// The constructor of the class. |
242 /// The constructor of the class. |
243 /// |
243 /// |
244 /// \param digraph The digraph the algorithm runs on. |
244 /// \param digraph The digraph the algorithm runs on. |
245 /// \param length The lengths (costs) of the arcs. |
245 /// \param cost The costs of the arcs. |
246 Howard( const Digraph &digraph, |
246 HowardMmc( const Digraph &digraph, |
247 const LengthMap &length ) : |
247 const CostMap &cost ) : |
248 _gr(digraph), _length(length), _best_found(false), |
248 _gr(digraph), _cost(cost), _best_found(false), |
249 _best_length(0), _best_size(1), _cycle_path(NULL), _local_path(false), |
249 _best_cost(0), _best_size(1), _cycle_path(NULL), _local_path(false), |
250 _policy(digraph), _reached(digraph), _level(digraph), _dist(digraph), |
250 _policy(digraph), _reached(digraph), _level(digraph), _dist(digraph), |
251 _comp(digraph), _in_arcs(digraph), |
251 _comp(digraph), _in_arcs(digraph), |
252 INF(std::numeric_limits<LargeValue>::has_infinity ? |
252 INF(std::numeric_limits<LargeCost>::has_infinity ? |
253 std::numeric_limits<LargeValue>::infinity() : |
253 std::numeric_limits<LargeCost>::infinity() : |
254 std::numeric_limits<LargeValue>::max()) |
254 std::numeric_limits<LargeCost>::max()) |
255 {} |
255 {} |
256 |
256 |
257 /// Destructor. |
257 /// Destructor. |
258 ~Howard() { |
258 ~HowardMmc() { |
259 if (_local_path) delete _cycle_path; |
259 if (_local_path) delete _cycle_path; |
260 } |
260 } |
261 |
261 |
262 /// \brief Set the path structure for storing the found cycle. |
262 /// \brief Set the path structure for storing the found cycle. |
263 /// |
263 /// |
264 /// This function sets an external path structure for storing the |
264 /// This function sets an external path structure for storing the |
265 /// found cycle. |
265 /// found cycle. |
266 /// |
266 /// |
267 /// If you don't call this function before calling \ref run() or |
267 /// If you don't call this function before calling \ref run() or |
268 /// \ref findMinMean(), it will allocate a local \ref Path "path" |
268 /// \ref findCycleMean(), it will allocate a local \ref Path "path" |
269 /// structure. The destuctor deallocates this automatically |
269 /// structure. The destuctor deallocates this automatically |
270 /// allocated object, of course. |
270 /// allocated object, of course. |
271 /// |
271 /// |
272 /// \note The algorithm calls only the \ref lemon::Path::addBack() |
272 /// \note The algorithm calls only the \ref lemon::Path::addBack() |
273 /// "addBack()" function of the given path structure. |
273 /// "addBack()" function of the given path structure. |
274 /// |
274 /// |
275 /// \return <tt>(*this)</tt> |
275 /// \return <tt>(*this)</tt> |
276 Howard& cycle(Path &path) { |
276 HowardMmc& cycle(Path &path) { |
277 if (_local_path) { |
277 if (_local_path) { |
278 delete _cycle_path; |
278 delete _cycle_path; |
279 _local_path = false; |
279 _local_path = false; |
280 } |
280 } |
281 _cycle_path = &path; |
281 _cycle_path = &path; |
301 } |
301 } |
302 |
302 |
303 /// \name Execution control |
303 /// \name Execution control |
304 /// The simplest way to execute the algorithm is to call the \ref run() |
304 /// The simplest way to execute the algorithm is to call the \ref run() |
305 /// function.\n |
305 /// function.\n |
306 /// If you only need the minimum mean length, you may call |
306 /// If you only need the minimum mean cost, you may call |
307 /// \ref findMinMean(). |
307 /// \ref findCycleMean(). |
308 |
308 |
309 /// @{ |
309 /// @{ |
310 |
310 |
311 /// \brief Run the algorithm. |
311 /// \brief Run the algorithm. |
312 /// |
312 /// |
313 /// This function runs the algorithm. |
313 /// This function runs the algorithm. |
314 /// It can be called more than once (e.g. if the underlying digraph |
314 /// It can be called more than once (e.g. if the underlying digraph |
315 /// and/or the arc lengths have been modified). |
315 /// and/or the arc costs have been modified). |
316 /// |
316 /// |
317 /// \return \c true if a directed cycle exists in the digraph. |
317 /// \return \c true if a directed cycle exists in the digraph. |
318 /// |
318 /// |
319 /// \note <tt>mmc.run()</tt> is just a shortcut of the following code. |
319 /// \note <tt>mmc.run()</tt> is just a shortcut of the following code. |
320 /// \code |
320 /// \code |
321 /// return mmc.findMinMean() && mmc.findCycle(); |
321 /// return mmc.findCycleMean() && mmc.findCycle(); |
322 /// \endcode |
322 /// \endcode |
323 bool run() { |
323 bool run() { |
324 return findMinMean() && findCycle(); |
324 return findCycleMean() && findCycle(); |
325 } |
325 } |
326 |
326 |
327 /// \brief Find the minimum cycle mean. |
327 /// \brief Find the minimum cycle mean. |
328 /// |
328 /// |
329 /// This function finds the minimum mean length of the directed |
329 /// This function finds the minimum mean cost of the directed |
330 /// cycles in the digraph. |
330 /// cycles in the digraph. |
331 /// |
331 /// |
332 /// \return \c true if a directed cycle exists in the digraph. |
332 /// \return \c true if a directed cycle exists in the digraph. |
333 bool findMinMean() { |
333 bool findCycleMean() { |
334 // Initialize and find strongly connected components |
334 // Initialize and find strongly connected components |
335 init(); |
335 init(); |
336 findComponents(); |
336 findComponents(); |
337 |
337 |
338 // Find the minimum cycle mean in the components |
338 // Find the minimum cycle mean in the components |
343 findPolicyCycle(); |
343 findPolicyCycle(); |
344 if (!computeNodeDistances()) break; |
344 if (!computeNodeDistances()) break; |
345 } |
345 } |
346 // Update the best cycle (global minimum mean cycle) |
346 // Update the best cycle (global minimum mean cycle) |
347 if ( _curr_found && (!_best_found || |
347 if ( _curr_found && (!_best_found || |
348 _curr_length * _best_size < _best_length * _curr_size) ) { |
348 _curr_cost * _best_size < _best_cost * _curr_size) ) { |
349 _best_found = true; |
349 _best_found = true; |
350 _best_length = _curr_length; |
350 _best_cost = _curr_cost; |
351 _best_size = _curr_size; |
351 _best_size = _curr_size; |
352 _best_node = _curr_node; |
352 _best_node = _curr_node; |
353 } |
353 } |
354 } |
354 } |
355 return _best_found; |
355 return _best_found; |
356 } |
356 } |
357 |
357 |
358 /// \brief Find a minimum mean directed cycle. |
358 /// \brief Find a minimum mean directed cycle. |
359 /// |
359 /// |
360 /// This function finds a directed cycle of minimum mean length |
360 /// This function finds a directed cycle of minimum mean cost |
361 /// in the digraph using the data computed by findMinMean(). |
361 /// in the digraph using the data computed by findCycleMean(). |
362 /// |
362 /// |
363 /// \return \c true if a directed cycle exists in the digraph. |
363 /// \return \c true if a directed cycle exists in the digraph. |
364 /// |
364 /// |
365 /// \pre \ref findMinMean() must be called before using this function. |
365 /// \pre \ref findCycleMean() must be called before using this function. |
366 bool findCycle() { |
366 bool findCycle() { |
367 if (!_best_found) return false; |
367 if (!_best_found) return false; |
368 _cycle_path->addBack(_policy[_best_node]); |
368 _cycle_path->addBack(_policy[_best_node]); |
369 for ( Node v = _best_node; |
369 for ( Node v = _best_node; |
370 (v = _gr.target(_policy[v])) != _best_node; ) { |
370 (v = _gr.target(_policy[v])) != _best_node; ) { |
380 /// functions.\n |
380 /// functions.\n |
381 /// The algorithm should be executed before using them. |
381 /// The algorithm should be executed before using them. |
382 |
382 |
383 /// @{ |
383 /// @{ |
384 |
384 |
385 /// \brief Return the total length of the found cycle. |
385 /// \brief Return the total cost of the found cycle. |
386 /// |
386 /// |
387 /// This function returns the total length of the found cycle. |
387 /// This function returns the total cost of the found cycle. |
388 /// |
388 /// |
389 /// \pre \ref run() or \ref findMinMean() must be called before |
389 /// \pre \ref run() or \ref findCycleMean() must be called before |
390 /// using this function. |
390 /// using this function. |
391 Value cycleLength() const { |
391 Cost cycleCost() const { |
392 return static_cast<Value>(_best_length); |
392 return static_cast<Cost>(_best_cost); |
393 } |
393 } |
394 |
394 |
395 /// \brief Return the number of arcs on the found cycle. |
395 /// \brief Return the number of arcs on the found cycle. |
396 /// |
396 /// |
397 /// This function returns the number of arcs on the found cycle. |
397 /// This function returns the number of arcs on the found cycle. |
398 /// |
398 /// |
399 /// \pre \ref run() or \ref findMinMean() must be called before |
399 /// \pre \ref run() or \ref findCycleMean() must be called before |
400 /// using this function. |
400 /// using this function. |
401 int cycleArcNum() const { |
401 int cycleSize() const { |
402 return _best_size; |
402 return _best_size; |
403 } |
403 } |
404 |
404 |
405 /// \brief Return the mean length of the found cycle. |
405 /// \brief Return the mean cost of the found cycle. |
406 /// |
406 /// |
407 /// This function returns the mean length of the found cycle. |
407 /// This function returns the mean cost of the found cycle. |
408 /// |
408 /// |
409 /// \note <tt>alg.cycleMean()</tt> is just a shortcut of the |
409 /// \note <tt>alg.cycleMean()</tt> is just a shortcut of the |
410 /// following code. |
410 /// following code. |
411 /// \code |
411 /// \code |
412 /// return static_cast<double>(alg.cycleLength()) / alg.cycleArcNum(); |
412 /// return static_cast<double>(alg.cycleCost()) / alg.cycleSize(); |
413 /// \endcode |
413 /// \endcode |
414 /// |
414 /// |
415 /// \pre \ref run() or \ref findMinMean() must be called before |
415 /// \pre \ref run() or \ref findCycleMean() must be called before |
416 /// using this function. |
416 /// using this function. |
417 double cycleMean() const { |
417 double cycleMean() const { |
418 return static_cast<double>(_best_length) / _best_size; |
418 return static_cast<double>(_best_cost) / _best_size; |
419 } |
419 } |
420 |
420 |
421 /// \brief Return the found cycle. |
421 /// \brief Return the found cycle. |
422 /// |
422 /// |
423 /// This function returns a const reference to the path structure |
423 /// This function returns a const reference to the path structure |