# 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) { |