00001
00003 #include "../stdafx.h"
00004 #include "../core/math_func.hpp"
00005 #include "mcf.h"
00006
00016 bool DistanceAnnotation::IsBetter(const DistanceAnnotation *base, uint cap,
00017 int free_cap, uint dist) const
00018 {
00019
00020
00021
00022 if (base->distance == UINT_MAX) {
00023 return false;
00024 } else if (this->distance == UINT_MAX) {
00025 return true;
00026 }
00027
00028 if (free_cap > 0 && base->free_capacity > 0) {
00029
00030
00031
00032
00033 return this->free_capacity > 0 ? (base->distance + dist < this->distance) : true;
00034 } else {
00035
00036
00037
00038
00039
00040 return this->free_capacity > 0 ? false : (base->distance + dist < this->distance);
00041 }
00042 }
00043
00053 bool CapacityAnnotation::IsBetter(const CapacityAnnotation *base, uint cap,
00054 int free_cap, uint dist) const
00055 {
00056 int min_cap = (min(base->free_capacity, free_cap) << 4) / (min(base->capacity, cap) + 1);
00057 int this_cap = this->GetCapacityRatio();
00058 if (min_cap == this_cap) {
00059
00060
00061
00062 return base->distance == UINT_MAX ? false : (base->distance + dist < this->distance);
00063 } else {
00064 return min_cap > this_cap;
00065 }
00066 }
00067
00081 template<class Tannotation>
00082 void MultiCommodityFlow::Dijkstra(NodeID source_node, PathVector &paths,
00083 bool create_new_paths)
00084 {
00085 typedef std::set<Tannotation *, typename Tannotation::Comparator> AnnoSet;
00086 uint size = this->graph->GetSize();
00087 StationID source_station = this->graph->GetNode(source_node).station;
00088 AnnoSet annos;
00089 paths.resize(size, NULL);
00090 for (NodeID node = 0; node < size; ++node) {
00091 Tannotation *anno = new Tannotation(node, node == source_node);
00092 annos.insert(anno);
00093 paths[node] = anno;
00094 }
00095 while (!annos.empty()) {
00096 typename AnnoSet::iterator i = annos.begin();
00097 Tannotation *source = *i;
00098 annos.erase(i);
00099 NodeID from = source->GetNode();
00100 NodeID to = this->graph->GetFirstEdge(from);
00101 while (to != INVALID_NODE) {
00102 Edge &edge = this->graph->GetEdge(from, to);
00103 assert(edge.distance < UINT_MAX);
00104 if (create_new_paths || this->graph->GetNode(from)
00105 .flows[source_station][this->graph->GetNode(to).station] > 0) {
00106 uint capacity = edge.capacity;
00107 if (create_new_paths) {
00108 capacity *= this->graph->GetSettings().short_path_saturation;
00109 capacity /= 100;
00110 if (capacity == 0) capacity = 1;
00111 }
00112
00113 uint distance = edge.distance + 1;
00114 Tannotation *dest = static_cast<Tannotation *>(paths[to]);
00115 if (dest->IsBetter(source, capacity, capacity - edge.flow, distance)) {
00116 annos.erase(dest);
00117 dest->Fork(source, capacity, capacity - edge.flow, distance);
00118 annos.insert(dest);
00119 }
00120 }
00121 to = edge.next_edge;
00122 }
00123 }
00124 }
00125
00131 void MultiCommodityFlow::CleanupPaths(NodeID source_id, PathVector &paths)
00132 {
00133 Path *source = paths[source_id];
00134 paths[source_id] = NULL;
00135 for (PathVector::iterator i = paths.begin(); i != paths.end(); ++i) {
00136 Path *path = *i;
00137 if (path == NULL) continue;
00138 if (path->GetParent() == source) path->Detach();
00139 while (path != source && path != NULL && path->GetFlow() == 0) {
00140 Path *parent = path->GetParent();
00141 path->Detach();
00142 if (path->GetNumChildren() == 0) {
00143 paths[path->GetNode()] = NULL;
00144 delete path;
00145 }
00146 path = parent;
00147 }
00148 }
00149 delete source;
00150 paths.clear();
00151 }
00152
00162 uint MultiCommodityFlow::PushFlow(Edge &edge, Path *path, uint accuracy,
00163 bool positive_cap)
00164 {
00165 assert(edge.unsatisfied_demand > 0);
00166 uint flow = Clamp(edge.demand / accuracy, 1, edge.unsatisfied_demand);
00167 flow = path->AddFlow(flow, this->graph, positive_cap);
00168 edge.unsatisfied_demand -= flow;
00169 return flow;
00170 }
00171
00178 uint MCF1stPass::FindCycleFlow(const PathVector &path, const Path *cycle_begin)
00179 {
00180 uint flow = UINT_MAX;
00181 const Path *cycle_end = cycle_begin;
00182 do {
00183 flow = min(flow, cycle_begin->GetFlow());
00184 cycle_begin = path[cycle_begin->GetNode()];
00185 } while (cycle_begin != cycle_end);
00186 return flow;
00187 }
00188
00195 void MCF1stPass::EliminateCycle(PathVector &path, Path *cycle_begin, uint flow)
00196 {
00197 Path *cycle_end = cycle_begin;
00198 do {
00199 NodeID prev = cycle_begin->GetNode();
00200 cycle_begin->ReduceFlow(flow);
00201 cycle_begin = path[cycle_begin->GetNode()];
00202 Edge &edge = this->graph->GetEdge(prev, cycle_begin->GetNode());
00203 edge.flow -= flow;
00204 } while (cycle_begin != cycle_end);
00205 }
00206
00216 bool MCF1stPass::EliminateCycles(PathVector &path, NodeID origin_id, NodeID next_id)
00217 {
00218 static Path *invalid_path = new Path(INVALID_NODE, true);
00219 Path *at_next_pos = path[next_id];
00220 if (at_next_pos == invalid_path) {
00221
00222 return false;
00223 } else if (at_next_pos == NULL) {
00224
00225
00226
00227 PathSet &paths = this->graph->GetNode(next_id).paths;
00228 PathViaMap next_hops;
00229 for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i) {
00230 Path *new_child = *i;
00231 if (new_child->GetOrigin() == origin_id) {
00232 PathViaMap::iterator via_it = next_hops.find(new_child->GetNode());
00233 if (via_it == next_hops.end()) {
00234 next_hops[new_child->GetNode()] = new_child;
00235 } else {
00236 Path *child = via_it->second;
00237 uint new_flow = new_child->GetFlow();
00238 child->AddFlow(new_flow);
00239 new_child->ReduceFlow(new_flow);
00240 }
00241 }
00242 }
00243 bool found = false;
00244
00245 for (PathViaMap::iterator via_it = next_hops.begin();
00246 via_it != next_hops.end(); ++via_it) {
00247 Path *child = via_it->second;
00248 if (child->GetFlow() > 0) {
00249
00250
00251
00252 path[next_id] = child;
00253 found = this->EliminateCycles(path, origin_id, child->GetNode()) || found;
00254 }
00255 }
00256
00257
00258
00259
00260
00261 path[next_id] = found ? NULL : invalid_path;
00262 return found;
00263 } else {
00264
00265
00266
00267 uint flow = this->FindCycleFlow(path, at_next_pos);
00268 if (flow > 0) {
00269 this->EliminateCycle(path, at_next_pos, flow);
00270 return true;
00271 } else {
00272 return false;
00273 }
00274 }
00275 }
00276
00282 bool MCF1stPass::EliminateCycles()
00283 {
00284 bool cycles_found = false;
00285 uint size = this->graph->GetSize();
00286 PathVector path(size, NULL);
00287 for (NodeID node = 0; node < size; ++node) {
00288
00289
00290
00291 std::fill(path.begin(), path.end(), (Path *)NULL);
00292 cycles_found |= this->EliminateCycles(path, node, node);
00293 }
00294 return cycles_found;
00295 }
00296
00301 MCF1stPass::MCF1stPass(LinkGraphComponent *graph) : MultiCommodityFlow(graph)
00302 {
00303 PathVector paths;
00304 uint size = this->graph->GetSize();
00305 uint accuracy = this->graph->GetSettings().accuracy;
00306 bool more_loops = true;
00307
00308 while (more_loops) {
00309 more_loops = false;
00310
00311 for (NodeID source = 0; source < size; ++source) {
00312
00313 this->Dijkstra<DistanceAnnotation>(source, paths, true);
00314
00315 for (NodeID dest = 0; dest < size; ++dest) {
00316 Edge &edge = this->graph->GetEdge(source, dest);
00317 if (edge.unsatisfied_demand > 0) {
00318 Path *path = paths[dest];
00319 assert(path != NULL);
00320
00321
00322
00323
00324 if (path->GetFreeCapacity() > 0 && this->PushFlow(edge, path,
00325 accuracy, true) > 0) {
00326
00327
00328
00329 more_loops = (edge.unsatisfied_demand > 0);
00330 } else if (edge.unsatisfied_demand == edge.demand &&
00331 path->GetFreeCapacity() > INT_MIN) {
00332 this->PushFlow(edge, path, accuracy, false);
00333 }
00334 }
00335 }
00336 this->CleanupPaths(source, paths);
00337 }
00338 if (!more_loops) more_loops = this->EliminateCycles();
00339 }
00340 }
00341
00347 MCF2ndPass::MCF2ndPass(LinkGraphComponent *graph) : MultiCommodityFlow(graph)
00348 {
00349 PathVector paths;
00350 uint size = this->graph->GetSize();
00351 uint accuracy = this->graph->GetSettings().accuracy;
00352 bool demand_left = true;
00353 while (demand_left) {
00354 demand_left = false;
00355 for (NodeID source = 0; source < size; ++source) {
00356 this->Dijkstra<CapacityAnnotation>(source, paths, false);
00357 for (NodeID dest = 0; dest < size; ++dest) {
00358 Edge &edge = this->graph->GetEdge(source, dest);
00359 Path *path = paths[dest];
00360 if (edge.unsatisfied_demand > 0 && path->GetFreeCapacity() > INT_MIN) {
00361 this->PushFlow(edge, path, accuracy, false);
00362 if (edge.unsatisfied_demand > 0) demand_left = true;
00363 }
00364 }
00365 this->CleanupPaths(source, paths);
00366 }
00367 }
00368 }
00369
00381 template <typename T>
00382 bool greater(T x_anno, T y_anno, NodeID x, NodeID y)
00383 {
00384 if (x_anno > y_anno) {
00385 return true;
00386 } else if (x_anno < y_anno) {
00387 return false;
00388 } else {
00389 return x > y;
00390 }
00391 }
00392
00399 bool CapacityAnnotation::Comparator::operator()(const CapacityAnnotation *x,
00400 const CapacityAnnotation *y) const
00401 {
00402 return x != y && greater<int>(x->GetAnnotation(), y->GetAnnotation(),
00403 x->GetNode(), y->GetNode());
00404 }
00405
00412 bool DistanceAnnotation::Comparator::operator()(const DistanceAnnotation *x,
00413 const DistanceAnnotation *y) const
00414 {
00415 return x != y && !greater<uint>(x->GetAnnotation(), y->GetAnnotation(),
00416 x->GetNode(), y->GetNode());
00417 }