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