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_update = INVALID_DATE;
00043 this->next_edge = INVALID_NODE;
00044 }
00045
00046 void LinkGraph::Compress()
00047 {
00048 this->last_compression = (_date + this->last_compression) / 2;
00049 for (NodeID node1 = 0; node1 < this->Size(); ++node1) {
00050 this->nodes[node1].supply /= 2;
00051 for (NodeID node2 = 0; node2 < this->Size(); ++node2) {
00052 BaseEdge &edge = this->edges[node1][node2];
00053 if (edge.capacity > 0) {
00054 edge.capacity = max(1U, edge.capacity / 2);
00055 edge.usage /= 2;
00056 }
00057 }
00058 }
00059 }
00060
00065 void LinkGraph::Merge(LinkGraph *other)
00066 {
00067 Date age = _date - this->last_compression + 1;
00068 Date other_age = _date - other->last_compression + 1;
00069 NodeID first = this->Size();
00070 for (NodeID node1 = 0; node1 < other->Size(); ++node1) {
00071 Station *st = Station::Get(other->nodes[node1].station);
00072 NodeID new_node = this->AddNode(st);
00073 this->nodes[new_node].supply = LinkGraph::Scale(other->nodes[node1].supply, age, other_age);
00074 st->goods[this->cargo].link_graph = this->index;
00075 st->goods[this->cargo].node = new_node;
00076 for (NodeID node2 = 0; node2 < node1; ++node2) {
00077 BaseEdge &forward = this->edges[new_node][first + node2];
00078 BaseEdge &backward = this->edges[first + node2][new_node];
00079 forward = other->edges[node1][node2];
00080 backward = other->edges[node2][node1];
00081 forward.capacity = LinkGraph::Scale(forward.capacity, age, other_age);
00082 forward.usage = LinkGraph::Scale(forward.usage, age, other_age);
00083 if (forward.next_edge != INVALID_NODE) forward.next_edge += first;
00084 backward.capacity = LinkGraph::Scale(backward.capacity, age, other_age);
00085 backward.usage = LinkGraph::Scale(backward.usage, age, other_age);
00086 if (backward.next_edge != INVALID_NODE) backward.next_edge += first;
00087 }
00088 BaseEdge &new_start = this->edges[new_node][new_node];
00089 new_start = other->edges[node1][node1];
00090 if (new_start.next_edge != INVALID_NODE) new_start.next_edge += first;
00091 }
00092 delete other;
00093 }
00094
00099 void LinkGraph::RemoveNode(NodeID id)
00100 {
00101 assert(id < this->Size());
00102
00103 NodeID last_node = this->Size() - 1;
00104 for (NodeID i = 0; i <= last_node; ++i) {
00105 (*this)[i].RemoveEdge(id);
00106 BaseEdge *node_edges = this->edges[i];
00107 NodeID prev = i;
00108 NodeID next = node_edges[i].next_edge;
00109 while (next != INVALID_NODE) {
00110 if (next == last_node) {
00111 node_edges[prev].next_edge = id;
00112 break;
00113 }
00114 prev = next;
00115 next = node_edges[prev].next_edge;
00116 }
00117 node_edges[id] = node_edges[last_node];
00118 }
00119 Station::Get(this->nodes[last_node].station)->goods[this->cargo].node = id;
00120 this->nodes.Erase(this->nodes.Get(id));
00121 this->edges.EraseColumn(id);
00122
00123
00124
00125 }
00126
00135 NodeID LinkGraph::AddNode(const Station *st)
00136 {
00137 const GoodsEntry &good = st->goods[this->cargo];
00138
00139 NodeID new_node = this->Size();
00140 this->nodes.Append();
00141
00142
00143 this->edges.Resize(new_node + 1U,
00144 max(new_node + 1U, this->edges.Height()));
00145
00146 this->nodes[new_node].Init(st->index,
00147 HasBit(good.acceptance_pickup, GoodsEntry::GES_ACCEPTANCE));
00148
00149 BaseEdge *new_edges = this->edges[new_node];
00150
00151
00152 new_edges[new_node].next_edge = INVALID_NODE;
00153
00154 for (NodeID i = 0; i <= new_node; ++i) {
00155 uint distance = DistanceManhattan(st->xy, Station::Get(this->nodes[i].station)->xy);
00156 new_edges[i].Init(distance);
00157 this->edges[i][new_node].Init(distance);
00158 }
00159 return new_node;
00160 }
00161
00167 void LinkGraph::Node::AddEdge(NodeID to, uint capacity, uint usage)
00168 {
00169 assert(this->index != to);
00170 BaseEdge &edge = this->edges[to];
00171 BaseEdge &first = this->edges[this->index];
00172 edge.capacity = capacity;
00173 edge.usage = usage == UINT_MAX ? 0 : usage;
00174 edge.next_edge = first.next_edge;
00175 first.next_edge = to;
00176 edge.last_update = _date;
00177 }
00178
00179 void LinkGraph::Node::UpdateEdge(NodeID to, uint capacity, uint usage)
00180 {
00181 assert(capacity > 0);
00182 assert(usage <= capacity || usage == UINT_MAX);
00183 if (this->edges[to].last_update == INVALID_DATE) {
00184 this->AddEdge(to, capacity, usage);
00185 } else {
00186 (*this)[to].Update(capacity, usage);
00187 }
00188 }
00189
00194 void LinkGraph::Node::RemoveEdge(NodeID to)
00195 {
00196 if (this->index == to) return;
00197 BaseEdge &edge = this->edges[to];
00198 edge.capacity = 0;
00199 edge.last_update = INVALID_DATE;
00200 edge.usage = 0;
00201
00202 NodeID prev = this->index;
00203 NodeID next = this->edges[this->index].next_edge;
00204 while (next != INVALID_NODE) {
00205 if (next == to) {
00206
00207 next = this->edges[prev].next_edge = edge.next_edge;
00208 break;
00209 } else {
00210 prev = next;
00211 next = this->edges[next].next_edge;
00212 }
00213 }
00214 }
00215
00224 void LinkGraph::Edge::Update(uint capacity, uint usage)
00225 {
00226 assert(this->edge.capacity > 0);
00227 if (usage == UINT_MAX) {
00228 this->edge.capacity = max(this->edge.capacity, capacity);
00229 } else {
00230 assert(capacity >= usage);
00231 this->edge.capacity += capacity;
00232 this->edge.usage += usage;
00233 }
00234 this->edge.last_update = _date;
00235 }
00236
00242 void LinkGraph::Init(uint size)
00243 {
00244 assert(this->Size() == 0);
00245 this->edges.Resize(size, size);
00246 this->nodes.Resize(size);
00247
00248 for (uint i = 0; i < size; ++i) {
00249 this->nodes[i].Init();
00250 BaseEdge *column = this->edges[i];
00251 for (uint j = 0; j < size; ++j) column[j].Init();
00252 }
00253 }