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;
356 assert(node.UnsatisfiedDemandTo(to) > 0);
357 uint flow =
Clamp(node.DemandTo(to) / accuracy, 1, node.UnsatisfiedDemandTo(to));
359 node.SatisfyDemandTo(to, flow);
371 uint flow = UINT_MAX;
372 const Path *cycle_end = cycle_begin;
374 flow = std::min(flow, cycle_begin->
GetFlow());
375 cycle_begin = path[cycle_begin->
GetNode()];
376 }
while (cycle_begin != cycle_end);
388 Path *cycle_end = cycle_begin;
390 NodeID prev = cycle_begin->
GetNode();
392 if (cycle_begin->
GetFlow() == 0) {
394 for (PathList::iterator i = node_paths.begin(); i != node_paths.end(); ++i) {
395 if (*i == cycle_begin) {
397 node_paths.push_back(cycle_begin);
402 cycle_begin = path[prev];
403 Edge &edge = this->
job[prev][cycle_begin->
GetNode()];
404 edge.RemoveFlow(flow);
405 }
while (cycle_begin != cycle_end);
419 Path *at_next_pos = path[next_id];
424 if (at_next_pos ==
nullptr) {
427 PathList &paths = this->
job[next_id].paths;
428 PathViaMap next_hops;
429 for (PathList::iterator i = paths.begin(); i != paths.end();) {
430 Path *new_child = *i;
431 uint new_flow = new_child->
GetFlow();
432 if (new_flow == 0)
break;
433 if (new_child->
GetOrigin() == origin_id) {
434 PathViaMap::iterator via_it = next_hops.find(new_child->
GetNode());
435 if (via_it == next_hops.end()) {
436 next_hops[new_child->
GetNode()] = new_child;
439 Path *child = via_it->second;
447 paths.push_back(new_child);
455 for (PathViaMap::iterator via_it = next_hops.begin();
456 via_it != next_hops.end(); ++via_it) {
457 Path *child = via_it->second;
461 path[next_id] = child;
492 bool cycles_found =
false;
493 uint16_t size = this->
job.Size();
494 PathVector path(size,
nullptr);
495 for (NodeID node = 0; node < size; ++node) {
498 std::fill(path.begin(), path.end(), (
Path *)
nullptr);
511 uint16_t size =
job.Size();
512 uint accuracy =
job.Settings().accuracy;
514 std::vector<bool> finished_sources(size);
518 for (NodeID source = 0; source < size; ++source) {
519 if (finished_sources[source])
continue;
524 Node &src_node =
job[source];
525 bool source_demand_left =
false;
526 for (NodeID dest = 0; dest < size; ++dest) {
527 if (src_node.UnsatisfiedDemandTo(dest) > 0) {
528 Path *path = paths[dest];
529 assert(path !=
nullptr);
533 if (path->
GetFreeCapacity() > 0 && this->PushFlow(src_node, dest, path,
534 accuracy, this->max_saturation) > 0) {
537 more_loops = more_loops || (src_node.UnsatisfiedDemandTo(dest) > 0);
538 }
else if (src_node.UnsatisfiedDemandTo(dest) == src_node.DemandTo(dest) &&
540 this->
PushFlow(src_node, dest, path, accuracy, UINT_MAX);
542 if (src_node.UnsatisfiedDemandTo(dest) > 0) source_demand_left =
true;
545 finished_sources[source] = !source_demand_left;
560 uint16_t size =
job.Size();
561 uint accuracy =
job.Settings().accuracy;
562 bool demand_left =
true;
563 std::vector<bool> finished_sources(size);
564 while (demand_left && !
job.IsJobAborted()) {
566 for (NodeID source = 0; source < size; ++source) {
567 if (finished_sources[source])
continue;
571 Node &src_node =
job[source];
572 bool source_demand_left =
false;
573 for (NodeID dest = 0; dest < size; ++dest) {
574 Path *path = paths[dest];
575 if (src_node.UnsatisfiedDemandTo(dest) > 0 && path->
GetFreeCapacity() > INT_MIN) {
576 this->
PushFlow(src_node, dest, path, accuracy, UINT_MAX);
577 if (src_node.UnsatisfiedDemandTo(dest) > 0) {
579 source_demand_left =
true;
583 finished_sources[source] = !source_demand_left;
602bool Greater(T x_anno, T y_anno, NodeID x, NodeID y)
604 if (x_anno > y_anno)
return true;
605 if (x_anno < y_anno)
return false;
618 return x != y &&
Greater<int>(x->GetAnnotation(), y->GetAnnotation(),
619 x->GetNode(), y->GetNode());
631 return x != y && !
Greater<uint>(x->GetAnnotation(), y->GetAnnotation(),
632 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.