00001
00003 #include "../stdafx.h"
00004 #include "../core/math_func.hpp"
00005 #include "mcf.h"
00006
00007 typedef std::map<NodeID, Path *> PathViaMap;
00008
00014 class DistanceAnnotation : public Path {
00015 public:
00016
00022 DistanceAnnotation(NodeID n, bool source = false) : Path(n, source) {}
00023
00024 bool IsBetter(const DistanceAnnotation *base, uint cap, int free_cap, uint dist) const;
00025
00030 inline uint GetAnnotation() const { return this->distance; }
00031
00035 struct Comparator {
00036 bool operator()(const DistanceAnnotation *x, const DistanceAnnotation *y) const;
00037 };
00038 };
00039
00046 class CapacityAnnotation : public Path {
00047 public:
00048
00054 CapacityAnnotation(NodeID n, bool source = false) : Path(n, source) {}
00055
00056 bool IsBetter(const CapacityAnnotation *base, uint cap, int free_cap, uint dist) const;
00057
00062 inline int GetAnnotation() const { return this->GetCapacityRatio(); }
00063
00067 struct Comparator {
00068 bool operator()(const CapacityAnnotation *x, const CapacityAnnotation *y) const;
00069 };
00070 };
00071
00076 class GraphEdgeIterator {
00077 private:
00078 LinkGraphJob &job;
00079 EdgeIterator i;
00080 EdgeIterator end;
00081
00082 public:
00083
00088 GraphEdgeIterator(LinkGraphJob &job) : job(job),
00089 i(NULL, NULL, INVALID_NODE), end(NULL, NULL, INVALID_NODE)
00090 {}
00091
00097 void SetNode(NodeID source, NodeID node)
00098 {
00099 this->i = this->job[node].Begin();
00100 this->end = this->job[node].End();
00101 }
00102
00107 NodeID Next()
00108 {
00109 return this->i != this->end ? (this->i++)->first : INVALID_NODE;
00110 }
00111 };
00112
00116 class FlowEdgeIterator {
00117 private:
00118 LinkGraphJob &job;
00119
00121 std::map<StationID, NodeID> station_to_node;
00122
00124 FlowStat::SharesMap::const_iterator it;
00125
00127 FlowStat::SharesMap::const_iterator end;
00128 public:
00129
00134 FlowEdgeIterator(LinkGraphJob &job) : job(job)
00135 {
00136 for (NodeID i = 0; i < job.Size(); ++i) {
00137 this->station_to_node[job[i].Station()] = i;
00138 }
00139 }
00140
00146 void SetNode(NodeID source, NodeID node)
00147 {
00148 static const FlowStat::SharesMap empty;
00149 const FlowStatMap &flows = this->job[node].Flows();
00150 FlowStatMap::const_iterator it = flows.find(this->job[source].Station());
00151 if (it != flows.end()) {
00152 this->it = it->second.GetShares()->begin();
00153 this->end = it->second.GetShares()->end();
00154 } else {
00155 this->it = empty.begin();
00156 this->end = empty.end();
00157 }
00158 }
00159
00164 NodeID Next()
00165 {
00166 if (this->it == this->end) return INVALID_NODE;
00167 return this->station_to_node[(this->it++)->second];
00168 }
00169 };
00170
00180 bool DistanceAnnotation::IsBetter(const DistanceAnnotation *base, uint cap,
00181 int free_cap, uint dist) const
00182 {
00183
00184
00185 if (base->distance == UINT_MAX) {
00186 return false;
00187 } else if (this->distance == UINT_MAX) {
00188 return true;
00189 }
00190
00191 if (free_cap > 0 && base->free_capacity > 0) {
00192
00193
00194
00195 return this->free_capacity > 0 ? (base->distance + dist < this->distance) : true;
00196 } else {
00197
00198
00199
00200
00201 return this->free_capacity > 0 ? false : (base->distance + dist < this->distance);
00202 }
00203 }
00204
00214 bool CapacityAnnotation::IsBetter(const CapacityAnnotation *base, uint cap,
00215 int free_cap, uint dist) const
00216 {
00217 int min_cap = Path::GetCapacityRatio(min(base->free_capacity, free_cap), min(base->capacity, cap));
00218 int this_cap = this->GetCapacityRatio();
00219 if (min_cap == this_cap) {
00220
00221
00222 return base->distance == UINT_MAX ? false : (base->distance + dist < this->distance);
00223 } else {
00224 return min_cap > this_cap;
00225 }
00226 }
00227
00237 template<class Tannotation, class Tedge_iterator>
00238 void MultiCommodityFlow::Dijkstra(NodeID source_node, PathVector &paths)
00239 {
00240 typedef std::set<Tannotation *, typename Tannotation::Comparator> AnnoSet;
00241 Tedge_iterator iter(this->job);
00242 uint size = this->job.Size();
00243 AnnoSet annos;
00244 paths.resize(size, NULL);
00245 for (NodeID node = 0; node < size; ++node) {
00246 Tannotation *anno = new Tannotation(node, node == source_node);
00247 annos.insert(anno);
00248 paths[node] = anno;
00249 }
00250 while (!annos.empty()) {
00251 typename AnnoSet::iterator i = annos.begin();
00252 Tannotation *source = *i;
00253 annos.erase(i);
00254 NodeID from = source->GetNode();
00255 iter.SetNode(source_node, from);
00256 for (NodeID to = iter.Next(); to != INVALID_NODE; to = iter.Next()) {
00257 if (to == from) continue;
00258 Edge edge = this->job[from][to];
00259 assert(edge.Distance() < UINT_MAX);
00260 uint capacity = edge.Capacity();
00261 if (this->max_saturation != UINT_MAX) {
00262 capacity *= this->max_saturation;
00263 capacity /= 100;
00264 if (capacity == 0) capacity = 1;
00265 }
00266
00267 uint distance = edge.Distance() + 1;
00268 Tannotation *dest = static_cast<Tannotation *>(paths[to]);
00269 if (dest->IsBetter(source, capacity, capacity - edge.Flow(), distance)) {
00270 annos.erase(dest);
00271 dest->Fork(source, capacity, capacity - edge.Flow(), distance);
00272 annos.insert(dest);
00273 }
00274 }
00275 }
00276 }
00277
00283 void MultiCommodityFlow::CleanupPaths(NodeID source_id, PathVector &paths)
00284 {
00285 Path *source = paths[source_id];
00286 paths[source_id] = NULL;
00287 for (PathVector::iterator i = paths.begin(); i != paths.end(); ++i) {
00288 Path *path = *i;
00289 if (path == NULL) continue;
00290 if (path->GetParent() == source) path->Detach();
00291 while (path != source && path != NULL && path->GetFlow() == 0) {
00292 Path *parent = path->GetParent();
00293 path->Detach();
00294 if (path->GetNumChildren() == 0) {
00295 paths[path->GetNode()] = NULL;
00296 delete path;
00297 }
00298 path = parent;
00299 }
00300 }
00301 delete source;
00302 paths.clear();
00303 }
00304
00314 uint MultiCommodityFlow::PushFlow(Edge &edge, Path *path, uint accuracy,
00315 uint max_saturation)
00316 {
00317 assert(edge.UnsatisfiedDemand() > 0);
00318 uint flow = Clamp(edge.Demand() / accuracy, 1, edge.UnsatisfiedDemand());
00319 flow = path->AddFlow(flow, this->job, max_saturation);
00320 edge.SatisfyDemand(flow);
00321 return flow;
00322 }
00323
00330 uint MCF1stPass::FindCycleFlow(const PathVector &path, const Path *cycle_begin)
00331 {
00332 uint flow = UINT_MAX;
00333 const Path *cycle_end = cycle_begin;
00334 do {
00335 flow = min(flow, cycle_begin->GetFlow());
00336 cycle_begin = path[cycle_begin->GetNode()];
00337 } while (cycle_begin != cycle_end);
00338 return flow;
00339 }
00340
00347 void MCF1stPass::EliminateCycle(PathVector &path, Path *cycle_begin, uint flow)
00348 {
00349 Path *cycle_end = cycle_begin;
00350 do {
00351 NodeID prev = cycle_begin->GetNode();
00352 cycle_begin->ReduceFlow(flow);
00353 cycle_begin = path[cycle_begin->GetNode()];
00354 Edge edge = this->job[prev][cycle_begin->GetNode()];
00355 edge.RemoveFlow(flow);
00356 } while (cycle_begin != cycle_end);
00357 }
00358
00368 bool MCF1stPass::EliminateCycles(PathVector &path, NodeID origin_id, NodeID next_id)
00369 {
00370 static Path *invalid_path = new Path(INVALID_NODE, true);
00371 Path *at_next_pos = path[next_id];
00372
00373
00374 if (at_next_pos == invalid_path) return false;
00375
00376 if (at_next_pos == NULL) {
00377
00378
00379 PathSet &paths = this->job[next_id].Paths();
00380 PathViaMap next_hops;
00381 for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i) {
00382 Path *new_child = *i;
00383 if (new_child->GetOrigin() == origin_id) {
00384 PathViaMap::iterator via_it = next_hops.find(new_child->GetNode());
00385 if (via_it == next_hops.end()) {
00386 next_hops[new_child->GetNode()] = new_child;
00387 } else {
00388 Path *child = via_it->second;
00389 uint new_flow = new_child->GetFlow();
00390 child->AddFlow(new_flow);
00391 new_child->ReduceFlow(new_flow);
00392 }
00393 }
00394 }
00395 bool found = false;
00396
00397 for (PathViaMap::iterator via_it = next_hops.begin();
00398 via_it != next_hops.end(); ++via_it) {
00399 Path *child = via_it->second;
00400 if (child->GetFlow() > 0) {
00401
00402
00403 path[next_id] = child;
00404 found = this->EliminateCycles(path, origin_id, child->GetNode()) || found;
00405 }
00406 }
00407
00408
00409
00410
00411
00412 path[next_id] = found ? NULL : invalid_path;
00413 return found;
00414 }
00415
00416
00417
00418 uint flow = this->FindCycleFlow(path, at_next_pos);
00419 if (flow > 0) {
00420 this->EliminateCycle(path, at_next_pos, flow);
00421 return true;
00422 }
00423
00424 return false;
00425 }
00426
00432 bool MCF1stPass::EliminateCycles()
00433 {
00434 bool cycles_found = false;
00435 uint size = this->job.Size();
00436 PathVector path(size, NULL);
00437 for (NodeID node = 0; node < size; ++node) {
00438
00439
00440 std::fill(path.begin(), path.end(), (Path *)NULL);
00441 cycles_found |= this->EliminateCycles(path, node, node);
00442 }
00443 return cycles_found;
00444 }
00445
00450 MCF1stPass::MCF1stPass(LinkGraphJob &job) : MultiCommodityFlow(job)
00451 {
00452 PathVector paths;
00453 uint size = job.Size();
00454 uint accuracy = job.Settings().accuracy;
00455 bool more_loops;
00456
00457 do {
00458 more_loops = false;
00459 for (NodeID source = 0; source < size; ++source) {
00460
00461 this->Dijkstra<DistanceAnnotation, GraphEdgeIterator>(source, paths);
00462
00463 for (NodeID dest = 0; dest < size; ++dest) {
00464 Edge edge = job[source][dest];
00465 if (edge.UnsatisfiedDemand() > 0) {
00466 Path *path = paths[dest];
00467 assert(path != NULL);
00468
00469
00470
00471 if (path->GetFreeCapacity() > 0 && this->PushFlow(edge, path,
00472 accuracy, this->max_saturation) > 0) {
00473
00474
00475 more_loops = more_loops || (edge.UnsatisfiedDemand() > 0);
00476 } else if (edge.UnsatisfiedDemand() == edge.Demand() &&
00477 path->GetFreeCapacity() > INT_MIN) {
00478 this->PushFlow(edge, path, accuracy, UINT_MAX);
00479 }
00480 }
00481 }
00482 this->CleanupPaths(source, paths);
00483 }
00484 } while (more_loops || this->EliminateCycles());
00485 }
00486
00492 MCF2ndPass::MCF2ndPass(LinkGraphJob &job) : MultiCommodityFlow(job)
00493 {
00494 this->max_saturation = UINT_MAX;
00495 PathVector paths;
00496 uint size = job.Size();
00497 uint accuracy = job.Settings().accuracy;
00498 bool demand_left = true;
00499 while (demand_left) {
00500 demand_left = false;
00501 for (NodeID source = 0; source < size; ++source) {
00502 this->Dijkstra<CapacityAnnotation, FlowEdgeIterator>(source, paths);
00503 for (NodeID dest = 0; dest < size; ++dest) {
00504 Edge edge = this->job[source][dest];
00505 Path *path = paths[dest];
00506 if (edge.UnsatisfiedDemand() > 0 && path->GetFreeCapacity() > INT_MIN) {
00507 this->PushFlow(edge, path, accuracy, UINT_MAX);
00508 if (edge.UnsatisfiedDemand() > 0) demand_left = true;
00509 }
00510 }
00511 this->CleanupPaths(source, paths);
00512 }
00513 }
00514 }
00515
00527 template <typename T>
00528 bool Greater(T x_anno, T y_anno, NodeID x, NodeID y)
00529 {
00530 if (x_anno > y_anno) return true;
00531 if (x_anno < y_anno) return false;
00532 return x > y;
00533 }
00534
00541 bool CapacityAnnotation::Comparator::operator()(const CapacityAnnotation *x,
00542 const CapacityAnnotation *y) const
00543 {
00544 return x != y && Greater<int>(x->GetAnnotation(), y->GetAnnotation(),
00545 x->GetNode(), y->GetNode());
00546 }
00547
00554 bool DistanceAnnotation::Comparator::operator()(const DistanceAnnotation *x,
00555 const DistanceAnnotation *y) const
00556 {
00557 return x != y && !Greater<uint>(x->GetAnnotation(), y->GetAnnotation(),
00558 x->GetNode(), y->GetNode());
00559 }