/** * 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()); }
/** * Run the second pass of the MCF calculation which assigns all remaining * demands to existing paths. * @param job Link graph job to calculate. */ MCF2ndPass::MCF2ndPass(LinkGraphJob &job) : MultiCommodityFlow(job) { this->max_saturation = UINT_MAX; // disable artificial cap on saturation PathVector paths; uint size = job.Size(); uint accuracy = job.Settings().accuracy; bool demand_left = true; while (demand_left) { demand_left = false; for (NodeID source = 0; source < size; ++source) { this->Dijkstra<CapacityAnnotation, FlowEdgeIterator>(source, paths); for (NodeID dest = 0; dest < size; ++dest) { Edge edge = this->job[source][dest]; Path *path = paths[dest]; if (edge.UnsatisfiedDemand() > 0 && path->GetFreeCapacity() > INT_MIN) { this->PushFlow(edge, path, accuracy, UINT_MAX); if (edge.UnsatisfiedDemand() > 0) demand_left = true; } } this->CleanupPaths(source, paths); } } }