00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "mcf.h"
00013 #include "../core/math_func.hpp"
00014
00024 bool DistanceAnnotation::IsBetter(const DistanceAnnotation *base, uint cap,
00025 int free_cap, uint dist) const
00026 {
00027
00028
00029
00030 if (base->distance == UINT_MAX) {
00031 return false;
00032 } else if (this->distance == UINT_MAX) {
00033 return true;
00034 }
00035
00036 if (free_cap > 0 && base->free_capacity > 0) {
00037
00038
00039
00040
00041 return this->free_capacity > 0 ? (base->distance + dist < this->distance) : true;
00042 } else {
00043
00044
00045
00046
00047
00048 return this->free_capacity > 0 ? false : (base->distance + dist < this->distance);
00049 }
00050 }
00051
00061 bool CapacityAnnotation::IsBetter(const CapacityAnnotation *base, uint cap,
00062 int free_cap, uint dist) const
00063 {
00064 int min_cap = (min(base->free_capacity, free_cap) << 4) / (min(base->capacity, cap) + 1);
00065 int this_cap = this->GetCapacityRatio();
00066 if (min_cap == this_cap) {
00067
00068
00069
00070 return base->distance == UINT_MAX ? false : (base->distance + dist < this->distance);
00071 } else {
00072 return min_cap > this_cap;
00073 }
00074 }
00075
00089 template<class Tannotation>
00090 void MultiCommodityFlow::Dijkstra(NodeID source_node, PathVector &paths,
00091 bool create_new_paths)
00092 {
00093 typedef std::set<Tannotation *, typename Tannotation::comp> AnnoSet;
00094 uint size = this->graph->GetSize();
00095 StationID source_station = this->graph->GetNode(source_node).station;
00096 AnnoSet annos;
00097 paths.resize(size, NULL);
00098 for (NodeID node = 0; node < size; ++node) {
00099 Tannotation *anno = new Tannotation(node, node == source_node);
00100 annos.insert(anno);
00101 paths[node] = anno;
00102 }
00103 while(!annos.empty()) {
00104 typename AnnoSet::iterator i = annos.begin();
00105 Tannotation *source = *i;
00106 annos.erase(i);
00107 NodeID from = source->GetNode();
00108 NodeID to = this->graph->GetFirstEdge(from);
00109 while (to != INVALID_NODE) {
00110 Edge &edge = this->graph->GetEdge(from, to);
00111 assert(edge.distance < UINT_MAX);
00112 if (create_new_paths ||
00113 this->graph->GetNode(from).flows[source_station]
00114 [this->graph->GetNode(to).station] > 0) {
00115 uint capacity = edge.capacity;
00116 if (create_new_paths) {
00117 capacity *= this->graph->GetSettings().short_path_saturation;
00118 capacity /= 100;
00119 if (capacity == 0) capacity = 1;
00120 }
00121
00122 uint distance = edge.distance + 1;
00123 Tannotation *dest = static_cast<Tannotation *>(paths[to]);
00124 if (dest->IsBetter(source, capacity, capacity - edge.flow, distance)) {
00125 annos.erase(dest);
00126 dest->Fork(source, capacity, capacity - edge.flow, distance);
00127 annos.insert(dest);
00128 }
00129 }
00130 to = edge.next_edge;
00131 }
00132 }
00133 }
00134
00140 void MultiCommodityFlow::CleanupPaths(NodeID source_id, PathVector &paths) {
00141 Path *source = paths[source_id];
00142 paths[source_id] = NULL;
00143 for(PathVector::iterator i = paths.begin(); i != paths.end(); ++i) {
00144 Path *path = *i;
00145 if (path != NULL) {
00146 if (path->GetParent() == source) path->UnFork();
00147 while (path != source && path != NULL && path->GetFlow() == 0) {
00148 Path *parent = path->GetParent();
00149 path->UnFork();
00150 if (path->GetNumChildren() == 0) {
00151 paths[path->GetNode()] = NULL;
00152 delete path;
00153 }
00154 path = parent;
00155 }
00156 }
00157 }
00158 delete source;
00159 paths.clear();
00160 }
00161
00171 uint MultiCommodityFlow::PushFlow(Edge &edge, Path *path, uint accuracy,
00172 bool positive_cap)
00173 {
00174 assert(edge.unsatisfied_demand > 0);
00175 uint flow = Clamp(edge.demand / accuracy, 1, edge.unsatisfied_demand);
00176 flow = path->AddFlow(flow, this->graph, positive_cap);
00177 edge.unsatisfied_demand -= flow;
00178 return flow;
00179 }
00180
00187 uint MCF1stPass::FindCycleFlow(const PathVector &path, const Path *cycle_begin)
00188 {
00189 uint flow = UINT_MAX;
00190 const Path *cycle_end = cycle_begin;
00191 do {
00192 flow = min(flow, cycle_begin->GetFlow());
00193 cycle_begin = path[cycle_begin->GetNode()];
00194 } while(cycle_begin != cycle_end);
00195 return flow;
00196 }
00197
00204 void MCF1stPass::EliminateCycle(PathVector &path, Path *cycle_begin, uint flow)
00205 {
00206 Path *cycle_end = cycle_begin;
00207 do {
00208 NodeID prev = cycle_begin->GetNode();
00209 cycle_begin->ReduceFlow(flow);
00210 cycle_begin = path[cycle_begin->GetNode()];
00211 Edge &edge = this->graph->GetEdge(prev, cycle_begin->GetNode());
00212 edge.flow -= flow;
00213 } while(cycle_begin != cycle_end);
00214 }
00215
00225 bool MCF1stPass::EliminateCycles(PathVector &path, NodeID origin_id, NodeID next_id)
00226 {
00227 static Path *invalid_path = new Path(INVALID_NODE, true);
00228 Path *at_next_pos = path[next_id];
00229 if (at_next_pos == invalid_path) {
00230
00231 return false;
00232 } else if (at_next_pos == NULL) {
00233
00234
00235
00236 PathSet &paths = this->graph->GetNode(next_id).paths;
00237 PathViaMap next_hops;
00238 for(PathSet::iterator i = paths.begin(); i != paths.end(); ++i) {
00239 Path *new_child = *i;
00240 if (new_child->GetOrigin() == origin_id) {
00241 PathViaMap::iterator via_it = next_hops.find(new_child->GetNode());
00242 if (via_it == next_hops.end()) {
00243 next_hops[new_child->GetNode()] = new_child;
00244 } else {
00245 Path *child = via_it->second;
00246 uint new_flow = new_child->GetFlow();
00247 child->AddFlow(new_flow);
00248 new_child->ReduceFlow(new_flow);
00249 }
00250 }
00251 }
00252 bool found = false;
00253
00254 for (PathViaMap::iterator via_it = next_hops.begin();
00255 via_it != next_hops.end(); ++via_it)
00256 {
00257 Path *child = via_it->second;
00258 if (child->GetFlow() > 0) {
00259
00260
00261
00262 path[next_id] = child;
00263 found = this->EliminateCycles(path, origin_id, child->GetNode()) || found;
00264 }
00265 }
00266
00267
00268
00269
00270
00271 path[next_id] = found ? NULL : invalid_path;
00272 return found;
00273 } else {
00274
00275
00276
00277 uint flow = this->FindCycleFlow(path, at_next_pos);
00278 if (flow > 0) {
00279 this->EliminateCycle(path, at_next_pos, flow);
00280 return true;
00281 } else {
00282 return false;
00283 }
00284 }
00285 }
00286
00292 bool MCF1stPass::EliminateCycles()
00293 {
00294 bool cycles_found = false;
00295 uint size = this->graph->GetSize();
00296 PathVector path(size, NULL);
00297 for (NodeID node = 0; node < size; ++node) {
00298
00299 std::fill(path.begin(), path.end(), (Path *)NULL);
00300 cycles_found = this->EliminateCycles(path, node, node) || cycles_found;
00301 }
00302 return cycles_found;
00303 }
00304
00309 MCF1stPass::MCF1stPass(LinkGraphComponent *graph) : MultiCommodityFlow(graph)
00310 {
00311 PathVector paths;
00312 uint size = this->graph->GetSize();
00313 uint accuracy = this->graph->GetSettings().accuracy;
00314 bool no_overload = this->graph->GetSettings().no_overload_links;
00315 bool more_loops = true;
00316
00317 while (more_loops) {
00318 more_loops = false;
00319
00320 for (NodeID source = 0; source < size; ++source) {
00321
00322 this->Dijkstra<DistanceAnnotation>(source, paths, true);
00323
00324 for (NodeID dest = 0; dest < size; ++dest) {
00325 Edge &edge = this->graph->GetEdge(source, dest);
00326 if (edge.unsatisfied_demand > 0) {
00327 Path *path = paths[dest];
00328 assert(path != NULL);
00329
00330
00331
00332
00333 if (path->GetFreeCapacity() > 0 && this->PushFlow(edge, path,
00334 accuracy, no_overload) > 0) {
00335
00336
00337
00338 more_loops = (edge.unsatisfied_demand > 0);
00339 } else if (edge.unsatisfied_demand == edge.demand && path->GetFreeCapacity() > INT_MIN) {
00340 this->PushFlow(edge, path, accuracy, false);
00341 }
00342 }
00343 }
00344 CleanupPaths(source, paths);
00345 }
00346 if (!more_loops) more_loops = EliminateCycles();
00347 }
00348 }
00349
00354 MCF2ndPass::MCF2ndPass(LinkGraphComponent *graph) : MultiCommodityFlow(graph)
00355 {
00356 PathVector paths;
00357 uint size = this->graph->GetSize();
00358 uint accuracy = this->graph->GetSettings().accuracy;
00359 bool no_overload = this->graph->GetSettings().no_overload_links;
00360 bool demand_left = true;
00361 uint flow_pushed = 1;
00362 while (demand_left && flow_pushed > 0) {
00363 flow_pushed = 0;
00364 demand_left = false;
00365 for (NodeID source = 0; source < size; ++source) {
00366
00367 this->Dijkstra<CapacityAnnotation>(source, paths, false);
00368 for (NodeID dest = 0; dest < size; ++dest) {
00369 Edge &edge = this->graph->GetEdge(source, dest);
00370 Path *path = paths[dest];
00371 if (edge.unsatisfied_demand > 0 && path->GetFreeCapacity() > INT_MIN) {
00372 flow_pushed += this->PushFlow(edge, path, accuracy, no_overload);
00373 if (edge.unsatisfied_demand > 0) demand_left = true;
00374 }
00375 }
00376 CleanupPaths(source, paths);
00377 }
00378 }
00379 }
00380
00392 template <typename T>
00393 bool greater(T x_anno, T y_anno, NodeID x, NodeID y) {
00394 if (x_anno > y_anno) {
00395 return true;
00396 } else if (x_anno < y_anno) {
00397 return false;
00398 } else {
00399 return x > y;
00400 }
00401 }
00402
00409 bool CapacityAnnotation::comp::operator()(const CapacityAnnotation *x,
00410 const CapacityAnnotation *y) const
00411 {
00412 return x != y && greater<int>(x->GetAnnotation(), y->GetAnnotation(),
00413 x->GetNode(), y->GetNode());
00414 }
00415
00422 bool DistanceAnnotation::comp::operator()(const DistanceAnnotation *x,
00423 const DistanceAnnotation *y) const
00424 {
00425 return x != y && !greater<uint>(x->GetAnnotation(), y->GetAnnotation(),
00426 x->GetNode(), y->GetNode());
00427 }