# 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; |