11#include "../core/math_func.hpp"
12#include "../timer/timer_game_tick.h"
15#include "../safeguards.h"
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) {
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) {
241 int free_cap, uint dist)
const
245 if (min_cap == this_cap) {
250 return min_cap > this_cap;
263template <
class Tannotation,
class Tedge_iterator>
266 typedef std::set<Tannotation *, typename Tannotation::Comparator> AnnoSet;
267 Tedge_iterator iter(this->
job);
268 uint16_t size = this->
job.
Size();
270 paths.resize(size,
nullptr);
271 for (NodeID node = 0; node < size; ++node) {
272 Tannotation *anno =
new Tannotation(node, node == source_node);
273 anno->UpdateAnnotation();
277 while (!annos.empty()) {
278 typename AnnoSet::iterator i = annos.begin();
279 Tannotation *source = *i;
281 NodeID from = source->GetNode();
282 iter.SetNode(source_node, from);
283 for (NodeID to = iter.Next(); to != INVALID_NODE; to = iter.Next()) {
284 if (to == from)
continue;
285 const Edge &edge = this->
job[from][to];
290 if (capacity == 0) capacity = 1;
301 uint distance_anno = express ? time : distance;
303 Tannotation *dest =
static_cast<Tannotation *
>(paths[to]);
304 if (dest->IsBetter(source, capacity, capacity - edge.Flow(), distance_anno)) {
306 dest->Fork(source, capacity, capacity - edge.Flow(), distance_anno);
307 dest->UpdateAnnotation();
321 Path *source = paths[source_id];
322 paths[source_id] =
nullptr;
323 for (PathVector::iterator i = paths.begin(); i != paths.end(); ++i) {
325 if (path ==
nullptr)
continue;
327 while (path != source && path !=
nullptr && path->
GetFlow() == 0) {
331 paths[path->
GetNode()] =
nullptr;
354 assert(node.UnsatisfiedDemandTo(to) > 0);
355 uint flow =
Clamp(node.DemandTo(to) / accuracy, 1, node.UnsatisfiedDemandTo(to));
356 flow = path->
AddFlow(flow, this->
job, max_saturation);
357 node.SatisfyDemandTo(to, flow);
369 uint flow = UINT_MAX;
370 const Path *cycle_end = cycle_begin;
372 flow = std::min(flow, cycle_begin->
GetFlow());
373 cycle_begin = path[cycle_begin->
GetNode()];
374 }
while (cycle_begin != cycle_end);
386 Path *cycle_end = cycle_begin;
388 NodeID prev = cycle_begin->
GetNode();
390 if (cycle_begin->
GetFlow() == 0) {
392 for (PathList::iterator i = node_paths.begin(); i != node_paths.end(); ++i) {
393 if (*i == cycle_begin) {
395 node_paths.push_back(cycle_begin);
400 cycle_begin = path[prev];
402 edge.RemoveFlow(flow);
403 }
while (cycle_begin != cycle_end);
417 Path *at_next_pos = path[next_id];
422 if (at_next_pos ==
nullptr) {
425 PathList &paths = this->
job[next_id].paths;
426 PathViaMap next_hops;
427 for (PathList::iterator i = paths.begin(); i != paths.end();) {
428 Path *new_child = *i;
429 uint new_flow = new_child->
GetFlow();
430 if (new_flow == 0)
break;
431 if (new_child->
GetOrigin() == origin_id) {
432 PathViaMap::iterator via_it = next_hops.find(new_child->
GetNode());
433 if (via_it == next_hops.end()) {
434 next_hops[new_child->
GetNode()] = new_child;
437 Path *child = via_it->second;
445 paths.push_back(new_child);
453 for (PathViaMap::iterator via_it = next_hops.begin();
454 via_it != next_hops.end(); ++via_it) {
455 Path *child = via_it->second;
459 path[next_id] = child;
490 bool cycles_found =
false;
491 uint16_t size = this->
job.
Size();
492 PathVector path(size,
nullptr);
493 for (NodeID node = 0; node < size; ++node) {
496 std::fill(path.begin(), path.end(), (
Path *)
nullptr);
512 std::vector<bool> finished_sources(size);
516 for (NodeID source = 0; source < size; ++source) {
517 if (finished_sources[source])
continue;
520 this->Dijkstra<DistanceAnnotation, GraphEdgeIterator>(source, paths);
523 bool source_demand_left =
false;
524 for (NodeID dest = 0; dest < size; ++dest) {
525 if (src_node.UnsatisfiedDemandTo(dest) > 0) {
526 Path *path = paths[dest];
527 assert(path !=
nullptr);
531 if (path->
GetFreeCapacity() > 0 && this->PushFlow(src_node, dest, path,
532 accuracy, this->max_saturation) > 0) {
535 more_loops = more_loops || (src_node.UnsatisfiedDemandTo(dest) > 0);
536 }
else if (src_node.UnsatisfiedDemandTo(dest) == src_node.DemandTo(dest) &&
538 this->
PushFlow(src_node, dest, path, accuracy, UINT_MAX);
540 if (src_node.UnsatisfiedDemandTo(dest) > 0) source_demand_left =
true;
543 finished_sources[source] = !source_demand_left;
560 bool demand_left =
true;
561 std::vector<bool> finished_sources(size);
564 for (NodeID source = 0; source < size; ++source) {
565 if (finished_sources[source])
continue;
567 this->Dijkstra<CapacityAnnotation, FlowEdgeIterator>(source, paths);
570 bool source_demand_left =
false;
571 for (NodeID dest = 0; dest < size; ++dest) {
572 Path *path = paths[dest];
573 if (src_node.UnsatisfiedDemandTo(dest) > 0 && path->
GetFreeCapacity() > INT_MIN) {
574 this->
PushFlow(src_node, dest, path, accuracy, UINT_MAX);
575 if (src_node.UnsatisfiedDemandTo(dest) > 0) {
577 source_demand_left =
true;
581 finished_sources[source] = !source_demand_left;
599bool Greater(T x_anno, T y_anno, NodeID x, NodeID y)
601 if (x_anno > y_anno)
return true;
602 if (x_anno < y_anno)
return false;
615 return x != y && Greater<int>(x->GetAnnotation(), y->GetAnnotation(),
616 x->GetNode(), y->GetNode());
628 return x != y && !Greater<uint>(x->GetAnnotation(), y->GetAnnotation(),
629 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 cap, 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.
Iterator class for getting edges from a FlowStatMap.
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.
Iterator class for getting the edges in the order of their next_edge members.
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.
const LinkGraphSettings & Settings() const
Get the link graph settings for this component.
CargoType Cargo() const
Get the cargo of the underlying link graph.
NodeID Size() const
Get the size of the underlying link graph.
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.
Multi-commodity flow calculating base class.
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.
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.
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.
uint8_t accuracy
accuracy when calculating things on the link graph. low accuracy => low running time
An edge in the link graph.
uint32_t TravelTime() const
Get edge's average travel time.
uint capacity
Capacity of the link.