Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "../stdafx.h"
00013 #include "../core/pool_func.hpp"
00014 #include "linkgraph.h"
00015
00016
00017 LinkGraphPool _link_graph_pool("LinkGraph");
00018 INSTANTIATE_POOL_METHODS(LinkGraph)
00019
00020
00025 inline void LinkGraph::BaseNode::Init(StationID st, uint demand)
00026 {
00027 this->supply = 0;
00028 this->demand = demand;
00029 this->station = st;
00030 this->last_update = INVALID_DATE;
00031 }
00032
00037 inline void LinkGraph::BaseEdge::Init(uint distance)
00038 {
00039 this->distance = distance;
00040 this->capacity = 0;
00041 this->usage = 0;
00042 this->last_unrestricted_update = INVALID_DATE;
00043 this->last_restricted_update = INVALID_DATE;
00044 this->next_edge = INVALID_NODE;
00045 }
00046
00052 void LinkGraph::ShiftDates(int interval)
00053 {
00054 this->last_compression += interval;
00055 for (NodeID node1 = 0; node1 < this->Size(); ++node1) {
00056 BaseNode &source = this->nodes[node1];
00057 if (source.last_update != INVALID_DATE) source.last_update += interval;
00058 for (NodeID node2 = 0; node2 < this->Size(); ++node2) {
00059 BaseEdge &edge = this->edges[node1][node2];
00060 if (edge.last_unrestricted_update != INVALID_DATE) edge.last_unrestricted_update += interval;
00061 if (edge.last_restricted_update != INVALID_DATE) edge.last_restricted_update += interval;
00062 }
00063 }
00064 }
00065
00066 void LinkGraph::Compress()
00067 {
00068 this->last_compression = (_date + this->last_compression) / 2;
00069 for (NodeID node1 = 0; node1 < this->Size(); ++node1) {
00070 this->nodes[node1].supply /= 2;
00071 for (NodeID node2 = 0; node2 < this->Size(); ++node2) {
00072 BaseEdge &edge = this->edges[node1][node2];
00073 if (edge.capacity > 0) {
00074 edge.capacity = max(1U, edge.capacity / 2);
00075 edge.usage /= 2;
00076 }
00077 }
00078 }
00079 }
00080
00085 void LinkGraph::Merge(LinkGraph *other)
00086 {
00087 Date age = _date - this->last_compression + 1;
00088 Date other_age = _date - other->last_compression + 1;
00089 NodeID first = this->Size();
00090 for (NodeID node1 = 0; node1 < other->Size(); ++node1) {
00091 Station *st = Station::Get(other->nodes[node1].station);
00092 NodeID new_node = this->AddNode(st);
00093 this->nodes[new_node].supply = LinkGraph::Scale(other->nodes[node1].supply, age, other_age);
00094 st->goods[this->cargo].link_graph = this->index;
00095 st->goods[this->cargo].node = new_node;
00096 for (NodeID node2 = 0; node2 < node1; ++node2) {
00097 BaseEdge &forward = this->edges[new_node][first + node2];
00098 BaseEdge &backward = this->edges[first + node2][new_node];
00099 forward = other->edges[node1][node2];
00100 backward = other->edges[node2][node1];
00101 forward.capacity = LinkGraph::Scale(forward.capacity, age, other_age);
00102 forward.usage = LinkGraph::Scale(forward.usage, age, other_age);
00103 if (forward.next_edge != INVALID_NODE) forward.next_edge += first;
00104 backward.capacity = LinkGraph::Scale(backward.capacity, age, other_age);
00105 backward.usage = LinkGraph::Scale(backward.usage, age, other_age);
00106 if (backward.next_edge != INVALID_NODE) backward.next_edge += first;
00107 }
00108 BaseEdge &new_start = this->edges[new_node][new_node];
00109 new_start = other->edges[node1][node1];
00110 if (new_start.next_edge != INVALID_NODE) new_start.next_edge += first;
00111 }
00112 delete other;
00113 }
00114
00119 void LinkGraph::RemoveNode(NodeID id)
00120 {
00121 assert(id < this->Size());
00122
00123 NodeID last_node = this->Size() - 1;
00124 for (NodeID i = 0; i <= last_node; ++i) {
00125 (*this)[i].RemoveEdge(id);
00126 BaseEdge *node_edges = this->edges[i];
00127 NodeID prev = i;
00128 NodeID next = node_edges[i].next_edge;
00129 while (next != INVALID_NODE) {
00130 if (next == last_node) {
00131 node_edges[prev].next_edge = id;
00132 break;
00133 }
00134 prev = next;
00135 next = node_edges[prev].next_edge;
00136 }
00137 node_edges[id] = node_edges[last_node];
00138 }
00139 Station::Get(this->nodes[last_node].station)->goods[this->cargo].node = id;
00140 this->nodes.Erase(this->nodes.Get(id));
00141 this->edges.EraseColumn(id);
00142
00143
00144
00145 }
00146
00152 void LinkGraph::UpdateDistances(NodeID id, TileIndex xy)
00153 {
00154 assert(id < this->Size());
00155 for (NodeID other = 0; other < this->Size(); ++other) {
00156 if (other == id) continue;
00157 this->edges[id][other].distance = this->edges[other][id].distance =
00158 DistanceMaxPlusManhattan(xy, Station::Get(this->nodes[other].station)->xy);
00159 }
00160 }
00161
00170 NodeID LinkGraph::AddNode(const Station *st)
00171 {
00172 const GoodsEntry &good = st->goods[this->cargo];
00173
00174 NodeID new_node = this->Size();
00175 this->nodes.Append();
00176
00177
00178 this->edges.Resize(new_node + 1U,
00179 max(new_node + 1U, this->edges.Height()));
00180
00181 this->nodes[new_node].Init(st->index,
00182 HasBit(good.acceptance_pickup, GoodsEntry::GES_ACCEPTANCE));
00183
00184 BaseEdge *new_edges = this->edges[new_node];
00185
00186
00187 new_edges[new_node].next_edge = INVALID_NODE;
00188
00189 for (NodeID i = 0; i <= new_node; ++i) {
00190 uint distance = DistanceMaxPlusManhattan(st->xy, Station::Get(this->nodes[i].station)->xy);
00191 new_edges[i].Init(distance);
00192 this->edges[i][new_node].Init(distance);
00193 }
00194 return new_node;
00195 }
00196
00204 void LinkGraph::Node::AddEdge(NodeID to, uint capacity, uint usage)
00205 {
00206 assert(this->index != to);
00207 BaseEdge &edge = this->edges[to];
00208 BaseEdge &first = this->edges[this->index];
00209 edge.capacity = capacity;
00210 edge.next_edge = first.next_edge;
00211 first.next_edge = to;
00212 switch (usage) {
00213 case REFRESH_UNRESTRICTED:
00214 edge.last_unrestricted_update = _date;
00215 break;
00216 case REFRESH_RESTRICTED:
00217 edge.last_restricted_update = _date;
00218 break;
00219 default:
00220 edge.usage = usage;
00221 break;
00222 }
00223 }
00224
00231 void LinkGraph::Node::UpdateEdge(NodeID to, uint capacity, uint usage)
00232 {
00233 assert(capacity > 0);
00234 assert(usage <= capacity || usage == REFRESH_RESTRICTED || usage == REFRESH_UNRESTRICTED);
00235 if (this->edges[to].capacity == 0) {
00236 this->AddEdge(to, capacity, usage);
00237 } else {
00238 (*this)[to].Update(capacity, usage);
00239 }
00240 }
00241
00246 void LinkGraph::Node::RemoveEdge(NodeID to)
00247 {
00248 if (this->index == to) return;
00249 BaseEdge &edge = this->edges[to];
00250 edge.capacity = 0;
00251 edge.last_unrestricted_update = INVALID_DATE;
00252 edge.last_restricted_update = INVALID_DATE;
00253 edge.usage = 0;
00254
00255 NodeID prev = this->index;
00256 NodeID next = this->edges[this->index].next_edge;
00257 while (next != INVALID_NODE) {
00258 if (next == to) {
00259
00260 this->edges[prev].next_edge = edge.next_edge;
00261 edge.next_edge = INVALID_NODE;
00262 break;
00263 } else {
00264 prev = next;
00265 next = this->edges[next].next_edge;
00266 }
00267 }
00268 }
00269
00279 void LinkGraph::Edge::Update(uint capacity, uint usage)
00280 {
00281 assert(this->edge.capacity > 0);
00282 if (usage > capacity) {
00283 this->edge.capacity = max(this->edge.capacity, capacity);
00284 switch (usage) {
00285 case REFRESH_UNRESTRICTED:
00286 this->edge.last_unrestricted_update = _date;
00287 break;
00288 case REFRESH_RESTRICTED:
00289 this->edge.last_restricted_update = _date;
00290 break;
00291 default:
00292 NOT_REACHED();
00293 break;
00294 }
00295 } else {
00296 this->edge.capacity += capacity;
00297 this->edge.usage += usage;
00298 }
00299 }
00300
00306 void LinkGraph::Init(uint size)
00307 {
00308 assert(this->Size() == 0);
00309 this->edges.Resize(size, size);
00310 this->nodes.Resize(size);
00311
00312 for (uint i = 0; i < size; ++i) {
00313 this->nodes[i].Init();
00314 BaseEdge *column = this->edges[i];
00315 for (uint j = 0; j < size; ++j) column[j].Init();
00316 }
00317 }