/** * Push flow along a path and update the unsatisfied_demand of the associated * edge. * @param edge Edge whose ends the path connects. * @param path End of the path the flow should be pushed on. * @param accuracy Accuracy of the calculation. * @param max_saturation If < UINT_MAX only push flow up to the given * saturation, otherwise the path can be "overloaded". */ uint MultiCommodityFlow::PushFlow(Edge &edge, Path *path, uint accuracy, uint max_saturation) { assert(edge.UnsatisfiedDemand() > 0); uint flow = Clamp(edge.Demand() / accuracy, 1, edge.UnsatisfiedDemand()); flow = path->AddFlow(flow, this->job, max_saturation); edge.SatisfyDemand(flow); return flow; }
/** * Run the first pass of the MCF calculation. * @param job Link graph job to calculate. */ MCF1stPass::MCF1stPass(LinkGraphJob &job) : MultiCommodityFlow(job) { PathVector paths; uint size = job.Size(); uint accuracy = job.Settings().accuracy; bool more_loops; do { more_loops = false; for (NodeID source = 0; source < size; ++source) { /* First saturate the shortest paths. */ this->Dijkstra<DistanceAnnotation, GraphEdgeIterator>(source, paths); for (NodeID dest = 0; dest < size; ++dest) { Edge edge = job[source][dest]; if (edge.UnsatisfiedDemand() > 0) { Path *path = paths[dest]; assert(path != NULL); /* Generally only allow paths that don't exceed the * available capacity. But if no demand has been assigned * yet, make an exception and allow any valid path *once*. */ if (path->GetFreeCapacity() > 0 && this->PushFlow(edge, path, accuracy, this->max_saturation) > 0) { /* If a path has been found there is a chance we can * find more. */ more_loops = more_loops || (edge.UnsatisfiedDemand() > 0); } else if (edge.UnsatisfiedDemand() == edge.Demand() && path->GetFreeCapacity() > INT_MIN) { this->PushFlow(edge, path, accuracy, UINT_MAX); } } } this->CleanupPaths(source, paths); } } while (more_loops || this->EliminateCycles()); }