17typedef std::map<NodeID, Path *> PathViaMap;
62 int cached_annotation = 0;
105 std::vector<LinkGraphJob::EdgeAnnotation>::const_iterator
i;
106 std::vector<LinkGraphJob::EdgeAnnotation>::const_iterator
end;
122 this->i = this->job[node].edges.cbegin();
123 this->end = this->job[node].edges.cend();
132 return this->i != this->end ? (this->i++)->base.dest_node : INVALID_NODE;
147 FlowStat::SharesMap::const_iterator
it;
150 FlowStat::SharesMap::const_iterator
end;
159 for (NodeID i = 0; i <
job.Size(); ++i) {
160 StationID st =
job[i].base.station;
161 if (st >= this->station_to_node.size()) {
162 this->station_to_node.resize(st + 1);
164 this->station_to_node[st] = i;
176 FlowStatMap::const_iterator
it = flows.find(this->job[source].base.station);
177 if (
it != flows.end()) {
178 this->it =
it->second.GetShares()->begin();
179 this->end =
it->second.GetShares()->end();
192 if (this->it == this->end)
return INVALID_NODE;
193 return this->station_to_node[(this->it++)->second];
207 int free_cap, uint dist)
const
213 }
else if (this->
distance == UINT_MAX) {
242 int free_cap, uint dist)
const
246 if (min_cap == this_cap) {
251 return min_cap > this_cap;
264template <
class Tannotation,
class Tedge_iterator>
267 typedef std::set<Tannotation *, typename Tannotation::Comparator> AnnoSet;
268 Tedge_iterator iter(this->
job);
269 uint16_t size = this->
job.Size();
271 paths.resize(size,
nullptr);
272 for (NodeID node = 0; node < size; ++node) {
273 Tannotation *anno =
new Tannotation(node, node == source_node);
274 anno->UpdateAnnotation();
278 while (!annos.empty()) {
279 typename AnnoSet::iterator i = annos.begin();
280 Tannotation *source = *i;
282 NodeID from = source->GetNode();
283 iter.SetNode(source_node, from);
284 for (NodeID to = iter.Next(); to != INVALID_NODE; to = iter.Next()) {
285 if (to == from)
continue;
286 const Edge &edge = this->
job[from][to];
291 if (capacity == 0) capacity = 1;
302 uint distance_anno = express ? time : distance;
304 Tannotation *dest =
static_cast<Tannotation *
>(paths[to]);
305 if (dest->IsBetter(source, capacity, capacity - edge.Flow(), distance_anno)) {
307 dest->Fork(source, capacity, capacity - edge.Flow(), distance_anno);
308 dest->UpdateAnnotation();
322 Path *source = paths[source_id];
323 paths[source_id] =
nullptr;
324 for (PathVector::iterator i = paths.begin(); i != paths.end(); ++i) {
326 if (path ==
nullptr)
continue;
328 while (path != source && path !=
nullptr && path->
GetFlow() == 0) {
332 paths[path->
GetNode()] =
nullptr;
355 assert(node.UnsatisfiedDemandTo(to) > 0);
356 uint flow =
Clamp(node.DemandTo(to) / accuracy, 1, node.UnsatisfiedDemandTo(to));
358 node.SatisfyDemandTo(to, flow);
370 uint flow = UINT_MAX;
371 const Path *cycle_end = cycle_begin;
373 flow = std::min(flow, cycle_begin->
GetFlow());
374 cycle_begin = path[cycle_begin->
GetNode()];
375 }
while (cycle_begin != cycle_end);
387 Path *cycle_end = cycle_begin;
389 NodeID prev = cycle_begin->
GetNode();
391 if (cycle_begin->
GetFlow() == 0) {
393 for (PathList::iterator i = node_paths.begin(); i != node_paths.end(); ++i) {
394 if (*i == cycle_begin) {
396 node_paths.push_back(cycle_begin);
401 cycle_begin = path[prev];
402 Edge &edge = this->
job[prev][cycle_begin->
GetNode()];
403 edge.RemoveFlow(flow);
404 }
while (cycle_begin != cycle_end);
418 Path *at_next_pos = path[next_id];
423 if (at_next_pos ==
nullptr) {
426 PathList &paths = this->
job[next_id].paths;
427 PathViaMap next_hops;
428 for (PathList::iterator i = paths.begin(); i != paths.end();) {
429 Path *new_child = *i;
430 uint new_flow = new_child->
GetFlow();
431 if (new_flow == 0)
break;
432 if (new_child->
GetOrigin() == origin_id) {
433 PathViaMap::iterator via_it = next_hops.find(new_child->
GetNode());
434 if (via_it == next_hops.end()) {
435 next_hops[new_child->
GetNode()] = new_child;
438 Path *child = via_it->second;
446 paths.push_back(new_child);
454 for (PathViaMap::iterator via_it = next_hops.begin();
455 via_it != next_hops.end(); ++via_it) {
456 Path *child = via_it->second;
460 path[next_id] = child;
491 bool cycles_found =
false;
492 uint16_t size = this->
job.Size();
493 PathVector path(size,
nullptr);
494 for (NodeID node = 0; node < size; ++node) {
497 std::fill(path.begin(), path.end(), (
Path *)
nullptr);
510 uint16_t size =
job.Size();
511 uint accuracy =
job.Settings().accuracy;
513 std::vector<bool> finished_sources(size);
517 for (NodeID source = 0; source < size; ++source) {
518 if (finished_sources[source])
continue;
523 Node &src_node =
job[source];
524 bool source_demand_left =
false;
525 for (NodeID dest = 0; dest < size; ++dest) {
526 if (src_node.UnsatisfiedDemandTo(dest) > 0) {
527 Path *path = paths[dest];
528 assert(path !=
nullptr);
532 if (path->
GetFreeCapacity() > 0 && this->PushFlow(src_node, dest, path,
533 accuracy, this->max_saturation) > 0) {
536 more_loops = more_loops || (src_node.UnsatisfiedDemandTo(dest) > 0);
537 }
else if (src_node.UnsatisfiedDemandTo(dest) == src_node.DemandTo(dest) &&
539 this->
PushFlow(src_node, dest, path, accuracy, UINT_MAX);
541 if (src_node.UnsatisfiedDemandTo(dest) > 0) source_demand_left =
true;
544 finished_sources[source] = !source_demand_left;
559 uint16_t size =
job.Size();
560 uint accuracy =
job.Settings().accuracy;
561 bool demand_left =
true;
562 std::vector<bool> finished_sources(size);
563 while (demand_left && !
job.IsJobAborted()) {
565 for (NodeID source = 0; source < size; ++source) {
566 if (finished_sources[source])
continue;
570 Node &src_node =
job[source];
571 bool source_demand_left =
false;
572 for (NodeID dest = 0; dest < size; ++dest) {
573 Path *path = paths[dest];
574 if (src_node.UnsatisfiedDemandTo(dest) > 0 && path->
GetFreeCapacity() > INT_MIN) {
575 this->
PushFlow(src_node, dest, path, accuracy, UINT_MAX);
576 if (src_node.UnsatisfiedDemandTo(dest) > 0) {
578 source_demand_left =
true;
582 finished_sources[source] = !source_demand_left;
600bool Greater(T x_anno, T y_anno, NodeID x, NodeID y)
602 if (x_anno > y_anno)
return true;
603 if (x_anno < y_anno)
return false;
616 return x != y &&
Greater<int>(x->GetAnnotation(), y->GetAnnotation(),
617 x->GetNode(), y->GetNode());
629 return x != y && !
Greater<uint>(x->GetAnnotation(), y->GetAnnotation(),
630 x->GetNode(), y->GetNode());
@ Express
Express cargo (Goods, Food, Candy, but also possible for passengers).
bool IsCargoInClass(CargoType cargo, CargoClasses cc)
Does cargo c have cargo class cc?
Capacity-based annotation for use in the Dijkstra algorithm.
void UpdateAnnotation()
Update the cached annotation value.
int GetAnnotation() const
Return the actual value of the annotation, in this case the capacity.
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.
CapacityAnnotation(NodeID n, bool source=false)
Constructor.
Distance-based annotation for use in the Dijkstra algorithm.
bool IsBetter(const DistanceAnnotation *base, uint, int free_cap, uint dist) const
Determines if an extension to the given Path with the given parameters is better than this path.
DistanceAnnotation(NodeID n, bool source=false)
Constructor.
uint GetAnnotation() const
Return the actual value of the annotation, in this case the distance.
void UpdateAnnotation()
Update the cached annotation value.
FlowStat::SharesMap::const_iterator end
End of the shares map.
FlowStat::SharesMap::const_iterator it
Current iterator in the shares map.
void SetNode(NodeID source, NodeID node)
Setup the node to retrieve edges from.
FlowEdgeIterator(LinkGraphJob &job)
Constructor.
TypedIndexContainer< std::vector< NodeID >, StationID > station_to_node
Lookup table for getting NodeIDs from StationIDs.
LinkGraphJob & job
Link graph job we're working with.
NodeID Next()
Get the next node for which a flow exists.
Flow descriptions by origin stations.
static const SharesMap empty_sharesmap
Static instance of FlowStat::SharesMap.
LinkGraphJob & job
Job being executed.
std::vector< LinkGraphJob::EdgeAnnotation >::const_iterator end
Iterator pointing beyond last edge.
std::vector< LinkGraphJob::EdgeAnnotation >::const_iterator i
Iterator pointing to current edge.
GraphEdgeIterator(LinkGraphJob &job)
Construct a GraphEdgeIterator.
NodeID Next()
Retrieve the ID of the node the next edge points to.
void SetNode(NodeID, NodeID node)
Setup the node to start iterating at.
Class for calculation jobs to be run on link graphs.
bool IsJobAborted() const
Check if job has been aborted.
MCF1stPass(LinkGraphJob &job)
Run the first pass of the MCF calculation.
bool EliminateCycles()
Eliminate all cycles in the graph.
uint FindCycleFlow(const PathVector &path, const Path *cycle_begin)
Find the flow along a cycle including cycle_begin in path.
void EliminateCycle(PathVector &path, Path *cycle_begin, uint flow)
Eliminate a cycle of the given flow in the given set of paths.
MCF2ndPass(LinkGraphJob &job)
Run the second pass of the MCF calculation which assigns all remaining demands to existing paths.
MultiCommodityFlow(LinkGraphJob &job)
Constructor.
void Dijkstra(NodeID from, PathVector &paths)
A slightly modified Dijkstra algorithm.
LinkGraphJob & job
Job we're working with.
uint max_saturation
Maximum saturation for edges.
uint PushFlow(Node &node, NodeID to, Path *path, uint accuracy, uint max_saturation)
Push flow along a path and update the unsatisfied_demand of the associated edge.
void CleanupPaths(NodeID source, PathVector &paths)
Clean up paths that lead nowhere and the root path.
A leg of a path in the link graph.
NodeID GetOrigin() const
Get the overall origin of the path.
Path(NodeID n, bool source=false)
Create a leg of a path in the link graph.
void AddFlow(uint f)
Increase the flow on this leg only by the specified amount.
static Path * invalid_path
Static instance of an invalid path.
void Detach()
Detach this path from its parent.
int GetFreeCapacity() const
Get the free capacity of the path.
uint GetFlow() const
Get the flow on this leg.
uint distance
Sum(distance of all legs up to this one).
NodeID GetNode() const
Get the node this leg passes.
int GetCapacityRatio() const
Get capacity ratio of this path.
uint GetNumChildren() const
Get the number of "forked off" child legs of this one.
void ReduceFlow(uint f)
Reduce the flow on this leg only by the specified amount.
Path * GetParent()
Get the parent leg of this one.
uint capacity
This capacity is min(capacity) fom all edges.
int free_capacity
This capacity is min(edge.capacity - edge.flow) for the current run of Dijkstra.
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
A sort-of mixin that implements 'at(pos)' and 'operator[](pos)' only for a specific type.
uint DistanceMaxPlusManhattan(TileIndex t0, TileIndex t1)
Gets the biggest distance component (x or y) between the two given tiles plus the Manhattan distance,...
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
bool Greater(T x_anno, T y_anno, NodeID x, NodeID y)
Relation that creates a weak order without duplicates.
Declaration of Multi-Commodity-Flow solver.
A number of safeguards to prevent using unsafe methods.
Definition of base types and functions in a cross-platform compatible way.
Comparator for std containers.
bool operator()(const CapacityAnnotation *x, const CapacityAnnotation *y) const
Compare two capacity annotations.
Comparator for std containers.
bool operator()(const DistanceAnnotation *x, const DistanceAnnotation *y) const
Compare two distance annotations.
uint32_t TravelTime() const
Get edge's average travel time.
uint capacity
Capacity of the link.
Definition of the tick-based game-timer.