4 #include "../core/math_func.hpp" 8 #include "../safeguards.h" 10 typedef std::map<NodeID, Path *> PathViaMap;
55 int cached_annotation;
107 i(NULL, NULL, INVALID_NODE), end(NULL, NULL, INVALID_NODE)
117 this->i = this->job[
node].Begin();
118 this->end = this->job[
node].End();
127 return this->i != this->end ? (this->i++)->first : INVALID_NODE;
142 FlowStat::SharesMap::const_iterator
it;
145 FlowStat::SharesMap::const_iterator
end;
154 for (NodeID i = 0; i < job.
Size(); ++i) {
155 StationID st = job[i].Station();
156 if (st >= this->station_to_node.size()) {
157 this->station_to_node.resize(st + 1);
159 this->station_to_node[st] = i;
171 FlowStatMap::const_iterator it = flows.find(this->job[source].
Station());
172 if (it != flows.end()) {
173 this->it = it->second.GetShares()->begin();
174 this->end = it->second.GetShares()->end();
187 if (this->it == this->end)
return INVALID_NODE;
188 return this->station_to_node[(this->it++)->second];
202 int free_cap, uint dist)
const 208 }
else if (this->
distance == UINT_MAX) {
236 int free_cap, uint dist)
const 240 if (min_cap == this_cap) {
245 return min_cap > this_cap;
258 template<
class Tannotation,
class Tedge_iterator>
261 typedef std::set<Tannotation *, typename Tannotation::Comparator> AnnoSet;
262 Tedge_iterator iter(this->job);
263 uint size = this->job.Size();
265 paths.resize(size, NULL);
267 Tannotation *anno =
new Tannotation(
node,
node == source_node);
268 anno->UpdateAnnotation();
272 while (!annos.empty()) {
273 typename AnnoSet::iterator i = annos.begin();
274 Tannotation *source = *i;
276 NodeID from = source->GetNode();
277 iter.SetNode(source_node, from);
278 for (NodeID to = iter.Next(); to != INVALID_NODE; to = iter.Next()) {
279 if (to == from)
continue;
280 Edge edge = this->job[from][to];
282 if (this->max_saturation != UINT_MAX) {
283 capacity *= this->max_saturation;
285 if (capacity == 0) capacity = 1;
289 Tannotation *dest =
static_cast<Tannotation *
>(paths[to]);
290 if (dest->IsBetter(source, capacity, capacity - edge.Flow(),
distance)) {
292 dest->Fork(source, capacity, capacity - edge.Flow(),
distance);
293 dest->UpdateAnnotation();
307 Path *source = paths[source_id];
308 paths[source_id] = NULL;
309 for (PathVector::iterator i = paths.begin(); i != paths.end(); ++i) {
311 if (path == NULL)
continue;
313 while (path != source && path != NULL && path->
GetFlow() == 0) {
339 assert(edge.UnsatisfiedDemand() > 0);
340 uint
flow =
Clamp(edge.Demand() / accuracy, 1, edge.UnsatisfiedDemand());
341 flow = path->
AddFlow(flow, this->job, max_saturation);
342 edge.SatisfyDemand(flow);
354 uint
flow = UINT_MAX;
355 const Path *cycle_end = cycle_begin;
358 cycle_begin = path[cycle_begin->GetNode()];
359 }
while (cycle_begin != cycle_end);
371 Path *cycle_end = cycle_begin;
373 NodeID prev = cycle_begin->
GetNode();
375 if (cycle_begin->
GetFlow() == 0) {
376 PathList &node_paths = this->job[cycle_begin->
GetParent()->
GetNode()].Paths();
377 for (PathList::iterator i = node_paths.begin(); i != node_paths.end(); ++i) {
378 if (*i == cycle_begin) {
380 node_paths.push_back(cycle_begin);
385 cycle_begin = path[prev];
386 Edge edge = this->job[prev][cycle_begin->
GetNode()];
387 edge.RemoveFlow(flow);
388 }
while (cycle_begin != cycle_end);
402 Path *at_next_pos = path[next_id];
407 if (at_next_pos == NULL) {
410 PathList &paths = this->job[next_id].Paths();
411 PathViaMap next_hops;
412 for (PathList::iterator i = paths.begin(); i != paths.end();) {
413 Path *new_child = *i;
414 uint new_flow = new_child->
GetFlow();
415 if (new_flow == 0)
break;
416 if (new_child->
GetOrigin() == origin_id) {
417 PathViaMap::iterator via_it = next_hops.find(new_child->
GetNode());
418 if (via_it == next_hops.end()) {
419 next_hops[new_child->
GetNode()] = new_child;
422 Path *child = via_it->second;
430 paths.push_back(new_child);
438 for (PathViaMap::iterator via_it = next_hops.begin();
439 via_it != next_hops.end(); ++via_it) {
440 Path *child = via_it->second;
444 path[next_id] = child;
445 found = this->EliminateCycles(path, origin_id, child->
GetNode()) || found;
459 uint
flow = this->FindCycleFlow(path, at_next_pos);
461 this->EliminateCycle(path, at_next_pos, flow);
475 bool cycles_found =
false;
476 uint size = this->job.Size();
477 PathVector path(size, NULL);
481 std::fill(path.begin(), path.end(), (
Path *)NULL);
482 cycles_found |= this->EliminateCycles(path,
node,
node);
494 uint size = job.
Size();
500 for (NodeID source = 0; source < size; ++source) {
502 this->Dijkstra<DistanceAnnotation, GraphEdgeIterator>(source, paths);
504 for (NodeID dest = 0; dest < size; ++dest) {
505 Edge edge = job[source][dest];
506 if (edge.UnsatisfiedDemand() > 0) {
507 Path *path = paths[dest];
508 assert(path != NULL);
516 more_loops = more_loops || (edge.UnsatisfiedDemand() > 0);
517 }
else if (edge.UnsatisfiedDemand() == edge.Demand() &&
519 this->
PushFlow(edge, path, accuracy, UINT_MAX);
537 uint size = job.
Size();
539 bool demand_left =
true;
540 while (demand_left) {
542 for (NodeID source = 0; source < size; ++source) {
543 this->Dijkstra<CapacityAnnotation, FlowEdgeIterator>(source, paths);
544 for (NodeID dest = 0; dest < size; ++dest) {
545 Edge edge = this->job[source][dest];
546 Path *path = paths[dest];
547 if (edge.UnsatisfiedDemand() > 0 && path->
GetFreeCapacity() > INT_MIN) {
548 this->
PushFlow(edge, path, accuracy, UINT_MAX);
549 if (edge.UnsatisfiedDemand() > 0) demand_left =
true;
568 template <
typename T>
569 bool Greater(T x_anno, T y_anno, NodeID x, NodeID y)
571 if (x_anno > y_anno)
return true;
572 if (x_anno < y_anno)
return false;
void UpdateAnnotation()
Update the cached annotation value.
LinkGraphJob & job
Job being executed.
Distance-based annotation for use in the Dijkstra algorithm.
bool operator()(const DistanceAnnotation *x, const DistanceAnnotation *y) const
Compare two distance annotations.
uint FindCycleFlow(const PathVector &path, const Path *cycle_begin)
Find the flow along a cycle including cycle_begin in path.
int free_capacity
This capacity is min(edge.capacity - edge.flow) for the current run of Dijkstra.
void UpdateAnnotation()
Update the cached annotation value.
FlowStat::SharesMap::const_iterator it
Current iterator in the shares map.
GraphEdgeIterator(LinkGraphJob &job)
Construct a GraphEdgeIterator.
DistanceAnnotation(NodeID n, bool source=false)
Constructor.
MCF1stPass(LinkGraphJob &job)
Run the first pass of the MCF calculation.
Multi-commodity flow calculating base class.
std::vector< NodeID > station_to_node
Lookup table for getting NodeIDs from StationIDs.
bool IsBetter(const CapacityAnnotation *base, uint cap, int free_cap, uint dist) const
Determines if an extension to the given Path with the given parameters is better than this path...
Declaration of Multi-Commodity-Flow solver.
void AddFlow(uint f)
Increase the flow on this leg only by the specified amount.
uint PushFlow(Edge &edge, Path *path, uint accuracy, uint max_saturation)
Push flow along a path and update the unsatisfied_demand of the associated edge.
NodeID GetOrigin() const
Get the overall origin of the path.
const LinkGraphSettings & Settings() const
Get the link graph settings for this component.
uint GetNumChildren() const
Get the number of "forked off" child legs of this one.
MCF2ndPass(LinkGraphJob &job)
Run the second pass of the MCF calculation which assigns all remaining demands to existing paths...
bool IsBetter(const DistanceAnnotation *base, uint cap, int free_cap, uint dist) const
Determines if an extension to the given Path with the given parameters is better than this path...
uint GetFlow() const
Get the flow on this leg.
bool Greater(T x_anno, T y_anno, NodeID x, NodeID y)
Relation that creates a weak order without duplicates.
void EliminateCycle(PathVector &path, Path *cycle_begin, uint flow)
Eliminate a cycle of the given flow in the given set of paths.
uint distance
Sum(distance of all legs up to this one).
NodeID GetNode() const
Get the node this leg passes.
int GetAnnotation() const
Return the actual value of the annotation, in this case the capacity.
A leg of a path in the link graph.
CapacityAnnotation(NodeID n, bool source=false)
Constructor.
Iterator class for getting edges from a FlowStatMap.
int GetCapacityRatio() const
Get capacity ratio of this path.
bool operator()(const CapacityAnnotation *x, const CapacityAnnotation *y) const
Compare two capacity annotations.
Capacity-based annotation for use in the Dijkstra algorithm.
static Path * invalid_path
Static instance of an invalid path.
void ReduceFlow(uint f)
Reduce the flow on this leg only by the specified amount.
static const SharesMap empty_sharesmap
Static instance of FlowStat::SharesMap.
static T min(const T a, const T b)
Returns the minimum of two values.
uint8 accuracy
accuracy when calculating things on the link graph. low accuracy => low running time ...
uint capacity
This capacity is min(capacity) fom all edges.
int GetFreeCapacity() const
Get the free capacity of the path.
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
NodeID Next()
Get the next node for which a flow exists.
NodeID node
Link graph node this leg passes.
EdgeIterator i
Iterator pointing to current edge.
uint max_saturation
Maximum saturation for edges.
void Dijkstra(NodeID from, PathVector &paths)
A slightly modified Dijkstra algorithm.
FlowEdgeIterator(LinkGraphJob &job)
Constructor.
Comparator for std containers.
void Detach()
Detach this path from its parent.
uint flow
Flow the current run of the mcf solver assigns.
void SetNode(NodeID source, NodeID node)
Setup the node to start iterating at.
uint DistanceMaxPlusManhattan(TileIndex t0, TileIndex t1)
Gets the biggest distance component (x or y) between the two given tiles plus the Manhattan distance...
uint Size() const
Get the size of the underlying link graph.
void CleanupPaths(NodeID source, PathVector &paths)
Clean up paths that lead nowhere and the root path.
Flow descriptions by origin stations.
LinkGraphJob & job
Job we're working with.
EdgeIterator end
Iterator pointing beyond last edge.
NodeID Next()
Retrieve the ID of the node the next edge points to.
bool EliminateCycles()
Eliminate all cycles in the graph.
uint GetAnnotation() const
Return the actual value of the annotation, in this case the distance.
Path * GetParent()
Get the parent leg of this one.
FlowStat::SharesMap::const_iterator end
End of the shares map.
void SetNode(NodeID source, NodeID node)
Setup the node to retrieve edges from.
An iterator for non-const edges.
LinkGraphJob & job
Link graph job we're working with.
uint Capacity() const
Get edge's capacity.
Path * parent
Parent leg of this one.
Comparator for std containers.
Iterator class for getting the edges in the order of their next_edge members.
Class for calculation jobs to be run on link graphs.