00001
00003 #include "../stdafx.h"
00004 #include "../core/math_func.hpp"
00005 #include "mcf.h"
00006
00011 class GraphEdgeIterator {
00012 private:
00013 LinkGraph *graph;
00014 NodeID from;
00015 NodeID to;
00016
00017 public:
00018
00023 GraphEdgeIterator(LinkGraphJob *job) : graph(&job->Graph()),
00024 from(INVALID_NODE), to(INVALID_NODE)
00025 {}
00026
00032 void SetNode(NodeID source, NodeID node)
00033 {
00034 this->to = node;
00035 this->from = node;
00036 }
00037
00042 NodeID Next()
00043 {
00044 if (this->to != INVALID_NODE) {
00045 this->to = this->graph->GetEdge(this->from, this->to).next_edge;
00046 }
00047 return this->to;
00048 }
00049 };
00050
00054 class FlowEdgeIterator {
00055 private:
00056 LinkGraphJob *job;
00057
00059 std::map<StationID, NodeID> station_to_node;
00060
00062 FlowStat::SharesMap::const_iterator it;
00063
00065 FlowStat::SharesMap::const_iterator end;
00066 public:
00067
00072 FlowEdgeIterator(LinkGraphJob *job) : job(job)
00073 {
00074 for (NodeID i = 0; i < job->Graph().GetSize(); ++i) {
00075 this->station_to_node[job->Graph().GetNode(i).station] = i;
00076 }
00077 }
00078
00084 void SetNode(NodeID source, NodeID node)
00085 {
00086 static const FlowStat::SharesMap empty;
00087 FlowStatMap &flows = this->job->GetNode(node).flows;
00088 FlowStatMap::const_iterator it = flows.find(this->job->Graph().GetNode(source).station);
00089 if (it != flows.end()) {
00090 this->it = it->second.GetShares()->begin();
00091 this->end = it->second.GetShares()->end();
00092 } else {
00093 this->it = empty.begin();
00094 this->end = empty.end();
00095 }
00096 }
00097
00102 NodeID Next()
00103 {
00104 if (this->it == this->end) return INVALID_NODE;
00105 return this->station_to_node[(this->it++)->second];
00106 }
00107 };
00108
00118 bool DistanceAnnotation::IsBetter(const DistanceAnnotation *base, uint cap,
00119 int free_cap, uint dist) const
00120 {
00121
00122
00123 if (base->distance == UINT_MAX) {
00124 return false;
00125 } else if (this->distance == UINT_MAX) {
00126 return true;
00127 }
00128
00129 if (free_cap > 0 && base->free_capacity > 0) {
00130
00131
00132
00133 return this->free_capacity > 0 ? (base->distance + dist < this->distance) : true;
00134 } else {
00135
00136
00137
00138
00139 return this->free_capacity > 0 ? false : (base->distance + dist < this->distance);
00140 }
00141 }
00142
00152 bool CapacityAnnotation::IsBetter(const CapacityAnnotation *base, uint cap,
00153 int free_cap, uint dist) const
00154 {
00155 int min_cap = Path::GetCapacityRatio(min(base->free_capacity, free_cap), min(base->capacity, cap));
00156 int this_cap = this->GetCapacityRatio();
00157 if (min_cap == this_cap) {
00158
00159
00160 return base->distance == UINT_MAX ? false : (base->distance + dist < this->distance);
00161 } else {
00162 return min_cap > this_cap;
00163 }
00164 }
00165
00175 template<class Tannotation, class Tedge_iterator>
00176 void MultiCommodityFlow::Dijkstra(NodeID source_node, PathVector &paths)
00177 {
00178 typedef std::set<Tannotation *, typename Tannotation::Comparator> AnnoSet;
00179 Tedge_iterator iter(this->job);
00180 uint size = this->graph->GetSize();
00181 AnnoSet annos;
00182 paths.resize(size, NULL);
00183 for (NodeID node = 0; node < size; ++node) {
00184 Tannotation *anno = new Tannotation(node, node == source_node);
00185 annos.insert(anno);
00186 paths[node] = anno;
00187 }
00188 while (!annos.empty()) {
00189 typename AnnoSet::iterator i = annos.begin();
00190 Tannotation *source = *i;
00191 annos.erase(i);
00192 NodeID from = source->GetNode();
00193 iter.SetNode(source_node, from);
00194 for (NodeID to = iter.Next(); to != INVALID_NODE; to = iter.Next()) {
00195 if (to == from) continue;
00196 Edge &edge = this->graph->GetEdge(from, to);
00197 assert(edge.distance < UINT_MAX);
00198 uint capacity = edge.capacity;
00199 if (this->max_saturation != UINT_MAX) {
00200 capacity *= this->max_saturation;
00201 capacity /= 100;
00202 if (capacity == 0) capacity = 1;
00203 }
00204
00205 uint distance = edge.distance + 1;
00206 Tannotation *dest = static_cast<Tannotation *>(paths[to]);
00207 EdgeAnnotation &edge_anno = this->job->GetEdge(from, to);
00208 if (dest->IsBetter(source, capacity, capacity - edge_anno.flow, distance)) {
00209 annos.erase(dest);
00210 dest->Fork(source, capacity, capacity - edge_anno.flow, distance);
00211 annos.insert(dest);
00212 }
00213 }
00214 }
00215 }
00216
00222 void MultiCommodityFlow::CleanupPaths(NodeID source_id, PathVector &paths)
00223 {
00224 Path *source = paths[source_id];
00225 paths[source_id] = NULL;
00226 for (PathVector::iterator i = paths.begin(); i != paths.end(); ++i) {
00227 Path *path = *i;
00228 if (path == NULL) continue;
00229 if (path->GetParent() == source) path->Detach();
00230 while (path != source && path != NULL && path->GetFlow() == 0) {
00231 Path *parent = path->GetParent();
00232 path->Detach();
00233 if (path->GetNumChildren() == 0) {
00234 paths[path->GetNode()] = NULL;
00235 delete path;
00236 }
00237 path = parent;
00238 }
00239 }
00240 delete source;
00241 paths.clear();
00242 }
00243
00253 uint MultiCommodityFlow::PushFlow(EdgeAnnotation &edge, Path *path, uint accuracy,
00254 uint max_saturation)
00255 {
00256 assert(edge.unsatisfied_demand > 0);
00257 uint flow = Clamp(edge.demand / accuracy, 1, edge.unsatisfied_demand);
00258 flow = path->AddFlow(flow, this->job, max_saturation);
00259 edge.unsatisfied_demand -= flow;
00260 return flow;
00261 }
00262
00269 uint MCF1stPass::FindCycleFlow(const PathVector &path, const Path *cycle_begin)
00270 {
00271 uint flow = UINT_MAX;
00272 const Path *cycle_end = cycle_begin;
00273 do {
00274 flow = min(flow, cycle_begin->GetFlow());
00275 cycle_begin = path[cycle_begin->GetNode()];
00276 } while (cycle_begin != cycle_end);
00277 return flow;
00278 }
00279
00286 void MCF1stPass::EliminateCycle(PathVector &path, Path *cycle_begin, uint flow)
00287 {
00288 Path *cycle_end = cycle_begin;
00289 do {
00290 NodeID prev = cycle_begin->GetNode();
00291 cycle_begin->ReduceFlow(flow);
00292 cycle_begin = path[cycle_begin->GetNode()];
00293 EdgeAnnotation &edge = this->job->GetEdge(prev, cycle_begin->GetNode());
00294 edge.flow -= flow;
00295 } while (cycle_begin != cycle_end);
00296 }
00297
00307 bool MCF1stPass::EliminateCycles(PathVector &path, NodeID origin_id, NodeID next_id)
00308 {
00309 static Path *invalid_path = new Path(INVALID_NODE, true);
00310 Path *at_next_pos = path[next_id];
00311
00312
00313 if (at_next_pos == invalid_path) return false;
00314
00315 if (at_next_pos == NULL) {
00316
00317
00318 PathSet &paths = this->job->GetNode(next_id).paths;
00319 PathViaMap next_hops;
00320 for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i) {
00321 Path *new_child = *i;
00322 if (new_child->GetOrigin() == origin_id) {
00323 PathViaMap::iterator via_it = next_hops.find(new_child->GetNode());
00324 if (via_it == next_hops.end()) {
00325 next_hops[new_child->GetNode()] = new_child;
00326 } else {
00327 Path *child = via_it->second;
00328 uint new_flow = new_child->GetFlow();
00329 child->AddFlow(new_flow);
00330 new_child->ReduceFlow(new_flow);
00331 }
00332 }
00333 }
00334 bool found = false;
00335
00336 for (PathViaMap::iterator via_it = next_hops.begin();
00337 via_it != next_hops.end(); ++via_it) {
00338 Path *child = via_it->second;
00339 if (child->GetFlow() > 0) {
00340
00341
00342 path[next_id] = child;
00343 found = this->EliminateCycles(path, origin_id, child->GetNode()) || found;
00344 }
00345 }
00346
00347
00348
00349
00350
00351 path[next_id] = found ? NULL : invalid_path;
00352 return found;
00353 }
00354
00355
00356
00357 uint flow = this->FindCycleFlow(path, at_next_pos);
00358 if (flow > 0) {
00359 this->EliminateCycle(path, at_next_pos, flow);
00360 return true;
00361 }
00362
00363 return false;
00364 }
00365
00371 bool MCF1stPass::EliminateCycles()
00372 {
00373 bool cycles_found = false;
00374 uint size = this->graph->GetSize();
00375 PathVector path(size, NULL);
00376 for (NodeID node = 0; node < size; ++node) {
00377
00378
00379 std::fill(path.begin(), path.end(), (Path *)NULL);
00380 cycles_found |= this->EliminateCycles(path, node, node);
00381 }
00382 return cycles_found;
00383 }
00384
00389 MCF1stPass::MCF1stPass(LinkGraphJob *job) : MultiCommodityFlow(job)
00390 {
00391 PathVector paths;
00392 uint size = this->graph->GetSize();
00393 uint accuracy = job->Settings().accuracy;
00394 bool more_loops;
00395
00396 do {
00397 more_loops = false;
00398 for (NodeID source = 0; source < size; ++source) {
00399
00400 this->Dijkstra<DistanceAnnotation, GraphEdgeIterator>(source, paths);
00401
00402 for (NodeID dest = 0; dest < size; ++dest) {
00403 EdgeAnnotation &edge = this->job->GetEdge(source, dest);
00404 if (edge.unsatisfied_demand > 0) {
00405 Path *path = paths[dest];
00406 assert(path != NULL);
00407
00408
00409
00410 if (path->GetFreeCapacity() > 0 && this->PushFlow(edge, path,
00411 accuracy, this->max_saturation) > 0) {
00412
00413
00414 more_loops = more_loops || (edge.unsatisfied_demand > 0);
00415 } else if (edge.unsatisfied_demand == edge.demand &&
00416 path->GetFreeCapacity() > INT_MIN) {
00417 this->PushFlow(edge, path, accuracy, UINT_MAX);
00418 }
00419 }
00420 }
00421 this->CleanupPaths(source, paths);
00422 }
00423 } while (more_loops || this->EliminateCycles());
00424 }
00425
00431 MCF2ndPass::MCF2ndPass(LinkGraphJob *job) : MultiCommodityFlow(job)
00432 {
00433 this->max_saturation = UINT_MAX;
00434 PathVector paths;
00435 uint size = this->graph->GetSize();
00436 uint accuracy = job->Settings().accuracy;
00437 bool demand_left = true;
00438 while (demand_left) {
00439 demand_left = false;
00440 for (NodeID source = 0; source < size; ++source) {
00441 this->Dijkstra<CapacityAnnotation, FlowEdgeIterator>(source, paths);
00442 for (NodeID dest = 0; dest < size; ++dest) {
00443 EdgeAnnotation &edge = this->job->GetEdge(source, dest);
00444 Path *path = paths[dest];
00445 if (edge.unsatisfied_demand > 0 && path->GetFreeCapacity() > INT_MIN) {
00446 this->PushFlow(edge, path, accuracy, UINT_MAX);
00447 if (edge.unsatisfied_demand > 0) demand_left = true;
00448 }
00449 }
00450 this->CleanupPaths(source, paths);
00451 }
00452 }
00453 }
00454
00466 template <typename T>
00467 bool Greater(T x_anno, T y_anno, NodeID x, NodeID y)
00468 {
00469 if (x_anno > y_anno) return true;
00470 if (x_anno < y_anno) return false;
00471 return x > y;
00472 }
00473
00480 bool CapacityAnnotation::Comparator::operator()(const CapacityAnnotation *x,
00481 const CapacityAnnotation *y) const
00482 {
00483 return x != y && Greater<int>(x->GetAnnotation(), y->GetAnnotation(),
00484 x->GetNode(), y->GetNode());
00485 }
00486
00493 bool DistanceAnnotation::Comparator::operator()(const DistanceAnnotation *x,
00494 const DistanceAnnotation *y) const
00495 {
00496 return x != y && !Greater<uint>(x->GetAnnotation(), y->GetAnnotation(),
00497 x->GetNode(), y->GetNode());
00498 }