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 if (base->distance == UINT_MAX) {
00022 return false;
00023 } else if (this->distance == UINT_MAX) {
00024 return true;
00025 }
00026
00027 if (free_cap > 0 && base->free_capacity > 0) {
00028
00029
00030
00031 return this->free_capacity > 0 ? (base->distance + dist < this->distance) : true;
00032 } else {
00033
00034
00035
00036
00037 return this->free_capacity > 0 ? false : (base->distance + dist < this->distance);
00038 }
00039 }
00040
00050 bool CapacityAnnotation::IsBetter(const CapacityAnnotation *base, uint cap,
00051 int free_cap, uint dist) const
00052 {
00053 int min_cap = Path::GetCapacityRatio(min(base->free_capacity, free_cap), min(base->capacity, cap));
00054 int this_cap = this->GetCapacityRatio();
00055 if (min_cap == this_cap) {
00056
00057
00058 return base->distance == UINT_MAX ? false : (base->distance + dist < this->distance);
00059 } else {
00060 return min_cap > this_cap;
00061 }
00062 }
00063
00077 template<class Tannotation>
00078 void MultiCommodityFlow::Dijkstra(NodeID source_node, PathVector &paths,
00079 bool create_new_paths)
00080 {
00081 typedef std::set<Tannotation *, typename Tannotation::Comparator> AnnoSet;
00082 uint size = this->graph->GetSize();
00083 StationID source_station = this->graph->GetNode(source_node).station;
00084 AnnoSet annos;
00085 paths.resize(size, NULL);
00086 for (NodeID node = 0; node < size; ++node) {
00087 Tannotation *anno = new Tannotation(node, node == source_node);
00088 annos.insert(anno);
00089 paths[node] = anno;
00090 }
00091 while (!annos.empty()) {
00092 typename AnnoSet::iterator i = annos.begin();
00093 Tannotation *source = *i;
00094 annos.erase(i);
00095 NodeID from = source->GetNode();
00096 NodeID to = this->graph->GetFirstEdge(from);
00097 while (to != INVALID_NODE) {
00098 Edge &edge = this->graph->GetEdge(from, to);
00099 assert(edge.distance < UINT_MAX);
00100 if (create_new_paths || this->graph->GetNode(from)
00101 .flows[source_station][this->graph->GetNode(to).station] > 0) {
00102 uint capacity = edge.capacity;
00103 if (create_new_paths) {
00104 capacity *= this->graph->GetSettings().short_path_saturation;
00105 capacity /= 100;
00106 if (capacity == 0) capacity = 1;
00107 }
00108
00109 uint distance = edge.distance + 1;
00110 Tannotation *dest = static_cast<Tannotation *>(paths[to]);
00111 if (dest->IsBetter(source, capacity, capacity - edge.flow, distance)) {
00112 annos.erase(dest);
00113 dest->Fork(source, capacity, capacity - edge.flow, distance);
00114 annos.insert(dest);
00115 }
00116 }
00117 to = edge.next_edge;
00118 }
00119 }
00120 }
00121
00127 void MultiCommodityFlow::CleanupPaths(NodeID source_id, PathVector &paths)
00128 {
00129 Path *source = paths[source_id];
00130 paths[source_id] = NULL;
00131 for (PathVector::iterator i = paths.begin(); i != paths.end(); ++i) {
00132 Path *path = *i;
00133 if (path == NULL) continue;
00134 if (path->GetParent() == source) path->Detach();
00135 while (path != source && path != NULL && path->GetFlow() == 0) {
00136 Path *parent = path->GetParent();
00137 path->Detach();
00138 if (path->GetNumChildren() == 0) {
00139 paths[path->GetNode()] = NULL;
00140 delete path;
00141 }
00142 path = parent;
00143 }
00144 }
00145 delete source;
00146 paths.clear();
00147 }
00148
00158 uint MultiCommodityFlow::PushFlow(Edge &edge, Path *path, uint accuracy,
00159 bool positive_cap)
00160 {
00161 assert(edge.unsatisfied_demand > 0);
00162 uint flow = Clamp(edge.demand / accuracy, 1, edge.unsatisfied_demand);
00163 flow = path->AddFlow(flow, this->graph, positive_cap);
00164 edge.unsatisfied_demand -= flow;
00165 return flow;
00166 }
00167
00174 uint MCF1stPass::FindCycleFlow(const PathVector &path, const Path *cycle_begin)
00175 {
00176 uint flow = UINT_MAX;
00177 const Path *cycle_end = cycle_begin;
00178 do {
00179 flow = min(flow, cycle_begin->GetFlow());
00180 cycle_begin = path[cycle_begin->GetNode()];
00181 } while (cycle_begin != cycle_end);
00182 return flow;
00183 }
00184
00191 void MCF1stPass::EliminateCycle(PathVector &path, Path *cycle_begin, uint flow)
00192 {
00193 Path *cycle_end = cycle_begin;
00194 do {
00195 NodeID prev = cycle_begin->GetNode();
00196 cycle_begin->ReduceFlow(flow);
00197 cycle_begin = path[cycle_begin->GetNode()];
00198 Edge &edge = this->graph->GetEdge(prev, cycle_begin->GetNode());
00199 edge.flow -= flow;
00200 } while (cycle_begin != cycle_end);
00201 }
00202
00212 bool MCF1stPass::EliminateCycles(PathVector &path, NodeID origin_id, NodeID next_id)
00213 {
00214 static Path *invalid_path = new Path(INVALID_NODE, true);
00215 Path *at_next_pos = path[next_id];
00216
00217
00218 if (at_next_pos == invalid_path) return false;
00219
00220 if (at_next_pos == NULL) {
00221
00222
00223 PathSet &paths = this->graph->GetNode(next_id).paths;
00224 PathViaMap next_hops;
00225 for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i) {
00226 Path *new_child = *i;
00227 if (new_child->GetOrigin() == origin_id) {
00228 PathViaMap::iterator via_it = next_hops.find(new_child->GetNode());
00229 if (via_it == next_hops.end()) {
00230 next_hops[new_child->GetNode()] = new_child;
00231 } else {
00232 Path *child = via_it->second;
00233 uint new_flow = new_child->GetFlow();
00234 child->AddFlow(new_flow);
00235 new_child->ReduceFlow(new_flow);
00236 }
00237 }
00238 }
00239 bool found = false;
00240
00241 for (PathViaMap::iterator via_it = next_hops.begin();
00242 via_it != next_hops.end(); ++via_it) {
00243 Path *child = via_it->second;
00244 if (child->GetFlow() > 0) {
00245
00246
00247 path[next_id] = child;
00248 found = this->EliminateCycles(path, origin_id, child->GetNode()) || found;
00249 }
00250 }
00251
00252
00253
00254
00255
00256 path[next_id] = found ? NULL : invalid_path;
00257 return found;
00258 }
00259
00260
00261
00262 uint flow = this->FindCycleFlow(path, at_next_pos);
00263 if (flow > 0) {
00264 this->EliminateCycle(path, at_next_pos, flow);
00265 return true;
00266 }
00267
00268 return false;
00269 }
00270
00276 bool MCF1stPass::EliminateCycles()
00277 {
00278 bool cycles_found = false;
00279 uint size = this->graph->GetSize();
00280 PathVector path(size, NULL);
00281 for (NodeID node = 0; node < size; ++node) {
00282
00283
00284 std::fill(path.begin(), path.end(), (Path *)NULL);
00285 cycles_found |= this->EliminateCycles(path, node, node);
00286 }
00287 return cycles_found;
00288 }
00289
00294 MCF1stPass::MCF1stPass(LinkGraphComponent *graph) : MultiCommodityFlow(graph)
00295 {
00296 PathVector paths;
00297 uint size = this->graph->GetSize();
00298 uint accuracy = this->graph->GetSettings().accuracy;
00299 bool more_loops;
00300
00301 do {
00302 more_loops = false;
00303 for (NodeID source = 0; source < size; ++source) {
00304
00305 this->Dijkstra<DistanceAnnotation>(source, paths, true);
00306
00307 for (NodeID dest = 0; dest < size; ++dest) {
00308 Edge &edge = this->graph->GetEdge(source, dest);
00309 if (edge.unsatisfied_demand > 0) {
00310 Path *path = paths[dest];
00311 assert(path != NULL);
00312
00313
00314
00315 if (path->GetFreeCapacity() > 0 && this->PushFlow(edge, path,
00316 accuracy, true) > 0) {
00317
00318
00319 more_loops = more_loops || (edge.unsatisfied_demand > 0);
00320 } else if (edge.unsatisfied_demand == edge.demand &&
00321 path->GetFreeCapacity() > INT_MIN) {
00322 this->PushFlow(edge, path, accuracy, false);
00323 }
00324 }
00325 }
00326 this->CleanupPaths(source, paths);
00327 }
00328 } while (more_loops || this->EliminateCycles());
00329 }
00330
00336 MCF2ndPass::MCF2ndPass(LinkGraphComponent *graph) : MultiCommodityFlow(graph)
00337 {
00338 PathVector paths;
00339 uint size = this->graph->GetSize();
00340 uint accuracy = this->graph->GetSettings().accuracy;
00341 bool demand_left = true;
00342 while (demand_left) {
00343 demand_left = false;
00344 for (NodeID source = 0; source < size; ++source) {
00345 this->Dijkstra<CapacityAnnotation>(source, paths, false);
00346 for (NodeID dest = 0; dest < size; ++dest) {
00347 Edge &edge = this->graph->GetEdge(source, dest);
00348 Path *path = paths[dest];
00349 if (edge.unsatisfied_demand > 0 && path->GetFreeCapacity() > INT_MIN) {
00350 this->PushFlow(edge, path, accuracy, false);
00351 if (edge.unsatisfied_demand > 0) demand_left = true;
00352 }
00353 }
00354 this->CleanupPaths(source, paths);
00355 }
00356 }
00357 }
00358
00370 template <typename T>
00371 bool Greater(T x_anno, T y_anno, NodeID x, NodeID y)
00372 {
00373 if (x_anno > y_anno) return true;
00374 if (x_anno < y_anno) return false;
00375 return x > y;
00376 }
00377
00384 bool CapacityAnnotation::Comparator::operator()(const CapacityAnnotation *x,
00385 const CapacityAnnotation *y) const
00386 {
00387 return x != y && Greater<int>(x->GetAnnotation(), y->GetAnnotation(),
00388 x->GetNode(), y->GetNode());
00389 }
00390
00397 bool DistanceAnnotation::Comparator::operator()(const DistanceAnnotation *x,
00398 const DistanceAnnotation *y) const
00399 {
00400 return x != y && !Greater<uint>(x->GetAnnotation(), y->GetAnnotation(),
00401 x->GetNode(), y->GetNode());
00402 }