00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "../stdafx.h"
00013 #include "../core/bitmath_func.hpp"
00014 #include "../core/pool_func.hpp"
00015 #include "../core/random_func.hpp"
00016 #include "../map_func.h"
00017 #include "../debug.h"
00018 #include "../window_func.h"
00019 #include "../window_gui.h"
00020 #include "linkgraph.h"
00021 #include "init.h"
00022 #include "demands.h"
00023 #include "mcf.h"
00024 #include "flowmapper.h"
00025
00026
00027 LinkGraphPool _link_graph_pool("LinkGraph");
00028 INSTANTIATE_POOL_METHODS(LinkGraph)
00029
00030
00031 LinkGraphJobPool _link_graph_job_pool("LinkGraphJob");
00032 INSTANTIATE_POOL_METHODS(LinkGraphJob)
00033
00034
00040 inline void Node::Init(StationID st, uint demand)
00041 {
00042 this->supply = 0;
00043 this->demand = demand;
00044 this->station = st;
00045 this->last_update = INVALID_DATE;
00046 }
00047
00052 inline void Edge::Init(uint distance)
00053 {
00054 this->distance = distance;
00055 this->capacity = 0;
00056 this->usage = 0;
00057 this->last_update = INVALID_DATE;
00058 this->next_edge = INVALID_NODE;
00059 }
00060
00061 void LinkGraph::Compress()
00062 {
00063 this->last_compression = (_date + this->last_compression) / 2;
00064 for (NodeID node1 = 0; node1 < this->num_nodes; ++node1) {
00065 this->nodes[node1].supply /= 2;
00066 for (NodeID node2 = 0; node2 < this->num_nodes; ++node2) {
00067 this->edges[node1][node2].capacity /= 2;
00068 this->edges[node1][node2].usage /= 2;
00069 }
00070 }
00071 }
00072
00077 void LinkGraph::Merge(LinkGraph *other)
00078 {
00079 Date age = _date - this->last_compression + 1;
00080 Date other_age = _date - other->last_compression + 1;
00081 NodeID first = this->num_nodes;
00082 for (NodeID node1 = 0; node1 < other->num_nodes; ++node1) {
00083 Station *st = Station::Get(other->nodes[node1].station);
00084 NodeID new_node = this->AddNode(st);
00085 this->nodes[new_node].supply = other->nodes[node1].supply * age / other_age;
00086 st->goods[this->cargo].link_graph = this->index;
00087 st->goods[this->cargo].node = new_node;
00088 for (NodeID node2 = 0; node2 < node1; ++node2) {
00089 Edge &forward = this->edges[new_node][first + node2];
00090 Edge &backward = this->edges[first + node2][new_node];
00091 forward = other->edges[node1][node2];
00092 backward = other->edges[node2][node1];
00093 forward.capacity = forward.capacity * age / other_age;
00094 forward.usage = forward.usage * age / other_age;
00095 if (forward.next_edge != INVALID_NODE) forward.next_edge += first;
00096 backward.capacity = backward.capacity * age / other_age;
00097 backward.usage = backward.usage * age / other_age;
00098 if (backward.next_edge != INVALID_NODE) backward.next_edge += first;
00099 }
00100 Edge &new_start = this->edges[new_node][new_node];
00101 new_start = other->edges[node1][node1];
00102 if (new_start.next_edge != INVALID_NODE) new_start.next_edge += first;
00103 }
00104 delete other;
00105 }
00106
00111 void LinkGraph::RemoveNode(NodeID id)
00112 {
00113 assert(id < this->num_nodes);
00114
00115 for (NodeID i = 0; i <= this->num_nodes; ++i) {
00116 this->RemoveEdge(i, id);
00117 NodeID prev = i;
00118 NodeID next = this->GetFirstEdge(i);
00119 while (next != INVALID_NODE) {
00120 if (next == this->num_nodes - 1) {
00121 this->edges[i][prev].next_edge = id;
00122 break;
00123 }
00124 }
00125 this->edges[i][id] = this->edges[i][this->num_nodes - 1];
00126 }
00127 --this->num_nodes;
00128 this->nodes.Erase(this->nodes.Get(id));
00129 this->edges.EraseColumn(id);
00130
00131
00132
00133 }
00134
00143 NodeID LinkGraph::AddNode(const Station *st)
00144 {
00145 const GoodsEntry &good = st->goods[this->cargo];
00146
00147 if (this->nodes.Length() == this->num_nodes) {
00148 this->nodes.Append();
00149
00150
00151 this->edges.Resize(this->num_nodes + 1,
00152 max(uint(this->num_nodes + 1), this->edges.Height()));
00153 }
00154
00155 this->nodes[this->num_nodes].Init(st->index,
00156 HasBit(good.acceptance_pickup, GoodsEntry::GES_ACCEPTANCE));
00157
00158 Edge *new_edges = this->edges[this->num_nodes];
00159
00160
00161 new_edges[this->num_nodes].next_edge = INVALID_NODE;
00162
00163 for (NodeID i = 0; i <= this->num_nodes; ++i) {
00164 uint distance = DistanceManhattan(st->xy, Station::Get(this->nodes[i].station)->xy);
00165 new_edges[i].Init(distance);
00166 this->edges[i][this->num_nodes].Init(distance);
00167 }
00168 return this->num_nodes++;
00169 }
00170
00177 inline void LinkGraph::AddEdge(NodeID from, NodeID to, uint capacity)
00178 {
00179 assert(from != to && from < this->num_nodes && to < this->num_nodes);
00180 Edge &edge = this->edges[from][to];
00181 Edge &first = this->edges[from][from];
00182 edge.capacity = capacity;
00183 edge.next_edge = first.next_edge;
00184 first.next_edge = to;
00185 edge.last_update = _date;
00186 }
00187
00188 void LinkGraph::RemoveEdge(NodeID from, NodeID to)
00189 {
00190 if (from == to) return;
00191 Edge &edge = this->edges[from][to];
00192 edge.capacity = 0;
00193 edge.last_update = INVALID_DATE;
00194 edge.usage = 0;
00195
00196 NodeID prev = from;
00197 NodeID next = this->GetFirstEdge(from);
00198 while (next != INVALID_NODE) {
00199 if (next == to) {
00200
00201 next = this->edges[from][prev].next_edge = edge.next_edge;
00202 break;
00203 } else {
00204 prev = next;
00205 next = this->edges[from][next].next_edge;
00206 }
00207 }
00208 }
00209
00218 void LinkGraph::UpdateEdge(NodeID from, NodeID to, uint capacity, uint usage)
00219 {
00220 Edge &edge = this->edges[from][to];
00221 if (edge.capacity == 0) {
00222 this->AddEdge(from, to, capacity);
00223 if (usage != UINT_MAX) edge.usage += usage;
00224 } else {
00225 if (usage == UINT_MAX) {
00226 edge.capacity = max(edge.capacity, capacity);
00227 } else {
00228 assert(capacity >= usage);
00229 edge.capacity += capacity;
00230 edge.usage += usage;
00231 }
00232 edge.last_update = _date;
00233 }
00234 }
00235
00245 void LinkGraph::SetSize()
00246 {
00247 if (this->nodes.Length() < this->num_nodes) {
00248 this->edges.Resize(this->num_nodes, this->num_nodes);
00249 this->nodes.Resize(this->num_nodes);
00250 }
00251
00252 for (uint i = 0; i < this->num_nodes; ++i) {
00253 this->nodes[i].Init();
00254 Edge *column = this->edges[i];
00255 for (uint j = 0; j < this->num_nodes; ++j) {
00256 column[j].Init();
00257 }
00258 }
00259 }
00260
00267 LinkGraphJob::LinkGraphJob(const LinkGraph &orig) :
00268
00269
00270 link_graph(orig),
00271 settings(_settings_game.linkgraph),
00272 thread(NULL),
00273 join_date(_date + _settings_game.linkgraph.recalc_time)
00274 {
00275 }
00276
00280 LinkGraphJob::~LinkGraphJob()
00281 {
00282 assert(this->thread == NULL);
00283 uint size = this->link_graph.GetSize();
00284 for (NodeID node_id = 0; node_id < size; ++node_id) {
00285 StationID &station = this->link_graph.GetNode(node_id).station;
00286 if (!Station::IsValidID(station)) {
00287
00288
00289 for (NodeID from_id = 0; from_id < size; ++from_id) {
00290 if (this->link_graph.GetEdge(from_id, node_id).capacity > 0) {
00291 FlowStatMap &flows = this->nodes[from_id].flows;
00292 for (FlowStatMap::iterator it(flows.begin()); it != flows.end(); ++it) {
00293 it->second.ChangeShare(station, INT_MIN);
00294 }
00295 }
00296 }
00297 station = INVALID_STATION;
00298 }
00299 }
00300 for (NodeID node_id = 0; node_id < size; ++node_id) {
00301 StationID station = this->link_graph.GetNode(node_id).station;
00302 if (station != INVALID_STATION) {
00303 InvalidateWindowData(WC_STATION_VIEW, station, this->link_graph.GetCargo());
00304 Station::Get(station)->goods[this->link_graph.GetCargo()].flows.
00305 swap(this->GetNode(node_id).flows);
00306 }
00307 }
00308 }
00309
00313 void LinkGraphSchedule::SpawnNext()
00314 {
00315 if (this->schedule.empty()) return;
00316 LinkGraph *next = this->schedule.front();
00317 assert(next == LinkGraph::Get(next->index));
00318 this->schedule.pop_front();
00319 if (LinkGraphJob::CanAllocateItem()) {
00320 LinkGraphJob *job = new LinkGraphJob(*next);
00321 job->SpawnThread();
00322 this->running.push_back(job);
00323 } else {
00324 DEBUG(misc, 0, "Can't allocate link graph job");
00325 }
00326 }
00327
00331 void LinkGraphSchedule::JoinNext()
00332 {
00333 if (this->running.empty()) return;
00334 LinkGraphJob *next = this->running.front();
00335 if (!next->IsFinished()) return;
00336 this->running.pop_front();
00337 LinkGraphID id = next->Graph().index;
00338 next->JoinThread();
00339 delete next;
00340 if (LinkGraph::IsValidID(id)) {
00341 LinkGraph *lg = LinkGraph::Get(id);
00342 this->Unqueue(lg);
00343 this->Queue(lg);
00344 }
00345 }
00346
00351 void LinkGraphSchedule::Run(void *j)
00352 {
00353 LinkGraphJob *job = (LinkGraphJob *)j;
00354 LinkGraphSchedule *schedule = LinkGraphSchedule::Instance();
00355 for (uint i = 0; i < lengthof(schedule->handlers); ++i) {
00356 schedule->handlers[i]->Run(job);
00357 }
00358 }
00359
00363 void LinkGraphJob::JoinThread()
00364 {
00365 if (this->thread != NULL) {
00366 this->thread->Join();
00367 delete this->thread;
00368 this->thread = NULL;
00369 }
00370 }
00371
00376 void LinkGraphJob::SpawnThread()
00377 {
00378 assert(this->thread == NULL);
00379 if (!ThreadObject::New(&(LinkGraphSchedule::Run), this, &(this->thread))) {
00380 this->thread = NULL;
00381
00382
00383
00384
00385
00386
00387
00388
00389 LinkGraphSchedule::Run(this);
00390 }
00391 }
00392
00397 void LinkGraphSchedule::SpawnAll()
00398 {
00399 for (JobList::iterator i = this->running.begin(); i != this->running.end(); ++i) {
00400 (*i)->SpawnThread();
00401 }
00402 }
00403
00407 void LinkGraphSchedule::Clear()
00408 {
00409 LinkGraphSchedule *inst = LinkGraphSchedule::Instance();
00410 for (JobList::iterator i(inst->running.begin()); i != inst->running.end(); ++i) {
00411 (*i)->JoinThread();
00412 }
00413 inst->running.clear();
00414 inst->schedule.clear();
00415 }
00416
00420 LinkGraphSchedule::LinkGraphSchedule()
00421 {
00422 this->handlers[0] = new InitHandler;
00423 this->handlers[1] = new DemandHandler;
00424 this->handlers[2] = new MCFHandler<MCF1stPass>;
00425 this->handlers[3] = new FlowMapper;
00426 this->handlers[4] = new MCFHandler<MCF2ndPass>;
00427 this->handlers[5] = new FlowMapper;
00428 }
00429
00433 LinkGraphSchedule::~LinkGraphSchedule()
00434 {
00435 this->Clear();
00436 for (uint i = 0; i < lengthof(this->handlers); ++i) {
00437 delete this->handlers[i];
00438 }
00439 }
00440
00444 LinkGraphSchedule *LinkGraphSchedule::Instance()
00445 {
00446 static LinkGraphSchedule inst;
00447 return &inst;
00448 }
00449
00453 void OnTick_LinkGraph()
00454 {
00455 if (_date_fract == LinkGraphSchedule::SPAWN_JOIN_TICK) {
00456 Date offset = _date % _settings_game.linkgraph.recalc_interval;
00457 if (offset == 0) {
00458 LinkGraphSchedule::Instance()->SpawnNext();
00459 } else if (offset == _settings_game.linkgraph.recalc_interval / 2) {
00460 LinkGraphSchedule::Instance()->JoinNext();
00461 }
00462 } else if (_date_fract == LinkGraph::COMPRESSION_TICK) {
00463 LinkGraph *lg;
00464
00465 int cutoff = RandomRange(256) + 256;
00466 FOR_ALL_LINK_GRAPHS(lg) {
00467 if (_date - lg->GetLastCompression() > cutoff) {
00468 lg->Compress();
00469 break;
00470 }
00471 }
00472 }
00473 }
00474
00483 void Path::Fork(Path *base, uint cap, int free_cap, uint dist)
00484 {
00485 this->capacity = min(base->capacity, cap);
00486 this->free_capacity = min(base->free_capacity, free_cap);
00487 this->distance = base->distance + dist;
00488 assert(this->distance > 0);
00489 if (this->parent != base) {
00490 this->Detach();
00491 this->parent = base;
00492 this->parent->num_children++;
00493 }
00494 this->origin = base->origin;
00495 }
00496
00505 uint Path::AddFlow(uint new_flow, LinkGraphJob *job, uint max_saturation)
00506 {
00507 if (this->parent != NULL) {
00508 EdgeAnnotation &edge = job->GetEdge(this->parent->node, this->node);
00509 if (max_saturation != UINT_MAX) {
00510 uint usable_cap = job->Graph().GetEdge(this->parent->node, this->node).capacity *
00511 max_saturation / 100;
00512 if (usable_cap > edge.flow) {
00513 new_flow = min(new_flow, usable_cap - edge.flow);
00514 } else {
00515 return 0;
00516 }
00517 }
00518 new_flow = this->parent->AddFlow(new_flow, job, max_saturation);
00519 if (new_flow > 0) {
00520 job->GetNode(this->parent->node).paths.insert(this);
00521 }
00522 edge.flow += new_flow;
00523 }
00524 this->flow += new_flow;
00525 return new_flow;
00526 }
00527
00533 Path::Path(NodeID n, bool source) :
00534 distance(source ? 0 : UINT_MAX),
00535 capacity(0),
00536 free_capacity(source ? INT_MAX : INT_MIN),
00537 flow(0), node(n), origin(source ? n : INVALID_NODE),
00538 num_children(0), parent(NULL)
00539 {}
00540