mirror of https://github.com/OpenTTD/OpenTTD.git
Codechange: [Linkgraph] Drop node/edge wrappers from LinkGraphJob.
This commit is contained in:
parent
7352f812e6
commit
4d3da0cf14
|
@ -36,7 +36,7 @@ public:
|
|||
*/
|
||||
inline void AddNode(const Node &node)
|
||||
{
|
||||
this->supply_sum += node.Supply();
|
||||
this->supply_sum += node.base.supply;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -57,7 +57,7 @@ public:
|
|||
*/
|
||||
inline uint EffectiveSupply(const Node &from, const Node &to)
|
||||
{
|
||||
return std::max(from.Supply() * std::max(1U, to.Supply()) * this->mod_size / 100 / this->demand_per_node, 1U);
|
||||
return std::max(from.base.supply * std::max(1U, to.base.supply) * this->mod_size / 100 / this->demand_per_node, 1U);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -69,7 +69,7 @@ public:
|
|||
*/
|
||||
inline bool HasDemandLeft(const Node &to)
|
||||
{
|
||||
return (to.Supply() == 0 || to.UndeliveredSupply() > 0) && to.Demand() > 0;
|
||||
return (to.base.supply == 0 || to.undelivered_supply > 0) && to.base.demand > 0;
|
||||
}
|
||||
|
||||
void SetDemands(LinkGraphJob &job, NodeID from, NodeID to, uint demand_forw);
|
||||
|
@ -108,7 +108,7 @@ public:
|
|||
*/
|
||||
inline uint EffectiveSupply(const Node &from, const Node &)
|
||||
{
|
||||
return from.Supply();
|
||||
return from.base.supply;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -116,7 +116,7 @@ public:
|
|||
* nodes always accept as long as their demand > 0.
|
||||
* @param to The node to be checked.
|
||||
*/
|
||||
inline bool HasDemandLeft(const Node &to) { return to.Demand() > 0; }
|
||||
inline bool HasDemandLeft(const Node &to) { return to.base.demand > 0; }
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -129,9 +129,9 @@ public:
|
|||
*/
|
||||
void SymmetricScaler::SetDemands(LinkGraphJob &job, NodeID from_id, NodeID to_id, uint demand_forw)
|
||||
{
|
||||
if (job[from_id].Demand() > 0) {
|
||||
if (job[from_id].base.demand > 0) {
|
||||
uint demand_back = demand_forw * this->mod_size / 100;
|
||||
uint undelivered = job[to_id].UndeliveredSupply();
|
||||
uint undelivered = job[to_id].undelivered_supply;
|
||||
if (demand_back > undelivered) {
|
||||
demand_back = undelivered;
|
||||
demand_forw = std::max(1U, demand_back * 100 / this->mod_size);
|
||||
|
@ -170,11 +170,11 @@ void DemandCalculator::CalcDemand(LinkGraphJob &job, Tscaler scaler)
|
|||
|
||||
for (NodeID node = 0; node < job.Size(); node++) {
|
||||
scaler.AddNode(job[node]);
|
||||
if (job[node].Supply() > 0) {
|
||||
if (job[node].base.supply > 0) {
|
||||
supplies.push(node);
|
||||
num_supplies++;
|
||||
}
|
||||
if (job[node].Demand() > 0) {
|
||||
if (job[node].base.demand > 0) {
|
||||
demands.push(node);
|
||||
num_demands++;
|
||||
}
|
||||
|
@ -209,7 +209,7 @@ void DemandCalculator::CalcDemand(LinkGraphJob &job, Tscaler scaler)
|
|||
|
||||
/* Scale the distance by mod_dist around max_distance */
|
||||
int32 distance = this->max_distance - (this->max_distance -
|
||||
(int32)DistanceMaxPlusManhattan(job[from_id].XY(), job[to_id].XY())) *
|
||||
(int32)DistanceMaxPlusManhattan(job[from_id].base.xy, job[to_id].base.xy)) *
|
||||
this->mod_dist / 100;
|
||||
|
||||
/* Scale the accuracy by distance around accuracy / 2 */
|
||||
|
@ -230,7 +230,7 @@ void DemandCalculator::CalcDemand(LinkGraphJob &job, Tscaler scaler)
|
|||
demand_forw = 1;
|
||||
}
|
||||
|
||||
demand_forw = std::min(demand_forw, job[from_id].UndeliveredSupply());
|
||||
demand_forw = std::min(demand_forw, job[from_id].undelivered_supply);
|
||||
|
||||
scaler.SetDemands(job, from_id, to_id, demand_forw);
|
||||
|
||||
|
@ -240,10 +240,10 @@ void DemandCalculator::CalcDemand(LinkGraphJob &job, Tscaler scaler)
|
|||
num_demands--;
|
||||
}
|
||||
|
||||
if (job[from_id].UndeliveredSupply() == 0) break;
|
||||
if (job[from_id].undelivered_supply == 0) break;
|
||||
}
|
||||
|
||||
if (job[from_id].UndeliveredSupply() != 0) {
|
||||
if (job[from_id].undelivered_supply != 0) {
|
||||
supplies.push(from_id);
|
||||
} else {
|
||||
num_supplies--;
|
||||
|
|
|
@ -19,35 +19,33 @@
|
|||
void FlowMapper::Run(LinkGraphJob &job) const
|
||||
{
|
||||
for (NodeID node_id = 0; node_id < job.Size(); ++node_id) {
|
||||
Node prev_node = job[node_id];
|
||||
StationID prev = prev_node.Station();
|
||||
PathList &paths = prev_node.Paths();
|
||||
for (PathList::iterator i = paths.begin(); i != paths.end(); ++i) {
|
||||
Path *path = *i;
|
||||
Node &prev_node = job[node_id];
|
||||
StationID prev = prev_node.base.station;
|
||||
for (const Path *path : prev_node.paths) {
|
||||
uint flow = path->GetFlow();
|
||||
if (flow == 0) break;
|
||||
Node node = job[path->GetNode()];
|
||||
StationID via = node.Station();
|
||||
StationID origin = job[path->GetOrigin()].Station();
|
||||
Node &node = job[path->GetNode()];
|
||||
StationID via = node.base.station;
|
||||
StationID origin = job[path->GetOrigin()].base.station;
|
||||
assert(prev != via && via != origin);
|
||||
/* Mark all of the flow for local consumption at "first". */
|
||||
node.Flows().AddFlow(origin, via, flow);
|
||||
node.flows.AddFlow(origin, via, flow);
|
||||
if (prev != origin) {
|
||||
/* Pass some of the flow marked for local consumption at "prev" on
|
||||
* to this node. */
|
||||
prev_node.Flows().PassOnFlow(origin, via, flow);
|
||||
prev_node.flows.PassOnFlow(origin, via, flow);
|
||||
} else {
|
||||
/* Prev node is origin. Simply add flow. */
|
||||
prev_node.Flows().AddFlow(origin, via, flow);
|
||||
prev_node.flows.AddFlow(origin, via, flow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (NodeID node_id = 0; node_id < job.Size(); ++node_id) {
|
||||
/* Remove local consumption shares marked as invalid. */
|
||||
Node node = job[node_id];
|
||||
FlowStatMap &flows = node.Flows();
|
||||
flows.FinalizeLocalConsumption(node.Station());
|
||||
Node &node = job[node_id];
|
||||
FlowStatMap &flows = node.flows;
|
||||
flows.FinalizeLocalConsumption(node.base.station);
|
||||
if (this->scale) {
|
||||
/* Scale by time the graph has been running without being compressed. Add 1 to avoid
|
||||
* division by 0 if spawn date == last compression date. This matches
|
||||
|
@ -58,10 +56,7 @@ void FlowMapper::Run(LinkGraphJob &job) const
|
|||
}
|
||||
}
|
||||
/* Clear paths. */
|
||||
PathList &paths = node.Paths();
|
||||
for (PathList::iterator i = paths.begin(); i != paths.end(); ++i) {
|
||||
delete *i;
|
||||
}
|
||||
paths.clear();
|
||||
for (Path *i : node.paths) delete i;
|
||||
node.paths.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,12 @@ public:
|
|||
|
||||
BaseEdge(NodeID dest_node = INVALID_NODE);
|
||||
|
||||
/**
|
||||
* Get edge's average travel time.
|
||||
* @return Travel time, in ticks.
|
||||
*/
|
||||
uint32 TravelTime() const { return this->travel_time_sum / this->capacity; }
|
||||
|
||||
/** Comparison operator based on \c dest_node. */
|
||||
bool operator <(const BaseEdge &rhs) const
|
||||
{
|
||||
|
@ -117,7 +123,7 @@ public:
|
|||
* Get edge's average travel time.
|
||||
* @return Travel time, in ticks.
|
||||
*/
|
||||
uint32 TravelTime() const { return this->edge.travel_time_sum / this->edge.capacity; }
|
||||
uint32 TravelTime() const { return this->edge.TravelTime(); }
|
||||
|
||||
/**
|
||||
* Get the date of the last update to the edge's unrestricted capacity.
|
||||
|
|
|
@ -50,7 +50,7 @@ LinkGraphJob::LinkGraphJob(const LinkGraph &orig) :
|
|||
void LinkGraphJob::EraseFlows(NodeID from)
|
||||
{
|
||||
for (NodeID node_id = 0; node_id < this->Size(); ++node_id) {
|
||||
(*this)[node_id].Flows().erase(from);
|
||||
(*this)[node_id].flows.erase(from);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,10 +103,10 @@ LinkGraphJob::~LinkGraphJob()
|
|||
|
||||
uint16 size = this->Size();
|
||||
for (NodeID node_id = 0; node_id < size; ++node_id) {
|
||||
Node from = (*this)[node_id];
|
||||
NodeAnnotation &from = this->nodes[node_id];
|
||||
|
||||
/* The station can have been deleted. Remove all flows originating from it then. */
|
||||
Station *st = Station::GetIfValid(from.Station());
|
||||
Station *st = Station::GetIfValid(from.base.station);
|
||||
if (st == nullptr) {
|
||||
this->EraseFlows(node_id);
|
||||
continue;
|
||||
|
@ -121,23 +121,24 @@ LinkGraphJob::~LinkGraphJob()
|
|||
}
|
||||
|
||||
LinkGraph *lg = LinkGraph::Get(ge.link_graph);
|
||||
FlowStatMap &flows = from.Flows();
|
||||
FlowStatMap &flows = from.flows;
|
||||
|
||||
for (EdgeIterator it(from.Begin()); it != from.End(); ++it) {
|
||||
if (it->second.Flow() == 0) continue;
|
||||
StationID to = (*this)[it->first].Station();
|
||||
for (const auto &edge : from.edges) {
|
||||
if (edge.Flow() == 0) continue;
|
||||
NodeID dest_id = edge.base.dest_node;
|
||||
StationID to = this->nodes[dest_id].base.station;
|
||||
Station *st2 = Station::GetIfValid(to);
|
||||
if (st2 == nullptr || st2->goods[this->Cargo()].link_graph != this->link_graph.index ||
|
||||
st2->goods[this->Cargo()].node != it->first ||
|
||||
!(*lg)[node_id].HasEdgeTo(it->first) ||
|
||||
(*lg)[node_id][it->first].LastUpdate() == INVALID_DATE) {
|
||||
st2->goods[this->Cargo()].node != dest_id ||
|
||||
!(*lg)[node_id].HasEdgeTo(dest_id) ||
|
||||
(*lg)[node_id][dest_id].LastUpdate() == INVALID_DATE) {
|
||||
/* Edge has been removed. Delete flows. */
|
||||
StationIDStack erased = flows.DeleteFlows(to);
|
||||
/* Delete old flows for source stations which have been deleted
|
||||
* from the new flows. This avoids flow cycles between old and
|
||||
* new flows. */
|
||||
while (!erased.IsEmpty()) ge.flows.erase(erased.Pop());
|
||||
} else if ((*lg)[node_id][it->first].LastUnrestrictedUpdate() == INVALID_DATE) {
|
||||
} else if ((*lg)[node_id][dest_id].LastUnrestrictedUpdate() == INVALID_DATE) {
|
||||
/* Edge is fully restricted. */
|
||||
flows.RestrictFlows(to);
|
||||
}
|
||||
|
@ -220,9 +221,9 @@ void Path::Fork(Path *base, uint cap, int free_cap, uint dist)
|
|||
uint Path::AddFlow(uint new_flow, LinkGraphJob &job, uint max_saturation)
|
||||
{
|
||||
if (this->parent != nullptr) {
|
||||
LinkGraphJob::Edge edge = job[this->parent->node][this->node];
|
||||
LinkGraphJob::EdgeAnnotation edge = job[this->parent->node][this->node];
|
||||
if (max_saturation != UINT_MAX) {
|
||||
uint usable_cap = edge.Capacity() * max_saturation / 100;
|
||||
uint usable_cap = edge.base.capacity * max_saturation / 100;
|
||||
if (usable_cap > edge.Flow()) {
|
||||
new_flow = std::min(new_flow, usable_cap - edge.Flow());
|
||||
} else {
|
||||
|
@ -231,7 +232,7 @@ uint Path::AddFlow(uint new_flow, LinkGraphJob &job, uint max_saturation)
|
|||
}
|
||||
new_flow = this->parent->AddFlow(new_flow, job, max_saturation);
|
||||
if (this->flow == 0 && new_flow > 0) {
|
||||
job[this->parent->node].Paths().push_front(this);
|
||||
job[this->parent->node].paths.push_front(this);
|
||||
}
|
||||
edge.AddFlow(new_flow);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ extern LinkGraphJobPool _link_graph_job_pool;
|
|||
* Class for calculation jobs to be run on link graphs.
|
||||
*/
|
||||
class LinkGraphJob : public LinkGraphJobPool::PoolItem<&_link_graph_job_pool>{
|
||||
private:
|
||||
public:
|
||||
/**
|
||||
* Demand between two nodes.
|
||||
*/
|
||||
|
@ -41,13 +41,46 @@ private:
|
|||
* Annotation for a link graph edge.
|
||||
*/
|
||||
struct EdgeAnnotation {
|
||||
const LinkGraph::BaseEdge &base; ///< Reference to the edge that is annotated.
|
||||
|
||||
uint flow; ///< Planned flow over this edge.
|
||||
|
||||
EdgeAnnotation(const LinkGraph::BaseEdge &base) : base(base), flow(0) {}
|
||||
|
||||
/**
|
||||
* Get the total flow on the edge.
|
||||
* @return Flow.
|
||||
*/
|
||||
uint Flow() const { return this->flow; }
|
||||
|
||||
/**
|
||||
* Add some flow.
|
||||
* @param flow Flow to be added.
|
||||
*/
|
||||
void AddFlow(uint flow) { this->flow += flow; }
|
||||
|
||||
/**
|
||||
* Remove some flow.
|
||||
* @param flow Flow to be removed.
|
||||
*/
|
||||
void RemoveFlow(uint flow)
|
||||
{
|
||||
assert(flow <= this->flow);
|
||||
this->flow -= flow;
|
||||
}
|
||||
|
||||
friend inline bool operator <(NodeID dest, const EdgeAnnotation &rhs)
|
||||
{
|
||||
return dest < rhs.base.dest_node;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Annotation for a link graph node.
|
||||
*/
|
||||
struct NodeAnnotation {
|
||||
const LinkGraph::BaseNode &base; ///< Reference to the node that is annotated.
|
||||
|
||||
uint undelivered_supply; ///< Amount of supply that hasn't been distributed yet.
|
||||
PathList paths; ///< Paths through this node, sorted so that those with flow == 0 are in the back.
|
||||
FlowStatMap flows; ///< Planned flows to other nodes.
|
||||
|
@ -55,13 +88,73 @@ private:
|
|||
std::vector<EdgeAnnotation> edges; ///< Annotations for all edges originating at this node.
|
||||
std::vector<DemandAnnotation> demands; ///< Annotations for the demand to all other nodes.
|
||||
|
||||
NodeAnnotation(const LinkGraph::BaseNode &node, size_t size) : undelivered_supply(node.supply), paths(), flows()
|
||||
NodeAnnotation(const LinkGraph::BaseNode &node, size_t size) : base(node), undelivered_supply(node.supply), paths(), flows()
|
||||
{
|
||||
this->edges.resize(node.edges.size());
|
||||
this->edges.reserve(node.edges.size());
|
||||
for (auto &e : node.edges) this->edges.emplace_back(e);
|
||||
this->demands.resize(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an edge starting at this node.
|
||||
* @param to Remote end of the edge.
|
||||
* @return Edge between this node and "to".
|
||||
*/
|
||||
EdgeAnnotation &operator[](NodeID to)
|
||||
{
|
||||
auto it = std::find_if(this->edges.begin(), this->edges.end(), [=] (const EdgeAnnotation &e) { return e.base.dest_node == to; });
|
||||
assert(it != this->edges.end());
|
||||
return *it;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve an edge starting at this node.
|
||||
* @param to Remote end of the edge.
|
||||
* @return Edge between this node and "to".
|
||||
*/
|
||||
const EdgeAnnotation &operator[](NodeID to) const
|
||||
{
|
||||
auto it = std::find_if(this->edges.begin(), this->edges.end(), [=] (const EdgeAnnotation &e) { return e.base.dest_node == to; });
|
||||
assert(it != this->edges.end());
|
||||
return *it;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the transport demand between end the points of the edge.
|
||||
* @return Demand.
|
||||
*/
|
||||
uint DemandTo(NodeID to) const { return this->demands[to].demand; }
|
||||
|
||||
/**
|
||||
* Get the transport demand that hasn't been satisfied by flows, yet.
|
||||
* @return Unsatisfied demand.
|
||||
*/
|
||||
uint UnsatisfiedDemandTo(NodeID to) const { return this->demands[to].unsatisfied_demand; }
|
||||
|
||||
/**
|
||||
* Satisfy some demand.
|
||||
* @param demand Demand to be satisfied.
|
||||
*/
|
||||
void SatisfyDemandTo(NodeID to, uint demand)
|
||||
{
|
||||
assert(demand <= this->demands[to].unsatisfied_demand);
|
||||
this->demands[to].unsatisfied_demand -= demand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deliver some supply, adding demand to the respective edge.
|
||||
* @param to Destination for supply.
|
||||
* @param amount Amount of supply to be delivered.
|
||||
*/
|
||||
void DeliverSupply(NodeID to, uint amount)
|
||||
{
|
||||
this->undelivered_supply -= amount;
|
||||
this->demands[to].demand += amount;
|
||||
this->demands[to].unsatisfied_demand += amount;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
typedef std::vector<NodeAnnotation> NodeAnnotationVector;
|
||||
|
||||
friend SaveLoadTable GetLinkGraphJobDesc();
|
||||
|
@ -81,199 +174,6 @@ protected:
|
|||
void SpawnThread();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* A job edge. Wraps a link graph edge and an edge annotation. The
|
||||
* annotation can be modified, the edge is constant.
|
||||
*/
|
||||
class Edge : public LinkGraph::ConstEdge {
|
||||
private:
|
||||
EdgeAnnotation &anno; ///< Annotation being wrapped.
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param edge Link graph edge to be wrapped.
|
||||
* @param anno Annotation to be wrapped.
|
||||
*/
|
||||
Edge(const LinkGraph::BaseEdge &edge, EdgeAnnotation &anno) :
|
||||
LinkGraph::ConstEdge(edge), anno(anno) {}
|
||||
|
||||
/**
|
||||
* Get the total flow on the edge.
|
||||
* @return Flow.
|
||||
*/
|
||||
uint Flow() const { return this->anno.flow; }
|
||||
|
||||
/**
|
||||
* Add some flow.
|
||||
* @param flow Flow to be added.
|
||||
*/
|
||||
void AddFlow(uint flow) { this->anno.flow += flow; }
|
||||
|
||||
/**
|
||||
* Remove some flow.
|
||||
* @param flow Flow to be removed.
|
||||
*/
|
||||
void RemoveFlow(uint flow)
|
||||
{
|
||||
assert(flow <= this->anno.flow);
|
||||
this->anno.flow -= flow;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Iterator for job edges.
|
||||
*/
|
||||
class EdgeIterator : public LinkGraph::BaseEdgeIterator<const LinkGraph::BaseEdge, Edge, EdgeIterator> {
|
||||
span<EdgeAnnotation> base_anno; ///< Array of annotations to be (indirectly) iterated.
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param base Array of edges to be iterated.
|
||||
* @param base_anno Array of annotations to be iterated.
|
||||
* @param current Start offset of iteration.
|
||||
*/
|
||||
EdgeIterator(span<const LinkGraph::BaseEdge> base, span<EdgeAnnotation> base_anno, bool end) :
|
||||
LinkGraph::BaseEdgeIterator<const LinkGraph::BaseEdge, Edge, EdgeIterator>(base, end),
|
||||
base_anno(base_anno) {}
|
||||
|
||||
EdgeIterator() :
|
||||
LinkGraph::BaseEdgeIterator<const LinkGraph::BaseEdge, Edge, EdgeIterator>(span<const LinkGraph::BaseEdge>(), true),
|
||||
base_anno() {}
|
||||
|
||||
/**
|
||||
* Dereference.
|
||||
* @return Pair of the edge currently pointed to and the ID of its
|
||||
* other end.
|
||||
*/
|
||||
std::pair<NodeID, Edge> operator*() const
|
||||
{
|
||||
return std::pair<NodeID, Edge>(this->base[this->current].dest_node, Edge(this->base[this->current], this->base_anno[this->current]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Dereference. Has to be repeated here as operator* is different than
|
||||
* in LinkGraph::EdgeWrapper.
|
||||
* @return Fake pointer to pair of NodeID/Edge.
|
||||
*/
|
||||
FakePointer operator->() const {
|
||||
return FakePointer(this->operator*());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Link graph job node. Wraps a constant link graph node and a modifiable
|
||||
* node annotation.
|
||||
*/
|
||||
class Node : public LinkGraph::ConstNode {
|
||||
private:
|
||||
NodeAnnotation &node_anno; ///< Annotation being wrapped.
|
||||
span<EdgeAnnotation> edge_annos; ///< Edge annotations belonging to this node.
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param lgj Job to take the node from.
|
||||
* @param node ID of the node.
|
||||
*/
|
||||
Node (LinkGraphJob *lgj, NodeID node) :
|
||||
LinkGraph::ConstNode(&lgj->link_graph, node),
|
||||
node_anno(lgj->nodes[node]), edge_annos(lgj->nodes[node].edges)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Retrieve an edge starting at this node. Mind that this returns an
|
||||
* object, not a reference.
|
||||
* @param to Remote end of the edge.
|
||||
* @return Edge between this node and "to".
|
||||
*/
|
||||
Edge operator[](NodeID to) const
|
||||
{
|
||||
assert(this->HasEdgeTo(to));
|
||||
auto index = std::distance(this->node.edges.begin(), this->GetEdge(to));
|
||||
return Edge(this->node.edges[index], this->edge_annos[index]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator for the "begin" of the edge array. Only edges with capacity
|
||||
* are iterated. The others are skipped.
|
||||
* @return Iterator pointing to the first edge.
|
||||
*/
|
||||
EdgeIterator Begin() const { return EdgeIterator(this->node.edges, this->edge_annos, false); }
|
||||
|
||||
/**
|
||||
* Iterator for the "end" of the edge array. Only edges with capacity
|
||||
* are iterated. The others are skipped.
|
||||
* @return Iterator pointing beyond the last edge.
|
||||
*/
|
||||
EdgeIterator End() const { return EdgeIterator(this->node.edges, this->edge_annos, true); }
|
||||
|
||||
/**
|
||||
* Get amount of supply that hasn't been delivered, yet.
|
||||
* @return Undelivered supply.
|
||||
*/
|
||||
uint UndeliveredSupply() const { return this->node_anno.undelivered_supply; }
|
||||
|
||||
/**
|
||||
* Get the flows running through this node.
|
||||
* @return Flows.
|
||||
*/
|
||||
FlowStatMap &Flows() { return this->node_anno.flows; }
|
||||
|
||||
/**
|
||||
* Get a constant version of the flows running through this node.
|
||||
* @return Flows.
|
||||
*/
|
||||
const FlowStatMap &Flows() const { return this->node_anno.flows; }
|
||||
|
||||
/**
|
||||
* Get the paths this node is part of. Paths are always expected to be
|
||||
* sorted so that those with flow == 0 are in the back of the list.
|
||||
* @return Paths.
|
||||
*/
|
||||
PathList &Paths() { return this->node_anno.paths; }
|
||||
|
||||
/**
|
||||
* Get a constant version of the paths this node is part of.
|
||||
* @return Paths.
|
||||
*/
|
||||
const PathList &Paths() const { return this->node_anno.paths; }
|
||||
|
||||
/**
|
||||
* Get the transport demand between end the points of the edge.
|
||||
* @return Demand.
|
||||
*/
|
||||
uint DemandTo(NodeID to) const { return this->node_anno.demands[to].demand; }
|
||||
|
||||
/**
|
||||
* Get the transport demand that hasn't been satisfied by flows, yet.
|
||||
* @return Unsatisfied demand.
|
||||
*/
|
||||
uint UnsatisfiedDemandTo(NodeID to) const { return this->node_anno.demands[to].unsatisfied_demand; }
|
||||
|
||||
/**
|
||||
* Satisfy some demand.
|
||||
* @param demand Demand to be satisfied.
|
||||
*/
|
||||
void SatisfyDemandTo(NodeID to, uint demand)
|
||||
{
|
||||
assert(demand <= this->node_anno.demands[to].unsatisfied_demand);
|
||||
this->node_anno.demands[to].unsatisfied_demand -= demand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deliver some supply, adding demand to the respective edge.
|
||||
* @param to Destination for supply.
|
||||
* @param amount Amount of supply to be delivered.
|
||||
*/
|
||||
void DeliverSupply(NodeID to, uint amount)
|
||||
{
|
||||
this->node_anno.undelivered_supply -= amount;
|
||||
this->node_anno.demands[to].demand += amount;
|
||||
this->node_anno.demands[to].unsatisfied_demand += amount;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Bare constructor, only for save/load. link_graph, join_date and actually
|
||||
* settings have to be brutally const-casted in order to populate them.
|
||||
|
@ -337,7 +237,7 @@ public:
|
|||
* @param num ID of the node.
|
||||
* @return the Requested node.
|
||||
*/
|
||||
inline Node operator[](NodeID num) { return Node(this, num); }
|
||||
inline NodeAnnotation &operator[](NodeID num) { return this->nodes[num]; }
|
||||
|
||||
/**
|
||||
* Get the size of the underlying link graph.
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
#include "linkgraphjob.h"
|
||||
#include "linkgraphschedule.h"
|
||||
|
||||
typedef LinkGraphJob::Node Node;
|
||||
typedef LinkGraphJob::Edge Edge;
|
||||
typedef LinkGraphJob::EdgeIterator EdgeIterator;
|
||||
typedef LinkGraphJob::NodeAnnotation Node;
|
||||
typedef LinkGraphJob::EdgeAnnotation Edge;
|
||||
|
||||
#endif /* LINKGRAPHJOB_BASE_H */
|
||||
|
|
|
@ -94,8 +94,9 @@ public:
|
|||
class GraphEdgeIterator {
|
||||
private:
|
||||
LinkGraphJob &job; ///< Job being executed
|
||||
EdgeIterator i; ///< Iterator pointing to current edge.
|
||||
EdgeIterator end; ///< Iterator pointing beyond last edge.
|
||||
|
||||
std::vector<LinkGraphJob::EdgeAnnotation>::const_iterator i; ///< Iterator pointing to current edge.
|
||||
std::vector<LinkGraphJob::EdgeAnnotation>::const_iterator end; ///< Iterator pointing beyond last edge.
|
||||
|
||||
public:
|
||||
|
||||
|
@ -112,8 +113,8 @@ public:
|
|||
*/
|
||||
void SetNode(NodeID source, NodeID node)
|
||||
{
|
||||
this->i = this->job[node].Begin();
|
||||
this->end = this->job[node].End();
|
||||
this->i = this->job[node].edges.cbegin();
|
||||
this->end = this->job[node].edges.cend();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -122,7 +123,7 @@ public:
|
|||
*/
|
||||
NodeID Next()
|
||||
{
|
||||
return this->i != this->end ? (this->i++)->first : INVALID_NODE;
|
||||
return this->i != this->end ? (this->i++)->base.dest_node : INVALID_NODE;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -150,7 +151,7 @@ public:
|
|||
FlowEdgeIterator(LinkGraphJob &job) : job(job)
|
||||
{
|
||||
for (NodeID i = 0; i < job.Size(); ++i) {
|
||||
StationID st = job[i].Station();
|
||||
StationID st = job[i].base.station;
|
||||
if (st >= this->station_to_node.size()) {
|
||||
this->station_to_node.resize(st + 1);
|
||||
}
|
||||
|
@ -165,8 +166,8 @@ public:
|
|||
*/
|
||||
void SetNode(NodeID source, NodeID node)
|
||||
{
|
||||
const FlowStatMap &flows = this->job[node].Flows();
|
||||
FlowStatMap::const_iterator it = flows.find(this->job[source].Station());
|
||||
const FlowStatMap &flows = this->job[node].flows;
|
||||
FlowStatMap::const_iterator it = flows.find(this->job[source].base.station);
|
||||
if (it != flows.end()) {
|
||||
this->it = it->second.GetShares()->begin();
|
||||
this->end = it->second.GetShares()->end();
|
||||
|
@ -275,8 +276,8 @@ void MultiCommodityFlow::Dijkstra(NodeID source_node, PathVector &paths)
|
|||
iter.SetNode(source_node, from);
|
||||
for (NodeID to = iter.Next(); to != INVALID_NODE; to = iter.Next()) {
|
||||
if (to == from) continue; // Not a real edge but a consumption sign.
|
||||
Edge edge = this->job[from][to];
|
||||
uint capacity = edge.Capacity();
|
||||
const Edge &edge = this->job[from][to];
|
||||
uint capacity = edge.base.capacity;
|
||||
if (this->max_saturation != UINT_MAX) {
|
||||
capacity *= this->max_saturation;
|
||||
capacity /= 100;
|
||||
|
@ -288,9 +289,9 @@ void MultiCommodityFlow::Dijkstra(NodeID source_node, PathVector &paths)
|
|||
bool express = IsCargoInClass(this->job.Cargo(), CC_PASSENGERS) ||
|
||||
IsCargoInClass(this->job.Cargo(), CC_MAIL) ||
|
||||
IsCargoInClass(this->job.Cargo(), CC_EXPRESS);
|
||||
uint distance = DistanceMaxPlusManhattan(this->job[from].XY(), this->job[to].XY()) + 1;
|
||||
uint distance = DistanceMaxPlusManhattan(this->job[from].base.xy, this->job[to].base.xy) + 1;
|
||||
/* Compute a default travel time from the distance and an average speed of 1 tile/day. */
|
||||
uint time = (edge.TravelTime() != 0) ? edge.TravelTime() + DAY_TICKS : distance * DAY_TICKS;
|
||||
uint time = (edge.base.TravelTime() != 0) ? edge.base.TravelTime() + DAY_TICKS : distance * DAY_TICKS;
|
||||
uint distance_anno = express ? time : distance;
|
||||
|
||||
Tannotation *dest = static_cast<Tannotation *>(paths[to]);
|
||||
|
@ -381,7 +382,7 @@ void MCF1stPass::EliminateCycle(PathVector &path, Path *cycle_begin, uint flow)
|
|||
NodeID prev = cycle_begin->GetNode();
|
||||
cycle_begin->ReduceFlow(flow);
|
||||
if (cycle_begin->GetFlow() == 0) {
|
||||
PathList &node_paths = this->job[cycle_begin->GetParent()->GetNode()].Paths();
|
||||
PathList &node_paths = this->job[cycle_begin->GetParent()->GetNode()].paths;
|
||||
for (PathList::iterator i = node_paths.begin(); i != node_paths.end(); ++i) {
|
||||
if (*i == cycle_begin) {
|
||||
node_paths.erase(i);
|
||||
|
@ -391,7 +392,7 @@ void MCF1stPass::EliminateCycle(PathVector &path, Path *cycle_begin, uint flow)
|
|||
}
|
||||
}
|
||||
cycle_begin = path[prev];
|
||||
Edge edge = this->job[prev][cycle_begin->GetNode()];
|
||||
Edge &edge = this->job[prev][cycle_begin->GetNode()];
|
||||
edge.RemoveFlow(flow);
|
||||
} while (cycle_begin != cycle_end);
|
||||
}
|
||||
|
@ -415,7 +416,7 @@ bool MCF1stPass::EliminateCycles(PathVector &path, NodeID origin_id, NodeID next
|
|||
if (at_next_pos == nullptr) {
|
||||
/* Summarize paths; add up the paths with the same source and next hop
|
||||
* in one path each. */
|
||||
PathList &paths = this->job[next_id].Paths();
|
||||
PathList &paths = this->job[next_id].paths;
|
||||
PathViaMap next_hops;
|
||||
for (PathList::iterator i = paths.begin(); i != paths.end();) {
|
||||
Path *new_child = *i;
|
||||
|
@ -512,7 +513,7 @@ MCF1stPass::MCF1stPass(LinkGraphJob &job) : MultiCommodityFlow(job)
|
|||
/* First saturate the shortest paths. */
|
||||
this->Dijkstra<DistanceAnnotation, GraphEdgeIterator>(source, paths);
|
||||
|
||||
Node src_node = job[source];
|
||||
Node &src_node = job[source];
|
||||
bool source_demand_left = false;
|
||||
for (NodeID dest = 0; dest < size; ++dest) {
|
||||
if (src_node.UnsatisfiedDemandTo(dest) > 0) {
|
||||
|
@ -559,7 +560,7 @@ MCF2ndPass::MCF2ndPass(LinkGraphJob &job) : MultiCommodityFlow(job)
|
|||
|
||||
this->Dijkstra<CapacityAnnotation, FlowEdgeIterator>(source, paths);
|
||||
|
||||
Node src_node = job[source];
|
||||
Node &src_node = job[source];
|
||||
bool source_demand_left = false;
|
||||
for (NodeID dest = 0; dest < size; ++dest) {
|
||||
Path *path = paths[dest];
|
||||
|
|
Loading…
Reference in New Issue