# HG changeset patch
# User Peter Kovacs <kpeter@inf.elte.hu>
# Date 1328290203 -3600
# Node ID ee2fe24de0158171e2cdacb5807d0a4daeb99d99
# Parent cfbabca1b4e9b8d4ce408f853db728509d020110
Optional iteration limit in HowardMmc (#438)
diff --git a/lemon/howard_mmc.h b/lemon/howard_mmc.h
a
|
b
|
|
149 | 149 | /// The \ref HowardMmcDefaultTraits "traits class" of the algorithm |
150 | 150 | typedef TR Traits; |
151 | 151 | |
| 152 | /// \brief Constants for the causes of search termination. |
| 153 | /// |
| 154 | /// Enum type containing constants for the different causes of search |
| 155 | /// termination. The \ref findCycleMean(int) function returns one of |
| 156 | /// these values. |
| 157 | enum TerminationCause { |
| 158 | |
| 159 | /// Optimal solution (minimum cycle mean) is found. |
| 160 | OPTIMAL, |
| 161 | |
| 162 | /// No directed cycle can be found in the digraph. |
| 163 | NO_CYCLE, |
| 164 | |
| 165 | /// The iteration count limit is reached. |
| 166 | ITERATION_LIMIT |
| 167 | }; |
| 168 | |
152 | 169 | private: |
153 | 170 | |
154 | 171 | TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
… |
… |
|
330 | 347 | /// cycles in the digraph. |
331 | 348 | /// |
332 | 349 | /// \return \c true if a directed cycle exists in the digraph. |
| 350 | /// |
| 351 | /// \note <tt>mmc.findCycleMean()</tt> is just a shortcut of the |
| 352 | /// following code. |
| 353 | /// \code |
| 354 | /// return mmc.findCycleMean(-1) == mmc.OPTIMAL; |
| 355 | /// \endcode |
333 | 356 | bool findCycleMean() { |
| 357 | return findCycleMean(-1) == OPTIMAL; |
| 358 | } |
| 359 | |
| 360 | /// \brief Find the minimum cycle mean. |
| 361 | /// |
| 362 | /// This function finds the minimum mean cost of the directed |
| 363 | /// cycles in the digraph or at least an upper bound for it. |
| 364 | /// At most the given number of iterations are performed during |
| 365 | /// the search process. The return value indicates if the optimal |
| 366 | /// solution is found or the iteration limit is reached. |
| 367 | /// In the latter case, an approximate solution can be obtained |
| 368 | /// using the query functions. |
| 369 | /// Such an approximate solution corresponds to a directed cycle |
| 370 | /// whose mean cost is relatively small, but not necessarily |
| 371 | /// minimal. |
| 372 | /// |
| 373 | /// \param limit The maximum allowed number of iterations duirng |
| 374 | /// the search process. Negative values mean that this limitation |
| 375 | /// is disabled, i.e. the algorithm runs until it finds the exact |
| 376 | /// optimal solution. |
| 377 | /// |
| 378 | /// \return The termination cause of the search process. |
| 379 | /// For more information, see \ref TerminationCause. |
| 380 | TerminationCause findCycleMean(int limit) { |
334 | 381 | // Initialize and find strongly connected components |
335 | 382 | init(); |
336 | 383 | findComponents(); |
| 384 | |
| 385 | // Check iteration limit |
| 386 | if (limit < 0) limit = std::numeric_limits<int>::max(); |
337 | 387 | |
338 | 388 | // Find the minimum cycle mean in the components |
| 389 | int iter_count = 0; |
| 390 | bool iter_limit = false; |
339 | 391 | for (int comp = 0; comp < _comp_num; ++comp) { |
340 | 392 | // Find the minimum mean cycle in the current component |
341 | 393 | if (!buildPolicyGraph(comp)) continue; |
342 | 394 | while (true) { |
| 395 | if (++iter_count > limit) { |
| 396 | iter_limit = true; |
| 397 | break; |
| 398 | } |
343 | 399 | findPolicyCycle(); |
344 | 400 | if (!computeNodeDistances()) break; |
345 | 401 | } |
| 402 | |
346 | 403 | // Update the best cycle (global minimum mean cycle) |
347 | 404 | if ( _curr_found && (!_best_found || |
348 | 405 | _curr_cost * _best_size < _best_cost * _curr_size) ) { |
… |
… |
|
351 | 408 | _best_size = _curr_size; |
352 | 409 | _best_node = _curr_node; |
353 | 410 | } |
| 411 | |
| 412 | if (iter_limit) break; |
354 | 413 | } |
355 | | return _best_found; |
| 414 | |
| 415 | if (iter_limit) { |
| 416 | return ITERATION_LIMIT; |
| 417 | } else { |
| 418 | return _best_found ? OPTIMAL : NO_CYCLE; |
| 419 | } |
356 | 420 | } |
357 | 421 | |
358 | 422 | /// \brief Find a minimum mean directed cycle. |
diff --git a/test/min_mean_cycle_test.cc b/test/min_mean_cycle_test.cc
a
|
b
|
|
210 | 210 | checkMmcAlg<HowardMmc<GR, IntArcMap> >(gr, l2, c2, 5, 2); |
211 | 211 | checkMmcAlg<HowardMmc<GR, IntArcMap> >(gr, l3, c3, 0, 1); |
212 | 212 | checkMmcAlg<HowardMmc<GR, IntArcMap> >(gr, l4, c4, -1, 1); |
| 213 | |
| 214 | // Howard with iteration limit |
| 215 | HowardMmc<GR, IntArcMap> mmc(gr, l1); |
| 216 | check((mmc.findCycleMean(2) == HowardMmc<GR, IntArcMap>::ITERATION_LIMIT), |
| 217 | "Wrong termination cause"); |
| 218 | check((mmc.findCycleMean(4) == HowardMmc<GR, IntArcMap>::OPTIMAL), |
| 219 | "Wrong termination cause"); |
213 | 220 | } |
214 | 221 | |
215 | 222 | return 0; |