# HG changeset patch # User Peter Kovacs # Date 1352959529 -3600 # Node ID 21a9f829ab68555675534cb075253929315be385 # Parent 764826c6e2b451f09cfa6e588a3de005bc308154 Optional iteration limit in HowardMmc (#438) diff -r 764826c6e2b4 -r 21a9f829ab68 lemon/howard_mmc.h --- a/lemon/howard_mmc.h Thu Nov 08 09:07:41 2012 +0100 +++ b/lemon/howard_mmc.h Thu Nov 15 07:05:29 2012 +0100 @@ -149,6 +149,23 @@ /// The \ref HowardMmcDefaultTraits "traits class" of the algorithm typedef TR Traits; + /// \brief Constants for the causes of search termination. + /// + /// Enum type containing constants for the different causes of search + /// termination. The \ref findCycleMean() function returns one of + /// these values. + enum TerminationCause { + + /// No directed cycle can be found in the digraph. + NO_CYCLE = 0, + + /// Optimal solution (minimum cycle mean) is found. + OPTIMAL = 1, + + /// The iteration count limit is reached. + ITERATION_LIMIT + }; + private: TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); @@ -324,25 +341,46 @@ return findCycleMean() && findCycle(); } - /// \brief Find the minimum cycle mean. + /// \brief Find the minimum cycle mean (or an upper bound). /// /// This function finds the minimum mean cost of the directed - /// cycles in the digraph. + /// cycles in the digraph (or an upper bound for it). /// - /// \return \c true if a directed cycle exists in the digraph. - bool findCycleMean() { + /// By default, the function finds the exact minimum cycle mean, + /// but an optional limit can also be specified for the number of + /// iterations performed during the search process. + /// The return value indicates if the optimal solution is found + /// or the iteration limit is reached. In the latter case, an + /// approximate solution is provided, which corresponds to a directed + /// cycle whose mean cost is relatively small, but not necessarily + /// minimal. + /// + /// \param limit The maximum allowed number of iterations during + /// the search process. Its default value implies that the algorithm + /// runs until it finds the exact optimal solution. + /// + /// \return The termination cause of the search process. + /// For more information, see \ref TerminationCause. + TerminationCause findCycleMean(int limit = std::numeric_limits::max()) { // Initialize and find strongly connected components init(); findComponents(); // Find the minimum cycle mean in the components + int iter_count = 0; + bool iter_limit_reached = false; for (int comp = 0; comp < _comp_num; ++comp) { // Find the minimum mean cycle in the current component if (!buildPolicyGraph(comp)) continue; while (true) { + if (++iter_count > limit) { + iter_limit_reached = true; + break; + } findPolicyCycle(); if (!computeNodeDistances()) break; } + // Update the best cycle (global minimum mean cycle) if ( _curr_found && (!_best_found || _curr_cost * _best_size < _best_cost * _curr_size) ) { @@ -351,8 +389,15 @@ _best_size = _curr_size; _best_node = _curr_node; } + + if (iter_limit_reached) break; } - return _best_found; + + if (iter_limit_reached) { + return ITERATION_LIMIT; + } else { + return _best_found ? OPTIMAL : NO_CYCLE; + } } /// \brief Find a minimum mean directed cycle. diff -r 764826c6e2b4 -r 21a9f829ab68 test/min_mean_cycle_test.cc --- a/test/min_mean_cycle_test.cc Thu Nov 08 09:07:41 2012 +0100 +++ b/test/min_mean_cycle_test.cc Thu Nov 15 07:05:29 2012 +0100 @@ -110,7 +110,7 @@ const SmartDigraph::ArcMap& cm, int cost, int size) { MMC alg(gr, lm); - alg.findCycleMean(); + check(alg.findCycleMean(), "Wrong result"); check(alg.cycleMean() == static_cast(cost) / size, "Wrong cycle mean"); alg.findCycle(); @@ -210,6 +210,13 @@ checkMmcAlg >(gr, l2, c2, 5, 2); checkMmcAlg >(gr, l3, c3, 0, 1); checkMmcAlg >(gr, l4, c4, -1, 1); + + // Howard with iteration limit + HowardMmc mmc(gr, l1); + check((mmc.findCycleMean(2) == HowardMmc::ITERATION_LIMIT), + "Wrong termination cause"); + check((mmc.findCycleMean(4) == HowardMmc::OPTIMAL), + "Wrong termination cause"); } return 0;