00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "../stdafx.h"
00013 #include "../map_func.h"
00014 #include "../core/bitmath_func.hpp"
00015 #include "../debug.h"
00016 #include "../window_func.h"
00017 #include "../window_gui.h"
00018 #include "../moving_average.h"
00019 #include "linkgraph.h"
00020 #include "demands.h"
00021 #include "mcf.h"
00022 #include "flowmapper.h"
00023 #include <queue>
00024
00028 LinkGraph _link_graphs[NUM_CARGO];
00029
00033 LinkGraphJob::HandlerList LinkGraphJob::_handlers;
00034
00041 void Node::Init(StationID st, uint sup, uint dem)
00042 {
00043 this->supply = sup;
00044 this->undelivered_supply = sup;
00045 this->demand = dem;
00046 this->station = st;
00047
00048 for (PathSet::iterator i = this->paths.begin(); i != this->paths.end(); ++i) {
00049 delete *i;
00050 }
00051 this->paths.clear();
00052 this->flows.clear();
00053 }
00054
00060 FORCEINLINE void Edge::Init(uint distance, uint capacity)
00061 {
00062 this->distance = distance;
00063 this->capacity = capacity;
00064 this->demand = 0;
00065 this->unsatisfied_demand = 0;
00066 this->flow = 0;
00067 this->next_edge = INVALID_NODE;
00068 }
00069
00070
00077 void LinkGraph::CreateComponent(Station *first)
00078 {
00079 std::map<Station *, NodeID> index;
00080 index[first] = this->AddNode(first);
00081
00082 std::queue<Station *> search_queue;
00083 search_queue.push(first);
00084
00085
00086 while (!search_queue.empty()) {
00087 Station *source = search_queue.front();
00088 search_queue.pop();
00089
00090 const LinkStatMap &links = source->goods[this->cargo].link_stats;
00091 for (LinkStatMap::const_iterator i = links.begin(); i != links.end(); ++i) {
00092 Station *target = Station::GetIfValid(i->first);
00093 if (target == NULL) continue;
00094
00095 std::map<Station *, NodeID>::iterator index_it = index.find(target);
00096 if (index_it == index.end()) {
00097 search_queue.push(target);
00098 NodeID node = this->AddNode(target);
00099 index[target] = node;
00100
00101 this->AddEdge(index[source], node, i->second.Capacity());
00102 } else {
00103 this->AddEdge(index[source], index_it->second, i->second.Capacity());
00104 }
00105 }
00106 }
00107
00108
00109 this->SpawnThread();
00110 }
00111
00125 void LinkGraph::NextComponent()
00126 {
00127 if (this->GetSize() > 0) return;
00128 StationID last_station_id = this->current_station_id;
00129 LinkGraphComponentID current_component_id = this->LinkGraphComponent::index;
00130
00131 do {
00132 if (++this->current_station_id >= Station::GetPoolSize()) {
00133
00134
00135
00136
00137 this->current_station_id = 0;
00138 if (current_component_id % 2 == 0) {
00139 current_component_id = 1;
00140 } else {
00141 current_component_id = 0;
00142 }
00143 }
00144
00145
00146 Station *station = Station::GetIfValid(this->current_station_id);
00147 if (station != NULL) {
00148 GoodsEntry &ge = station->goods[this->cargo];
00149 if (ge.last_component == INVALID_LINKGRAPH_COMPONENT ||
00150 (ge.last_component + current_component_id) % 2 != 0) {
00151
00152
00153
00154
00155 if (!ge.link_stats.empty()) {
00156 this->LinkGraphComponent::Init(current_component_id + 2);
00157 CreateComponent(station);
00158 return;
00159 }
00160 }
00161 }
00162
00163 } while (this->current_station_id != last_station_id);
00164 }
00165
00171 void OnTick_LinkGraph()
00172 {
00173 if (_date_fract == LinkGraph::COMPONENTS_SPAWN_TICK ||
00174 _date_fract == LinkGraph::COMPONENTS_JOIN_TICK) {
00175
00176
00177
00178
00179 for (uint cargo = _date % _settings_game.linkgraph.recalc_interval; cargo < NUM_CARGO;
00180 cargo += _settings_game.linkgraph.recalc_interval) {
00181
00182
00183 if (_settings_game.linkgraph.GetDistributionType(cargo) == DT_MANUAL) continue;
00184
00185 if (_date_fract == LinkGraph::COMPONENTS_SPAWN_TICK) {
00186 _link_graphs[cargo].NextComponent();
00187 } else {
00188 _link_graphs[cargo].Join();
00189 }
00190 }
00191 }
00192 }
00193
00202 NodeID LinkGraphComponent::AddNode(Station *st)
00203 {
00204 GoodsEntry &good = st->goods[this->cargo];
00205 good.last_component = this->index;
00206
00207 bool do_resize = (this->nodes.size() == this->num_nodes);
00208
00209 if (do_resize) {
00210 this->nodes.push_back(Node());
00211 this->edges.push_back(std::vector<Edge>(this->num_nodes + 1));
00212 }
00213
00214 this->nodes[this->num_nodes].Init(st->index, good.supply,
00215 HasBit(good.acceptance_pickup, GoodsEntry::ACCEPTANCE));
00216
00217 std::vector<Edge> &new_edges = this->edges[this->num_nodes];
00218
00219
00220 new_edges[this->num_nodes].next_edge = INVALID_NODE;
00221
00222 for (NodeID i = 0; i < this->num_nodes; ++i) {
00223 uint distance = DistanceManhattan(st->xy, Station::Get(this->nodes[i].station)->xy);
00224 if (do_resize) this->edges[i].push_back(Edge());
00225 new_edges[i].Init(distance);
00226 this->edges[i][this->num_nodes].Init(distance);
00227 }
00228 return this->num_nodes++;
00229 }
00230
00237 FORCEINLINE void LinkGraphComponent::AddEdge(NodeID from, NodeID to, uint capacity)
00238 {
00239 assert(from != to);
00240 Edge &edge = this->edges[from][to];
00241 Edge &first = this->edges[from][from];
00242 edge.capacity = capacity;
00243 edge.next_edge = first.next_edge;
00244 first.next_edge = to;
00245 }
00246
00256 void LinkGraphComponent::SetSize()
00257 {
00258 if (this->nodes.size() < this->num_nodes) {
00259 for (EdgeMatrix::iterator i = this->edges.begin(); i != this->edges.end(); ++i) {
00260 i->resize(this->num_nodes);
00261 }
00262 this->nodes.resize(this->num_nodes);
00263 this->edges.resize(this->num_nodes, std::vector<Edge>(this->num_nodes));
00264 }
00265
00266 for (uint i = 0; i < this->num_nodes; ++i) {
00267 this->nodes[i].Init();
00268 for (uint j = 0; j < this->num_nodes; ++j) {
00269 this->edges[i][j].Init();
00270 }
00271 }
00272 }
00273
00277 LinkGraphComponent::LinkGraphComponent() :
00278 settings(_settings_game.linkgraph),
00279 cargo(INVALID_CARGO),
00280 num_nodes(0),
00281 index(INVALID_LINKGRAPH_COMPONENT)
00282 {}
00283
00287 void LinkGraphComponent::Init(LinkGraphComponentID id)
00288 {
00289 assert(this->num_nodes == 0);
00290 this->index = id;
00291 this->settings = _settings_game.linkgraph;
00292 }
00293
00294
00303 void Node::ExportNewFlows(FlowMap::iterator &it, FlowStatSet &dest, CargoID cargo)
00304 {
00305 StationID source = it->first;
00306 FlowViaMap &source_flows = it->second;
00307 if (!Station::IsValidID(source)) {
00308 source_flows.clear();
00309 } else {
00310 Station *curr_station = Station::Get(this->station);
00311 for (FlowViaMap::iterator update = source_flows.begin(); update != source_flows.end();) {
00312 StationID next = update->first;
00313 int planned = update->second;
00314 assert(planned >= 0);
00315
00316 Station *via = Station::GetIfValid(next);
00317 if (planned > 0 && via != NULL) {
00318 uint distance = GetMovingAverageLength(curr_station, via);
00319 if (next != this->station) {
00320 const LinkStatMap &ls = curr_station->goods[cargo].link_stats;
00321 if (ls.find(next) != ls.end()) {
00322 dest.insert(FlowStat(distance, next, planned, 0));
00323 }
00324 } else {
00325 dest.insert(FlowStat(distance, next, planned, 0));
00326 }
00327 }
00328 source_flows.erase(update++);
00329 }
00330 }
00331 assert(source_flows.empty());
00332
00333 this->flows.erase(it++);
00334 }
00335
00340 void Node::ExportFlows(CargoID cargo)
00341 {
00342 FlowStatMap &station_flows = Station::Get(this->station)->goods[cargo].flows;
00343 FlowStatSet new_flows;
00344
00345 for (FlowStatMap::iterator station_outer_it(station_flows.begin()); station_outer_it != station_flows.end();) {
00346 FlowMap::iterator node_outer_it(this->flows.find(station_outer_it->first));
00347 if (node_outer_it == this->flows.end()) {
00348
00349 station_flows.erase(station_outer_it++);
00350 } else {
00351 FlowViaMap &source = node_outer_it->second;
00352 FlowStatSet &dest = station_outer_it->second;
00353
00354 for (FlowStatSet::iterator station_inner_it(dest.begin()); station_inner_it != dest.end();) {
00355 FlowViaMap::iterator node_inner_it(source.find(station_inner_it->Via()));
00356 if (node_inner_it != source.end()) {
00357 assert(node_inner_it->second >= 0);
00358 if (node_inner_it->second > 0) {
00359 new_flows.insert(FlowStat(*station_inner_it, node_inner_it->second));
00360 }
00361 source.erase(node_inner_it);
00362 }
00363 dest.erase(station_inner_it++);
00364 }
00365
00366 dest.swap(new_flows);
00367 assert(new_flows.empty());
00368
00369 ExportNewFlows(node_outer_it, dest, cargo);
00370
00371 ++station_outer_it;
00372 }
00373 }
00374
00375 for (FlowMap::iterator it(this->flows.begin()); it != this->flows.end();) {
00376 ExportNewFlows(it, station_flows[it->first], cargo);
00377 }
00378 assert(this->flows.empty());
00379 }
00380
00384 void LinkGraph::Join()
00385 {
00386 this->LinkGraphJob::Join();
00387
00388 for (NodeID node_id = 0; node_id < this->GetSize(); ++node_id) {
00389 Node &node = this->GetNode(node_id);
00390 if (Station::IsValidID(node.station)) {
00391 node.ExportFlows(this->cargo);
00392 InvalidateWindowData(WC_STATION_VIEW, node.station, this->GetCargo());
00393 }
00394 }
00395
00396 this->LinkGraphComponent::Clear();
00397 }
00398
00403 void LinkGraphJob::RunLinkGraphJob(void *j)
00404 {
00405 LinkGraphJob *job = (LinkGraphJob *)j;
00406 for (HandlerList::iterator i = _handlers.begin(); i != _handlers.end(); ++i) {
00407 (*i)->Run(job);
00408 }
00409 }
00410
00414 void LinkGraphJob::ClearHandlers()
00415 {
00416 for (HandlerList::iterator i = _handlers.begin(); i != _handlers.end(); ++i) {
00417 delete *i;
00418 }
00419 _handlers.clear();
00420 }
00421
00429 void Path::Fork(Path *base, uint cap, int free_cap, uint dist)
00430 {
00431 this->capacity = min(base->capacity, cap);
00432 this->free_capacity = min(base->free_capacity, free_cap);
00433 this->distance = base->distance + dist;
00434 assert(this->distance > 0);
00435 if (this->parent != base) {
00436 this->Detach();
00437 this->parent = base;
00438 this->parent->num_children++;
00439 }
00440 this->origin = base->origin;
00441 }
00442
00451 uint Path::AddFlow(uint new_flow, LinkGraphComponent *graph, bool only_positive)
00452 {
00453 if (this->parent != NULL) {
00454 Edge &edge = graph->GetEdge(this->parent->node, this->node);
00455 if (only_positive) {
00456 uint usable_cap = edge.capacity * graph->GetSettings().short_path_saturation / 100;
00457 if (usable_cap > edge.flow) {
00458 new_flow = min(new_flow, usable_cap - edge.flow);
00459 } else {
00460 return 0;
00461 }
00462 }
00463 new_flow = this->parent->AddFlow(new_flow, graph, only_positive);
00464 if (new_flow > 0) {
00465 graph->GetNode(this->parent->node).paths.insert(this);
00466 }
00467 edge.flow += new_flow;
00468 }
00469 this->flow += new_flow;
00470 return new_flow;
00471 }
00472
00478 Path::Path(NodeID n, bool source) :
00479 distance(source ? 0 : UINT_MAX),
00480 capacity(0),
00481 free_capacity(source ? INT_MAX : INT_MIN),
00482 flow(0), node(n), origin(source ? n : INVALID_NODE),
00483 num_children(0), parent(NULL)
00484 {}
00485
00489 FORCEINLINE void LinkGraphJob::Join()
00490 {
00491 if (this->thread == NULL) return;
00492 this->thread->Join();
00493 delete this->thread;
00494 this->thread = NULL;
00495 }
00496
00501 void LinkGraphJob::SpawnThread()
00502 {
00503 assert(this->thread == NULL);
00504 if (!ThreadObject::New(&(LinkGraphJob::RunLinkGraphJob), this, &(this->thread))) {
00505 this->thread = NULL;
00506
00507
00508
00509
00510
00511
00512
00513
00514 LinkGraphJob::RunLinkGraphJob(this);
00515 }
00516 }
00517
00523 void LinkGraph::Init(CargoID cargo)
00524 {
00525 this->LinkGraphJob::Join();
00526 this->LinkGraphComponent::Clear();
00527
00528 this->current_station_id = 0;
00529 this->LinkGraphComponent::cargo = cargo;
00530 }
00531
00535 void InitializeLinkGraphs()
00536 {
00537 for (CargoID c = 0; c < NUM_CARGO; ++c) _link_graphs[c].Init(c);
00538
00539 LinkGraphJob::ClearHandlers();
00540 LinkGraphJob::AddHandler(new DemandHandler);
00541 LinkGraphJob::AddHandler(new MCFHandler<MCF1stPass>);
00542 LinkGraphJob::AddHandler(new FlowMapper);
00543 LinkGraphJob::AddHandler(new MCFHandler<MCF2ndPass>);
00544 LinkGraphJob::AddHandler(new FlowMapper);
00545 }