# HG changeset patch
# User Peter Kovacs <kpeter@inf.elte.hu>
# Date 1329319288 -3600
# Node ID c63fed6750c63f56d40d98bea06c2c7da676fe8a
# Parent ee2fe24de0158171e2cdacb5807d0a4daeb99d99
Ensure strongly polynomial running time for CycleCanceling (#436)
The number of iterations performed by Howard's algorithm is limited.
If the limit is reached, a strongly polynomial implementation,
HartmannOrlinMmc is executed to find a minimum mean cycle.
Note that Howard's algorithm is usually much faster in practice
than the other two minimum mean cycle algorithms currently
implemented in LEMON.
diff --git a/lemon/cycle_canceling.h b/lemon/cycle_canceling.h
|
a
|
b
|
|
| 35 | 35 | #include <lemon/circulation.h> |
| 36 | 36 | #include <lemon/bellman_ford.h> |
| 37 | 37 | #include <lemon/howard_mmc.h> |
| | 38 | #include <lemon/hartmann_orlin_mmc.h> |
| 38 | 39 | |
| 39 | 40 | namespace lemon { |
| 40 | 41 | |
| … |
… |
|
| 922 | 923 | |
| 923 | 924 | // Execute the "Minimum Mean Cycle Canceling" method |
| 924 | 925 | void startMinMeanCycleCanceling() { |
| 925 | | typedef SimplePath<StaticDigraph> SPath; |
| | 926 | typedef Path<StaticDigraph> SPath; |
| 926 | 927 | typedef typename SPath::ArcIt SPathArcIt; |
| 927 | 928 | typedef typename HowardMmc<StaticDigraph, CostArcMap> |
| 928 | | ::template SetPath<SPath>::Create MMC; |
| | 929 | ::template SetPath<SPath>::Create HwMmc; |
| | 930 | typedef typename HartmannOrlinMmc<StaticDigraph, CostArcMap> |
| | 931 | ::template SetPath<SPath>::Create HoMmc; |
| | 932 | |
| | 933 | const double HW_ITER_LIMIT_FACTOR = 1.0; |
| | 934 | const int HW_ITER_LIMIT_MIN_VALUE = 5; |
| | 935 | |
| | 936 | const int hw_iter_limit = |
| | 937 | std::max(static_cast<int>(HW_ITER_LIMIT_FACTOR * _node_num), |
| | 938 | HW_ITER_LIMIT_MIN_VALUE); |
| 929 | 939 | |
| 930 | 940 | SPath cycle; |
| 931 | | MMC mmc(_sgr, _cost_map); |
| 932 | | mmc.cycle(cycle); |
| | 941 | HwMmc hw_mmc(_sgr, _cost_map); |
| | 942 | hw_mmc.cycle(cycle); |
| 933 | 943 | buildResidualNetwork(); |
| 934 | | while (mmc.findCycleMean() && mmc.cycleCost() < 0) { |
| 935 | | // Find the cycle |
| 936 | | mmc.findCycle(); |
| 937 | | |
| | 944 | while (true) { |
| | 945 | |
| | 946 | typename HwMmc::TerminationCause hw_tc = |
| | 947 | hw_mmc.findCycleMean(hw_iter_limit); |
| | 948 | if (hw_tc == HwMmc::ITERATION_LIMIT) { |
| | 949 | // Howard's algorithm reached the iteration limit, start a |
| | 950 | // strongly polynomial algorithm instead |
| | 951 | HoMmc ho_mmc(_sgr, _cost_map); |
| | 952 | ho_mmc.cycle(cycle); |
| | 953 | // Find a minimum mean cycle (Hartmann-Orlin algorithm) |
| | 954 | if (!(ho_mmc.findCycleMean() && ho_mmc.cycleCost() < 0)) break; |
| | 955 | ho_mmc.findCycle(); |
| | 956 | } else { |
| | 957 | // Find a minimum mean cycle (Howard algorithm) |
| | 958 | if (!(hw_tc == HwMmc::OPTIMAL && hw_mmc.cycleCost() < 0)) break; |
| | 959 | hw_mmc.findCycle(); |
| | 960 | } |
| | 961 | |
| 938 | 962 | // Compute delta value |
| 939 | 963 | Value delta = INF; |
| 940 | 964 | for (SPathArcIt a(cycle); a != INVALID; ++a) { |
| … |
… |
|
| 959 | 983 | // Constants for the min mean cycle computations |
| 960 | 984 | const double LIMIT_FACTOR = 1.0; |
| 961 | 985 | const int MIN_LIMIT = 5; |
| | 986 | const double HW_ITER_LIMIT_FACTOR = 1.0; |
| | 987 | const int HW_ITER_LIMIT_MIN_VALUE = 5; |
| | 988 | |
| | 989 | const int hw_iter_limit = |
| | 990 | std::max(static_cast<int>(HW_ITER_LIMIT_FACTOR * _node_num), |
| | 991 | HW_ITER_LIMIT_MIN_VALUE); |
| 962 | 992 | |
| 963 | 993 | // Contruct auxiliary data vectors |
| 964 | 994 | DoubleVector pi(_res_node_num, 0.0); |
| … |
… |
|
| 1132 | 1162 | } |
| 1133 | 1163 | } |
| 1134 | 1164 | } else { |
| 1135 | | typedef HowardMmc<StaticDigraph, CostArcMap> MMC; |
| | 1165 | typedef HowardMmc<StaticDigraph, CostArcMap> HwMmc; |
| | 1166 | typedef HartmannOrlinMmc<StaticDigraph, CostArcMap> HoMmc; |
| 1136 | 1167 | typedef typename BellmanFord<StaticDigraph, CostArcMap> |
| 1137 | 1168 | ::template SetDistMap<CostNodeMap>::Create BF; |
| 1138 | 1169 | |
| 1139 | 1170 | // Set epsilon to the minimum cycle mean |
| | 1171 | Cost cycle_cost = 0; |
| | 1172 | int cycle_size = 1; |
| 1140 | 1173 | buildResidualNetwork(); |
| 1141 | | MMC mmc(_sgr, _cost_map); |
| 1142 | | mmc.findCycleMean(); |
| 1143 | | epsilon = -mmc.cycleMean(); |
| 1144 | | Cost cycle_cost = mmc.cycleCost(); |
| 1145 | | int cycle_size = mmc.cycleSize(); |
| | 1174 | HwMmc hw_mmc(_sgr, _cost_map); |
| | 1175 | if (hw_mmc.findCycleMean(hw_iter_limit) == HwMmc::ITERATION_LIMIT) { |
| | 1176 | // Howard's algorithm reached the iteration limit, start a |
| | 1177 | // strongly polynomial algorithm instead |
| | 1178 | HoMmc ho_mmc(_sgr, _cost_map); |
| | 1179 | ho_mmc.findCycleMean(); |
| | 1180 | epsilon = -ho_mmc.cycleMean(); |
| | 1181 | cycle_cost = ho_mmc.cycleCost(); |
| | 1182 | cycle_size = ho_mmc.cycleSize(); |
| | 1183 | } else { |
| | 1184 | // Set epsilon |
| | 1185 | epsilon = -hw_mmc.cycleMean(); |
| | 1186 | cycle_cost = hw_mmc.cycleCost(); |
| | 1187 | cycle_size = hw_mmc.cycleSize(); |
| | 1188 | } |
| 1146 | 1189 | |
| 1147 | 1190 | // Compute feasible potentials for the current epsilon |
| 1148 | 1191 | for (int i = 0; i != int(_cost_vec.size()); ++i) { |