diff -r 21a9f829ab68 -r f6f6896a4724 lemon/cycle_canceling.h --- a/lemon/cycle_canceling.h Thu Nov 15 07:05:29 2012 +0100 +++ b/lemon/cycle_canceling.h Thu Nov 15 07:17:48 2012 +0100 @@ -35,6 +35,7 @@ #include #include #include +#include namespace lemon { @@ -927,19 +928,42 @@ // Execute the "Minimum Mean Cycle Canceling" method void startMinMeanCycleCanceling() { - typedef SimplePath SPath; + typedef Path SPath; typedef typename SPath::ArcIt SPathArcIt; typedef typename HowardMmc - ::template SetPath::Create MMC; + ::template SetPath::Create HwMmc; + typedef typename HartmannOrlinMmc + ::template SetPath::Create HoMmc; + + const double HW_ITER_LIMIT_FACTOR = 1.0; + const int HW_ITER_LIMIT_MIN_VALUE = 5; + + const int hw_iter_limit = + std::max(static_cast(HW_ITER_LIMIT_FACTOR * _node_num), + HW_ITER_LIMIT_MIN_VALUE); SPath cycle; - MMC mmc(_sgr, _cost_map); - mmc.cycle(cycle); + HwMmc hw_mmc(_sgr, _cost_map); + hw_mmc.cycle(cycle); buildResidualNetwork(); - while (mmc.findCycleMean() && mmc.cycleCost() < 0) { - // Find the cycle - mmc.findCycle(); - + while (true) { + + typename HwMmc::TerminationCause hw_tc = + hw_mmc.findCycleMean(hw_iter_limit); + if (hw_tc == HwMmc::ITERATION_LIMIT) { + // Howard's algorithm reached the iteration limit, start a + // strongly polynomial algorithm instead + HoMmc ho_mmc(_sgr, _cost_map); + ho_mmc.cycle(cycle); + // Find a minimum mean cycle (Hartmann-Orlin algorithm) + if (!(ho_mmc.findCycleMean() && ho_mmc.cycleCost() < 0)) break; + ho_mmc.findCycle(); + } else { + // Find a minimum mean cycle (Howard algorithm) + if (!(hw_tc == HwMmc::OPTIMAL && hw_mmc.cycleCost() < 0)) break; + hw_mmc.findCycle(); + } + // Compute delta value Value delta = INF; for (SPathArcIt a(cycle); a != INVALID; ++a) { @@ -964,6 +988,12 @@ // Constants for the min mean cycle computations const double LIMIT_FACTOR = 1.0; const int MIN_LIMIT = 5; + const double HW_ITER_LIMIT_FACTOR = 1.0; + const int HW_ITER_LIMIT_MIN_VALUE = 5; + + const int hw_iter_limit = + std::max(static_cast(HW_ITER_LIMIT_FACTOR * _node_num), + HW_ITER_LIMIT_MIN_VALUE); // Contruct auxiliary data vectors DoubleVector pi(_res_node_num, 0.0); @@ -1137,17 +1167,30 @@ } } } else { - typedef HowardMmc MMC; + typedef HowardMmc HwMmc; + typedef HartmannOrlinMmc HoMmc; typedef typename BellmanFord ::template SetDistMap::Create BF; // Set epsilon to the minimum cycle mean + Cost cycle_cost = 0; + int cycle_size = 1; buildResidualNetwork(); - MMC mmc(_sgr, _cost_map); - mmc.findCycleMean(); - epsilon = -mmc.cycleMean(); - Cost cycle_cost = mmc.cycleCost(); - int cycle_size = mmc.cycleSize(); + HwMmc hw_mmc(_sgr, _cost_map); + if (hw_mmc.findCycleMean(hw_iter_limit) == HwMmc::ITERATION_LIMIT) { + // Howard's algorithm reached the iteration limit, start a + // strongly polynomial algorithm instead + HoMmc ho_mmc(_sgr, _cost_map); + ho_mmc.findCycleMean(); + epsilon = -ho_mmc.cycleMean(); + cycle_cost = ho_mmc.cycleCost(); + cycle_size = ho_mmc.cycleSize(); + } else { + // Set epsilon + epsilon = -hw_mmc.cycleMean(); + cycle_cost = hw_mmc.cycleCost(); + cycle_size = hw_mmc.cycleSize(); + } // Compute feasible potentials for the current epsilon for (int i = 0; i != int(_cost_vec.size()); ++i) {