Ticket #417: 417-ca9d1dc77026--78d9eddfaf1a.patch
File 417-ca9d1dc77026--78d9eddfaf1a.patch, 29.4 KB (added by , 14 years ago) |
---|
-
lemon/cost_scaling.h
# HG changeset patch # User Peter Kovacs <kpeter@inf.elte.hu> # Date 1300212980 -3600 # Node ID 4866b640dba97fae2fdfdd81cf4bec497d1cd48d # Parent ca9d1dc770268c0b476d33857ece1c13471ea447 Fix and improve refine methods in CostScaling (#417) The old implementation could run into infinite loop using the AUGMENT method. diff --git a/lemon/cost_scaling.h b/lemon/cost_scaling.h
a b 1100 1100 } 1101 1101 1102 1102 /// Execute the algorithm performing augment and relabel operations 1103 void startAugment(int max_length = std::numeric_limits<int>::max()) {1103 void startAugment(int max_length) { 1104 1104 // Paramters for heuristics 1105 1105 const int EARLY_TERM_EPSILON_LIMIT = 1000; 1106 const double GLOBAL_UPDATE_FACTOR = 3.0; 1107 1108 const int global_update_freq = int(GLOBAL_UPDATE_FACTOR * 1106 const double GLOBAL_UPDATE_FACTOR = 1.0; 1107 const int global_update_skip = static_cast<int>(GLOBAL_UPDATE_FACTOR * 1109 1108 (_res_node_num + _sup_node_num * _sup_node_num)); 1110 int next_update_limit = global_update_freq; 1111 1112 int relabel_cnt = 0; 1109 int next_global_update_limit = global_update_skip; 1113 1110 1114 1111 // Perform cost scaling phases 1115 std::vector<int> path; 1112 IntVector path; 1113 BoolVector path_arc(_res_arc_num, false); 1114 int relabel_cnt = 0; 1116 1115 for ( ; _epsilon >= 1; _epsilon = _epsilon < _alpha && _epsilon > 1 ? 1117 1116 1 : _epsilon / _alpha ) 1118 1117 { … … 1135 1134 int start = _active_nodes.front(); 1136 1135 1137 1136 // Find an augmenting path from the start node 1138 path.clear();1139 1137 int tip = start; 1140 while ( _excess[tip] >= 0 && int(path.size()) < max_length) {1138 while (int(path.size()) < max_length && _excess[tip] >= 0) { 1141 1139 int u; 1142 LargeCost min_red_cost, rc, pi_tip = _pi[tip]; 1140 LargeCost rc, min_red_cost = std::numeric_limits<LargeCost>::max(); 1141 LargeCost pi_tip = _pi[tip]; 1143 1142 int last_out = _first_out[tip+1]; 1144 1143 for (int a = _next_out[tip]; a != last_out; ++a) { 1145 u = _target[a]; 1146 if (_res_cap[a] > 0 && _cost[a] + pi_tip - _pi[u] < 0) { 1147 path.push_back(a); 1148 _next_out[tip] = a; 1149 tip = u; 1150 goto next_step; 1144 if (_res_cap[a] > 0) { 1145 u = _target[a]; 1146 rc = _cost[a] + pi_tip - _pi[u]; 1147 if (rc < 0) { 1148 path.push_back(a); 1149 _next_out[tip] = a; 1150 if (path_arc[a]) { 1151 goto augment; // a cycle is found, stop path search 1152 } 1153 tip = u; 1154 path_arc[a] = true; 1155 goto next_step; 1156 } 1157 else if (rc < min_red_cost) { 1158 min_red_cost = rc; 1159 } 1151 1160 } 1152 1161 } 1153 1162 1154 1163 // Relabel tip node 1155 min_red_cost = std::numeric_limits<LargeCost>::max();1156 1164 if (tip != start) { 1157 1165 int ra = _reverse[path.back()]; 1158 min_red_cost = _cost[ra] + pi_tip - _pi[_target[ra]]; 1166 min_red_cost = 1167 std::min(min_red_cost, _cost[ra] + pi_tip - _pi[_target[ra]]); 1159 1168 } 1169 last_out = _next_out[tip]; 1160 1170 for (int a = _first_out[tip]; a != last_out; ++a) { 1161 rc = _cost[a] + pi_tip - _pi[_target[a]]; 1162 if (_res_cap[a] > 0 && rc < min_red_cost) { 1163 min_red_cost = rc; 1171 if (_res_cap[a] > 0) { 1172 rc = _cost[a] + pi_tip - _pi[_target[a]]; 1173 if (rc < min_red_cost) { 1174 min_red_cost = rc; 1175 } 1164 1176 } 1165 1177 } 1166 1178 _pi[tip] -= min_red_cost + _epsilon; … … 1169 1181 1170 1182 // Step back 1171 1183 if (tip != start) { 1172 tip = _source[path.back()]; 1184 int pa = path.back(); 1185 path_arc[pa] = false; 1186 tip = _source[pa]; 1173 1187 path.pop_back(); 1174 1188 } 1175 1189 … … 1177 1191 } 1178 1192 1179 1193 // Augment along the found path (as much flow as possible) 1194 augment: 1180 1195 Value delta; 1181 1196 int pa, u, v = start; 1182 1197 for (int i = 0; i != int(path.size()); ++i) { 1183 1198 pa = path[i]; 1184 1199 u = v; 1185 1200 v = _target[pa]; 1201 path_arc[pa] = false; 1186 1202 delta = std::min(_res_cap[pa], _excess[u]); 1187 1203 _res_cap[pa] -= delta; 1188 1204 _res_cap[_reverse[pa]] += delta; 1189 1205 _excess[u] -= delta; 1190 1206 _excess[v] += delta; 1191 if (_excess[v] > 0 && _excess[v] <= delta) 1207 if (_excess[v] > 0 && _excess[v] <= delta) { 1192 1208 _active_nodes.push_back(v); 1209 } 1193 1210 } 1211 path.clear(); 1194 1212 1195 1213 // Global update heuristic 1196 if (relabel_cnt >= next_ update_limit) {1214 if (relabel_cnt >= next_global_update_limit) { 1197 1215 globalUpdate(); 1198 next_ update_limit += global_update_freq;1216 next_global_update_limit += global_update_skip; 1199 1217 } 1200 1218 } 1219 1201 1220 } 1221 1202 1222 } 1203 1223 1204 1224 /// Execute the algorithm performing push and relabel operations … … 1207 1227 const int EARLY_TERM_EPSILON_LIMIT = 1000; 1208 1228 const double GLOBAL_UPDATE_FACTOR = 2.0; 1209 1229 1210 const int global_update_ freq = int(GLOBAL_UPDATE_FACTOR *1230 const int global_update_skip = static_cast<int>(GLOBAL_UPDATE_FACTOR * 1211 1231 (_res_node_num + _sup_node_num * _sup_node_num)); 1212 int next_update_limit = global_update_freq; 1213 1214 int relabel_cnt = 0; 1232 int next_global_update_limit = global_update_skip; 1215 1233 1216 1234 // Perform cost scaling phases 1217 1235 BoolVector hyper(_res_node_num, false); 1218 1236 LargeCostVector hyper_cost(_res_node_num); 1237 int relabel_cnt = 0; 1219 1238 for ( ; _epsilon >= 1; _epsilon = _epsilon < _alpha && _epsilon > 1 ? 1220 1239 1 : _epsilon / _alpha ) 1221 1240 { … … 1293 1312 min_red_cost = hyper[n] ? -hyper_cost[n] : 1294 1313 std::numeric_limits<LargeCost>::max(); 1295 1314 for (int a = _first_out[n]; a != last_out; ++a) { 1296 rc = _cost[a] + pi_n - _pi[_target[a]]; 1297 if (_res_cap[a] > 0 && rc < min_red_cost) { 1298 min_red_cost = rc; 1315 if (_res_cap[a] > 0) { 1316 rc = _cost[a] + pi_n - _pi[_target[a]]; 1317 if (rc < min_red_cost) { 1318 min_red_cost = rc; 1319 } 1299 1320 } 1300 1321 } 1301 1322 _pi[n] -= min_red_cost + _epsilon; … … 1313 1334 } 1314 1335 1315 1336 // Global update heuristic 1316 if (relabel_cnt >= next_ update_limit) {1337 if (relabel_cnt >= next_global_update_limit) { 1317 1338 globalUpdate(); 1318 1339 for (int u = 0; u != _res_node_num; ++u) 1319 1340 hyper[u] = false; 1320 next_ update_limit += global_update_freq;1341 next_global_update_limit += global_update_skip; 1321 1342 } 1322 1343 } 1323 1344 } -
lemon/cost_scaling.h
# HG changeset patch # User Peter Kovacs <kpeter@inf.elte.hu> # Date 1300213941 -3600 # Node ID f88191cb740f5469104cdde0e26d11d6a4edd3c8 # Parent 4866b640dba97fae2fdfdd81cf4bec497d1cd48d Implement the scaling Price Refinement heuristic in CostScaling (#417) instead of Early Termination. These two heuristics are similar, but the newer one is faster and not only makes it possible to skip some epsilon phases, but it can improve the performance of the other phases, as well. diff --git a/lemon/cost_scaling.h b/lemon/cost_scaling.h
a b 980 980 } 981 981 } 982 982 983 // Early termination heuristic 984 bool earlyTermination() { 985 const double EARLY_TERM_FACTOR = 3.0; 983 // Price (potential) refinement heuristic 984 bool priceRefinement() { 986 985 987 // Build a static residual graph 988 _arc_vec.clear(); 989 _cost_vec.clear(); 990 for (int j = 0; j != _res_arc_num; ++j) { 991 if (_res_cap[j] > 0) { 992 _arc_vec.push_back(IntPair(_source[j], _target[j])); 993 _cost_vec.push_back(_cost[j] + 1); 986 // Stack for stroing the topological order 987 IntVector stack(_res_node_num); 988 int stack_top; 989 990 // Perform phases 991 while (topologicalSort(stack, stack_top)) { 992 993 // Compute node ranks in the acyclic admissible network and 994 // store the nodes in buckets 995 for (int i = 0; i != _res_node_num; ++i) { 996 _rank[i] = 0; 994 997 } 998 const int bucket_end = _root + 1; 999 for (int r = 0; r != _max_rank; ++r) { 1000 _buckets[r] = bucket_end; 1001 } 1002 int top_rank = 0; 1003 for ( ; stack_top >= 0; --stack_top) { 1004 int u = stack[stack_top], v; 1005 int rank_u = _rank[u]; 1006 1007 LargeCost rc, pi_u = _pi[u]; 1008 int last_out = _first_out[u+1]; 1009 for (int a = _first_out[u]; a != last_out; ++a) { 1010 if (_res_cap[a] > 0) { 1011 v = _target[a]; 1012 rc = _cost[a] + pi_u - _pi[v]; 1013 if (rc < 0) { 1014 LargeCost nrc = static_cast<LargeCost>((-rc - 0.5) / _epsilon); 1015 if (nrc < LargeCost(_max_rank)) { 1016 int new_rank_v = rank_u + static_cast<int>(nrc); 1017 if (new_rank_v > _rank[v]) { 1018 _rank[v] = new_rank_v; 1019 } 1020 } 1021 } 1022 } 1023 } 1024 1025 if (rank_u > 0) { 1026 top_rank = std::max(top_rank, rank_u); 1027 int bfirst = _buckets[rank_u]; 1028 _bucket_next[u] = bfirst; 1029 _bucket_prev[bfirst] = u; 1030 _buckets[rank_u] = u; 1031 } 1032 } 1033 1034 // Check if the current flow is epsilon-optimal 1035 if (top_rank == 0) { 1036 return true; 1037 } 1038 1039 // Process buckets in top-down order 1040 for (int rank = top_rank; rank > 0; --rank) { 1041 while (_buckets[rank] != bucket_end) { 1042 // Remove the first node from the current bucket 1043 int u = _buckets[rank]; 1044 _buckets[rank] = _bucket_next[u]; 1045 1046 // Search the outgoing arcs of u 1047 LargeCost rc, pi_u = _pi[u]; 1048 int last_out = _first_out[u+1]; 1049 int v, old_rank_v, new_rank_v; 1050 for (int a = _first_out[u]; a != last_out; ++a) { 1051 if (_res_cap[a] > 0) { 1052 v = _target[a]; 1053 old_rank_v = _rank[v]; 1054 1055 if (old_rank_v < rank) { 1056 1057 // Compute the new rank of node v 1058 rc = _cost[a] + pi_u - _pi[v]; 1059 if (rc < 0) { 1060 new_rank_v = rank; 1061 } else { 1062 LargeCost nrc = rc / _epsilon; 1063 new_rank_v = 0; 1064 if (nrc < LargeCost(_max_rank)) { 1065 new_rank_v = rank - 1 - static_cast<int>(nrc); 1066 } 1067 } 1068 1069 // Change the rank of node v 1070 if (new_rank_v > old_rank_v) { 1071 _rank[v] = new_rank_v; 1072 1073 // Remove v from its old bucket 1074 if (old_rank_v > 0) { 1075 if (_buckets[old_rank_v] == v) { 1076 _buckets[old_rank_v] = _bucket_next[v]; 1077 } else { 1078 int pv = _bucket_prev[v], nv = _bucket_next[v]; 1079 _bucket_next[pv] = nv; 1080 _bucket_prev[nv] = pv; 1081 } 1082 } 1083 1084 // Insert v into its new bucket 1085 int nv = _buckets[new_rank_v]; 1086 _bucket_next[v] = nv; 1087 _bucket_prev[nv] = v; 1088 _buckets[new_rank_v] = v; 1089 } 1090 } 1091 } 1092 } 1093 1094 // Refine potential of node u 1095 _pi[u] -= rank * _epsilon; 1096 } 1097 } 1098 995 1099 } 996 _sgr.build(_res_node_num, _arc_vec.begin(), _arc_vec.end());997 1100 998 // Run Bellman-Ford algorithm to check if the current flow is optimal 999 BellmanFord<StaticDigraph, LargeCostArcMap> bf(_sgr, _cost_map); 1000 bf.init(0); 1001 bool done = false; 1002 int K = int(EARLY_TERM_FACTOR * std::sqrt(double(_res_node_num))); 1003 for (int i = 0; i < K && !done; ++i) { 1004 done = bf.processNextWeakRound(); 1101 return false; 1102 } 1103 1104 // Find and cancel cycles in the admissible network and 1105 // determine topological order using DFS 1106 bool topologicalSort(IntVector &stack, int &stack_top) { 1107 const int MAX_CYCLE_CANCEL = 1; 1108 1109 BoolVector reached(_res_node_num, false); 1110 BoolVector processed(_res_node_num, false); 1111 IntVector pred(_res_node_num); 1112 for (int i = 0; i != _res_node_num; ++i) { 1113 _next_out[i] = _first_out[i]; 1005 1114 } 1006 return done; 1115 stack_top = -1; 1116 1117 int cycle_cnt = 0; 1118 for (int start = 0; start != _res_node_num; ++start) { 1119 if (reached[start]) continue; 1120 1121 // Start DFS search from this start node 1122 pred[start] = -1; 1123 int tip = start, v; 1124 while (true) { 1125 // Check the outgoing arcs of the current tip node 1126 reached[tip] = true; 1127 LargeCost pi_tip = _pi[tip]; 1128 int a, last_out = _first_out[tip+1]; 1129 for (a = _next_out[tip]; a != last_out; ++a) { 1130 if (_res_cap[a] > 0) { 1131 v = _target[a]; 1132 if (_cost[a] + pi_tip - _pi[v] < 0) { 1133 if (!reached[v]) { 1134 // A new node is reached 1135 reached[v] = true; 1136 pred[v] = tip; 1137 _next_out[tip] = a; 1138 tip = v; 1139 a = _next_out[tip]; 1140 last_out = _first_out[tip+1]; 1141 break; 1142 } 1143 else if (!processed[v]) { 1144 // A cycle is found 1145 ++cycle_cnt; 1146 _next_out[tip] = a; 1147 1148 // Find the minimum residual capacity along the cycle 1149 Value d, delta = _res_cap[a]; 1150 int u, delta_node = tip; 1151 for (u = tip; u != v; ) { 1152 u = pred[u]; 1153 d = _res_cap[_next_out[u]]; 1154 if (d <= delta) { 1155 delta = d; 1156 delta_node = u; 1157 } 1158 } 1159 1160 // Augment along the cycle 1161 _res_cap[a] -= delta; 1162 _res_cap[_reverse[a]] += delta; 1163 for (u = tip; u != v; ) { 1164 u = pred[u]; 1165 int ca = _next_out[u]; 1166 _res_cap[ca] -= delta; 1167 _res_cap[_reverse[ca]] += delta; 1168 } 1169 1170 // Check the maximum number of cycle canceling 1171 if (cycle_cnt >= MAX_CYCLE_CANCEL) { 1172 return false; 1173 } 1174 1175 // Roll back search to delta_node 1176 if (delta_node != tip) { 1177 for (u = tip; u != delta_node; u = pred[u]) { 1178 reached[u] = false; 1179 } 1180 tip = delta_node; 1181 a = _next_out[tip] + 1; 1182 last_out = _first_out[tip+1]; 1183 break; 1184 } 1185 } 1186 } 1187 } 1188 } 1189 1190 // Step back to the previous node 1191 if (a == last_out) { 1192 processed[tip] = true; 1193 stack[++stack_top] = tip; 1194 tip = pred[tip]; 1195 if (tip < 0) { 1196 // Finish DFS from the current start node 1197 break; 1198 } 1199 ++_next_out[tip]; 1200 } 1201 } 1202 1203 } 1204 1205 return (cycle_cnt == 0); 1007 1206 } 1008 1207 1009 1208 // Global potential update heuristic … … 1102 1301 /// Execute the algorithm performing augment and relabel operations 1103 1302 void startAugment(int max_length) { 1104 1303 // Paramters for heuristics 1105 const int EARLY_TERM_EPSILON_LIMIT = 1000;1304 const int PRICE_REFINEMENT_LIMIT = 2; 1106 1305 const double GLOBAL_UPDATE_FACTOR = 1.0; 1107 1306 const int global_update_skip = static_cast<int>(GLOBAL_UPDATE_FACTOR * 1108 1307 (_res_node_num + _sup_node_num * _sup_node_num)); … … 1112 1311 IntVector path; 1113 1312 BoolVector path_arc(_res_arc_num, false); 1114 1313 int relabel_cnt = 0; 1314 int eps_phase_cnt = 0; 1115 1315 for ( ; _epsilon >= 1; _epsilon = _epsilon < _alpha && _epsilon > 1 ? 1116 1316 1 : _epsilon / _alpha ) 1117 1317 { 1118 // Early termination heuristic 1119 if (_epsilon <= EARLY_TERM_EPSILON_LIMIT) { 1120 if (earlyTermination()) break; 1318 ++eps_phase_cnt; 1319 1320 // Price refinement heuristic 1321 if (eps_phase_cnt >= PRICE_REFINEMENT_LIMIT) { 1322 if (priceRefinement()) continue; 1121 1323 } 1122 1324 1123 1325 // Initialize current phase … … 1224 1426 /// Execute the algorithm performing push and relabel operations 1225 1427 void startPush() { 1226 1428 // Paramters for heuristics 1227 const int EARLY_TERM_EPSILON_LIMIT = 1000;1429 const int PRICE_REFINEMENT_LIMIT = 2; 1228 1430 const double GLOBAL_UPDATE_FACTOR = 2.0; 1229 1431 1230 1432 const int global_update_skip = static_cast<int>(GLOBAL_UPDATE_FACTOR * … … 1235 1437 BoolVector hyper(_res_node_num, false); 1236 1438 LargeCostVector hyper_cost(_res_node_num); 1237 1439 int relabel_cnt = 0; 1440 int eps_phase_cnt = 0; 1238 1441 for ( ; _epsilon >= 1; _epsilon = _epsilon < _alpha && _epsilon > 1 ? 1239 1442 1 : _epsilon / _alpha ) 1240 1443 { 1241 // Early termination heuristic 1242 if (_epsilon <= EARLY_TERM_EPSILON_LIMIT) { 1243 if (earlyTermination()) break; 1444 ++eps_phase_cnt; 1445 1446 // Price refinement heuristic 1447 if (eps_phase_cnt >= PRICE_REFINEMENT_LIMIT) { 1448 if (priceRefinement()) continue; 1244 1449 } 1245 1450 1246 1451 // Initialize current phase -
lemon/cost_scaling.h
# HG changeset patch # User Peter Kovacs <kpeter@inf.elte.hu> # Date 1300215151 -3600 # Node ID 482ff194df9394723c9db6b69892cc34efa69f54 # Parent f88191cb740f5469104cdde0e26d11d6a4edd3c8 Faster computation of the dual solution in CostScaling (#417) diff --git a/lemon/cost_scaling.h b/lemon/cost_scaling.h
a b 237 237 std::vector<Value>& _v; 238 238 }; 239 239 240 typedef StaticVectorMap<StaticDigraph::Node, LargeCost> LargeCostNodeMap;241 240 typedef StaticVectorMap<StaticDigraph::Arc, LargeCost> LargeCostArcMap; 242 241 243 242 private: … … 288 287 IntVector _rank; 289 288 int _max_rank; 290 289 291 // Data for a StaticDigraph structure292 typedef std::pair<int, int> IntPair;293 StaticDigraph _sgr;294 std::vector<IntPair> _arc_vec;295 std::vector<LargeCost> _cost_vec;296 LargeCostArcMap _cost_map;297 LargeCostNodeMap _pi_map;298 299 290 public: 300 291 301 292 /// \brief Constant for infinite upper bounds (capacities). … … 342 333 /// \param graph The digraph the algorithm runs on. 343 334 CostScaling(const GR& graph) : 344 335 _graph(graph), _node_id(graph), _arc_idf(graph), _arc_idb(graph), 345 _cost_map(_cost_vec), _pi_map(_pi),346 336 INF(std::numeric_limits<Value>::has_infinity ? 347 337 std::numeric_limits<Value>::infinity() : 348 338 std::numeric_limits<Value>::max()) … … 619 609 _excess.resize(_res_node_num); 620 610 _next_out.resize(_res_node_num); 621 611 622 _arc_vec.reserve(_res_arc_num);623 _cost_vec.reserve(_res_arc_num);624 625 612 // Copy the graph 626 613 int i = 0, j = 0, k = 2 * _arc_num + _node_num; 627 614 for (NodeIt n(_graph); n != INVALID; ++n, ++i) { … … 923 910 break; 924 911 } 925 912 926 // Compute node potentials for the original costs 927 _arc_vec.clear(); 928 _cost_vec.clear(); 929 for (int j = 0; j != _res_arc_num; ++j) { 930 if (_res_cap[j] > 0) { 931 _arc_vec.push_back(IntPair(_source[j], _target[j])); 932 _cost_vec.push_back(_scost[j]); 913 // Compute node potentials (dual solution) 914 for (int i = 0; i != _res_node_num; ++i) { 915 _pi[i] = static_cast<Cost>(_pi[i] / (_res_node_num * _alpha)); 916 } 917 bool optimal = true; 918 for (int i = 0; optimal && i != _res_node_num; ++i) { 919 LargeCost pi_i = _pi[i]; 920 int last_out = _first_out[i+1]; 921 for (int j = _first_out[i]; j != last_out; ++j) { 922 if (_res_cap[j] > 0 && _scost[j] + pi_i - _pi[_target[j]] < 0) { 923 optimal = false; 924 break; 925 } 933 926 } 934 927 } 935 _sgr.build(_res_node_num, _arc_vec.begin(), _arc_vec.end());936 928 937 typename BellmanFord<StaticDigraph, LargeCostArcMap> 938 ::template SetDistMap<LargeCostNodeMap>::Create bf(_sgr, _cost_map); 939 bf.distMap(_pi_map); 940 bf.init(0); 941 bf.start(); 929 if (!optimal) { 930 // Compute node potentials for the original costs with BellmanFord 931 // (if it is necessary) 932 typedef std::pair<int, int> IntPair; 933 StaticDigraph sgr; 934 std::vector<IntPair> arc_vec; 935 std::vector<LargeCost> cost_vec; 936 LargeCostArcMap cost_map(cost_vec); 937 938 arc_vec.clear(); 939 cost_vec.clear(); 940 for (int j = 0; j != _res_arc_num; ++j) { 941 if (_res_cap[j] > 0) { 942 int u = _source[j], v = _target[j]; 943 arc_vec.push_back(IntPair(u, v)); 944 cost_vec.push_back(_scost[j] + _pi[u] - _pi[v]); 945 } 946 } 947 sgr.build(_res_node_num, arc_vec.begin(), arc_vec.end()); 948 949 typename BellmanFord<StaticDigraph, LargeCostArcMap>::Create 950 bf(sgr, cost_map); 951 bf.init(0); 952 bf.start(); 953 954 for (int i = 0; i != _res_node_num; ++i) { 955 _pi[i] += bf.dist(sgr.node(i)); 956 } 957 } 958 959 // Shift potentials to meet the requirements of the GEQ type 960 // optimality conditions 961 LargeCost max_pot = _pi[_root]; 962 for (int i = 0; i != _res_node_num; ++i) { 963 if (_pi[i] > max_pot) max_pot = _pi[i]; 964 } 965 if (max_pot != 0) { 966 for (int i = 0; i != _res_node_num; ++i) { 967 _pi[i] -= max_pot; 968 } 969 } 942 970 943 971 // Handle non-zero lower bounds 944 972 if (_have_lower) { -
lemon/cost_scaling.h
# HG changeset patch # User Peter Kovacs <kpeter@inf.elte.hu> # Date 1300215251 -3600 # Node ID 78d9eddfaf1add430990966beaea64a47eb2d7bf # Parent 482ff194df9394723c9db6b69892cc34efa69f54 Change the default scaling factor in CostScaling (#417) diff --git a/lemon/cost_scaling.h b/lemon/cost_scaling.h
a b 487 487 /// 488 488 /// \param method The internal method that will be used in the 489 489 /// algorithm. For more information, see \ref Method. 490 /// \param factor The cost scaling factor. It must be larger than one.490 /// \param factor The cost scaling factor. It must be at least two. 491 491 /// 492 492 /// \return \c INFEASIBLE if no feasible flow exists, 493 493 /// \n \c OPTIMAL if the problem has optimal solution … … 501 501 /// 502 502 /// \see ProblemType, Method 503 503 /// \see resetParams(), reset() 504 ProblemType run(Method method = PARTIAL_AUGMENT, int factor = 8) { 504 ProblemType run(Method method = PARTIAL_AUGMENT, int factor = 16) { 505 LEMON_ASSERT(factor >= 2, "The scaling factor must be at least 2"); 505 506 _alpha = factor; 506 507 ProblemType pt = init(); 507 508 if (pt != OPTIMAL) return pt; -
lemon/cost_scaling.h
# HG changeset patch # User Peter Kovacs <kpeter@inf.elte.hu> # Date 1300208397 -3600 # Node ID ca9d1dc770268c0b476d33857ece1c13471ea447 # Parent 8e39ccaabf484a72dc36608cb5e954a62a0b984d Minor improvements in CostScaling (#417) diff --git a/lemon/cost_scaling.h b/lemon/cost_scaling.h
a b 575 575 return *this; 576 576 } 577 577 578 /// \brief Reset all the parameters that have been given before. 578 /// \brief Reset the internal data structures and all the parameters 579 /// that have been given before. 579 580 /// 580 /// This function resets all the paramaters that have been given581 /// before using functions \ref lowerMap(), \ref upperMap(),582 /// \ref costMap(), \ref supplyMap(), \ref stSupply().581 /// This function resets the internal data structures and all the 582 /// paramaters that have been given before using functions \ref lowerMap(), 583 /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply(). 583 584 /// 584 /// It is useful for multiple run() calls. If this function is not 585 /// used, all the parameters given before are kept for the next 586 /// \ref run() call. 587 /// However, the underlying digraph must not be modified after this 588 /// class have been constructed, since it copies and extends the graph. 585 /// It is useful for multiple \ref run() calls. By default, all the given 586 /// parameters are kept for the next \ref run() call, unless 587 /// \ref resetParams() or \ref reset() is used. 588 /// If the underlying digraph was also modified after the construction 589 /// of the class or the last \ref reset() call, then the \ref reset() 590 /// function must be used, otherwise \ref resetParams() is sufficient. 591 /// 592 /// See \ref resetParams() for examples. 593 /// 589 594 /// \return <tt>(*this)</tt> 595 /// 596 /// \see resetParams(), run() 590 597 CostScaling& reset() { 591 598 // Resize vectors 592 599 _node_num = countNodes(_graph); … … 890 897 } 891 898 } 892 899 893 return OPTIMAL;894 }895 896 // Execute the algorithm and transform the results897 void start(Method method) {898 // Maximum path length for partial augment899 const int MAX_PATH_LENGTH = 4;900 901 900 // Initialize data structures for buckets 902 901 _max_rank = _alpha * _res_node_num; 903 902 _buckets.resize(_max_rank); … … 905 904 _bucket_prev.resize(_res_node_num + 1); 906 905 _rank.resize(_res_node_num + 1); 907 906 908 // Execute the algorithm 907 return OPTIMAL; 908 } 909 910 // Execute the algorithm and transform the results 911 void start(Method method) { 912 const int MAX_PARTIAL_PATH_LENGTH = 4; 913 909 914 switch (method) { 910 915 case PUSH: 911 916 startPush(); 912 917 break; 913 918 case AUGMENT: 914 startAugment( );919 startAugment(_res_node_num - 1); 915 920 break; 916 921 case PARTIAL_AUGMENT: 917 startAugment(MAX_PA TH_LENGTH);922 startAugment(MAX_PARTIAL_PATH_LENGTH); 918 923 break; 919 924 } 920 925 … … 951 956 int last_out = _first_out[u+1]; 952 957 LargeCost pi_u = _pi[u]; 953 958 for (int a = _first_out[u]; a != last_out; ++a) { 954 int v = _target[a]; 955 if (_res_cap[a] > 0 && _cost[a] + pi_u - _pi[v] < 0) { 956 Value delta = _res_cap[a]; 957 _excess[u] -= delta; 958 _excess[v] += delta; 959 _res_cap[a] = 0; 960 _res_cap[_reverse[a]] += delta; 959 Value delta = _res_cap[a]; 960 if (delta > 0) { 961 int v = _target[a]; 962 if (_cost[a] + pi_u - _pi[v] < 0) { 963 _excess[u] -= delta; 964 _excess[v] += delta; 965 _res_cap[a] = 0; 966 _res_cap[_reverse[a]] += delta; 967 } 961 968 } 962 969 } 963 970 } … … 1001 1008 1002 1009 // Global potential update heuristic 1003 1010 void globalUpdate() { 1004 int bucket_end = _root + 1;1011 const int bucket_end = _root + 1; 1005 1012 1006 1013 // Initialize buckets 1007 1014 for (int r = 0; r != _max_rank; ++r) { 1008 1015 _buckets[r] = bucket_end; 1009 1016 } 1010 1017 Value total_excess = 0; 1018 int b0 = bucket_end; 1011 1019 for (int i = 0; i != _res_node_num; ++i) { 1012 1020 if (_excess[i] < 0) { 1013 1021 _rank[i] = 0; 1014 _bucket_next[i] = _buckets[0];1015 _bucket_prev[ _buckets[0]] = i;1016 _buckets[0]= i;1022 _bucket_next[i] = b0; 1023 _bucket_prev[b0] = i; 1024 b0 = i; 1017 1025 } else { 1018 1026 total_excess += _excess[i]; 1019 1027 _rank[i] = _max_rank; 1020 1028 } 1021 1029 } 1022 1030 if (total_excess == 0) return; 1031 _buckets[0] = b0; 1023 1032 1024 1033 // Search the buckets 1025 1034 int r = 0; … … 1041 1050 // Compute the new rank of v 1042 1051 LargeCost nrc = (_cost[ra] + _pi[v] - pi_u) / _epsilon; 1043 1052 int new_rank_v = old_rank_v; 1044 if (nrc < LargeCost(_max_rank)) 1045 new_rank_v = r + 1 + int(nrc); 1053 if (nrc < LargeCost(_max_rank)) { 1054 new_rank_v = r + 1 + static_cast<int>(nrc); 1055 } 1046 1056 1047 1057 // Change the rank of v 1048 1058 if (new_rank_v < old_rank_v) { … … 1054 1064 if (_buckets[old_rank_v] == v) { 1055 1065 _buckets[old_rank_v] = _bucket_next[v]; 1056 1066 } else { 1057 _bucket_next[_bucket_prev[v]] = _bucket_next[v]; 1058 _bucket_prev[_bucket_next[v]] = _bucket_prev[v]; 1067 int pv = _bucket_prev[v], nv = _bucket_next[v]; 1068 _bucket_next[pv] = nv; 1069 _bucket_prev[nv] = pv; 1059 1070 } 1060 1071 } 1061 1072 1062 // Insert v to its new bucket 1063 _bucket_next[v] = _buckets[new_rank_v]; 1064 _bucket_prev[_buckets[new_rank_v]] = v; 1073 // Insert v into its new bucket 1074 int nv = _buckets[new_rank_v]; 1075 _bucket_next[v] = nv; 1076 _bucket_prev[nv] = v; 1065 1077 _buckets[new_rank_v] = v; 1066 1078 } 1067 1079 }