00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #include "linkgraph.h"
00013 #include "demands.h"
00014 #include "mcf.h"
00015 #include "flowmapper.h"
00016 #include "../map_func.h"
00017 #include "../core/bitmath_func.hpp"
00018 #include "../debug.h"
00019 #include "../window_func.h"
00020 #include "../window_gui.h"
00021 #include "../moving_average.h"
00022 #include <queue>
00023
00027 LinkGraph _link_graphs[NUM_CARGO];
00028
00032 LinkGraphJob::HandlerList LinkGraphJob::_handlers;
00033
00040 void Node::Init(StationID st, uint sup, uint dem)
00041 {
00042 this->supply = sup;
00043 this->undelivered_supply = sup;
00044 this->demand = dem;
00045 this->station = st;
00046
00047 for (PathSet::iterator i = this->paths.begin(); i != this->paths.end(); ++i) {
00048 delete (*i);
00049 }
00050 this->paths.clear();
00051 this->flows.clear();
00052 }
00053
00059 FORCEINLINE void Edge::Init(uint distance, uint capacity)
00060 {
00061 this->distance = distance;
00062 this->capacity = capacity;
00063 this->demand = 0;
00064 this->unsatisfied_demand = 0;
00065 this->flow = 0;
00066 this->next_edge =INVALID_NODE;
00067 }
00068
00075 void LinkGraph::CreateComponent(Station *first)
00076 {
00077 std::map<Station *, NodeID> index;
00078 index[first] = this->AddNode(first);
00079
00080 std::queue<Station *> search_queue;
00081 search_queue.push(first);
00082
00083
00084 while(!search_queue.empty()) {
00085 Station *source = search_queue.front();
00086 search_queue.pop();
00087
00088 const LinkStatMap &links = source->goods[this->cargo].link_stats;
00089 for(LinkStatMap::const_iterator i = links.begin(); i != links.end(); ++i) {
00090 Station *target = Station::GetIfValid(i->first);
00091 if (target == NULL) continue;
00092
00093 std::map<Station *, NodeID>::iterator index_it = index.find(target);
00094 if (index_it == index.end()) {
00095 search_queue.push(target);
00096 NodeID node = this->AddNode(target);
00097 index[target] = node;
00098
00099 this->AddEdge(index[source], node, i->second.Capacity());
00100 } else {
00101 this->AddEdge(index[source], index_it->second, i->second.Capacity());
00102 }
00103 }
00104 }
00105
00106
00107 this->SpawnThread();
00108 }
00109
00123 void LinkGraph::NextComponent()
00124 {
00125
00126
00127
00128 if (Station::GetNumItems() == 0) return;
00129
00130
00131 if (this->GetSize() > 0) return;
00132
00133
00134
00135
00136
00137
00138 StationID last_station_id = min(this->current_station_id, Station::GetPoolSize() - 1);
00139 LinkGraphComponentID current_component_id = this->LinkGraphComponent::index;
00140
00141 do {
00142 if (++this->current_station_id >= Station::GetPoolSize()) {
00143
00144
00145
00146
00147 this->current_station_id = 0;
00148 if (current_component_id % 2 == 0) {
00149 current_component_id = 1;
00150 } else {
00151 current_component_id = 0;
00152 }
00153 }
00154
00155
00156 Station *station = Station::GetIfValid(this->current_station_id);
00157 if (station != NULL) {
00158 GoodsEntry &ge = station->goods[this->cargo];
00159 if (ge.last_component == INVALID_LINKGRAPH_COMPONENT ||
00160 (ge.last_component + current_component_id) % 2 != 0) {
00161
00162
00163
00164
00165 if (!ge.link_stats.empty()) {
00166 this->LinkGraphComponent::Init(current_component_id + 2);
00167 CreateComponent(station);
00168 return;
00169 }
00170 }
00171 }
00172
00173 } while (this->current_station_id != last_station_id);
00174 }
00175
00181 void OnTick_LinkGraph()
00182 {
00183 if (_date_fract == LinkGraph::COMPONENTS_SPAWN_TICK ||
00184 _date_fract == LinkGraph::COMPONENTS_JOIN_TICK) {
00185
00186
00187
00188
00189 for (uint cargo = _date % _settings_game.linkgraph.recalc_interval; cargo < NUM_CARGO;
00190 cargo += _settings_game.linkgraph.recalc_interval) {
00191
00192
00193 if (_settings_game.linkgraph.GetDistributionType(cargo) == DT_MANUAL) continue;
00194
00195 if (_date_fract == LinkGraph::COMPONENTS_SPAWN_TICK) {
00196 _link_graphs[cargo].NextComponent();
00197 } else {
00198 _link_graphs[cargo].Join();
00199 }
00200 }
00201 }
00202 }
00203
00212 NodeID LinkGraphComponent::AddNode(Station *st)
00213 {
00214 GoodsEntry &good = st->goods[this->cargo];
00215 good.last_component = this->index;
00216
00217 bool do_resize = (this->nodes.size() == this->num_nodes);
00218
00219 if (do_resize) {
00220 this->nodes.push_back(Node());
00221 this->edges.push_back(std::vector<Edge>(this->num_nodes + 1));
00222 }
00223
00224 this->nodes[this->num_nodes].Init(st->index, good.supply,
00225 HasBit(good.acceptance_pickup, GoodsEntry::GES_ACCEPTANCE));
00226
00227 std::vector<Edge> &new_edges = this->edges[this->num_nodes];
00228
00229
00230 new_edges[this->num_nodes].next_edge = INVALID_NODE;
00231
00232 for(NodeID i = 0; i < this->num_nodes; ++i) {
00233 uint distance = DistanceManhattan(st->xy, Station::Get(this->nodes[i].station)->xy);
00234 if (do_resize) this->edges[i].push_back(Edge());
00235 new_edges[i].Init(distance);
00236 this->edges[i][this->num_nodes].Init(distance);
00237 }
00238 return this->num_nodes++;
00239 }
00240
00247 FORCEINLINE void LinkGraphComponent::AddEdge(NodeID from, NodeID to, uint capacity)
00248 {
00249 assert(from != to);
00250 Edge &edge = this->edges[from][to];
00251 Edge &first = this->edges[from][from];
00252 edge.capacity = capacity;
00253 edge.next_edge = first.next_edge;
00254 first.next_edge = to;
00255 }
00256
00266 void LinkGraphComponent::SetSize()
00267 {
00268 if (this->nodes.size() < this->num_nodes) {
00269 for (EdgeMatrix::iterator i = this->edges.begin(); i != this->edges.end(); ++i) {
00270 i->resize(this->num_nodes);
00271 }
00272 this->nodes.resize(this->num_nodes);
00273 this->edges.resize(this->num_nodes, std::vector<Edge>(this->num_nodes));
00274 }
00275
00276 for(uint i = 0; i < this->num_nodes; ++i) {
00277 this->nodes[i].Init();
00278 for (uint j = 0; j < this->num_nodes; ++j) {
00279 this->edges[i][j].Init();
00280 }
00281 }
00282 }
00283
00287 LinkGraphComponent::LinkGraphComponent() :
00288 settings(_settings_game.linkgraph),
00289 cargo(INVALID_CARGO),
00290 num_nodes(0),
00291 index(INVALID_LINKGRAPH_COMPONENT)
00292 {}
00293
00297 void LinkGraphComponent::Init(LinkGraphComponentID id)
00298 {
00299 assert(this->num_nodes == 0);
00300 this->index = id;
00301 this->settings = _settings_game.linkgraph;
00302 }
00303
00304
00313 void Node::ExportNewFlows(FlowMap::iterator &it, FlowStatSet &dest, CargoID cargo)
00314 {
00315 StationID source = it->first;
00316 FlowViaMap &source_flows = it->second;
00317 if (!Station::IsValidID(source)) {
00318 source_flows.clear();
00319 } else {
00320 Station *curr_station = Station::Get(this->station);
00321 for (FlowViaMap::iterator update = source_flows.begin(); update != source_flows.end();) {
00322 StationID next = update->first;
00323 int planned = update->second;
00324 assert(planned >= 0);
00325
00326 Station *via = Station::GetIfValid(next);
00327 if (planned > 0 && via != NULL) {
00328 uint distance = GetMovingAverageLength(curr_station, via);
00329 if (next != this->station) {
00330 const LinkStatMap &ls = curr_station->goods[cargo].link_stats;
00331 if (ls.find(next) != ls.end()) {
00332 dest.insert(FlowStat(distance, next, planned, 0));
00333 }
00334 } else {
00335 dest.insert(FlowStat(distance, next, planned, 0));
00336 }
00337 }
00338 source_flows.erase(update++);
00339 }
00340 }
00341 assert(source_flows.empty());
00342
00343 this->flows.erase(it++);
00344 }
00345
00350 void Node::ExportFlows(CargoID cargo) {
00351 FlowStatMap &station_flows = Station::Get(this->station)->goods[cargo].flows;
00352 FlowStatSet new_flows;
00353
00354 for(FlowStatMap::iterator station_outer_it(station_flows.begin()); station_outer_it != station_flows.end();) {
00355 FlowMap::iterator node_outer_it(this->flows.find(station_outer_it->first));
00356 if (node_outer_it == this->flows.end()) {
00357
00358 station_flows.erase(station_outer_it++);
00359 } else {
00360 FlowViaMap &source = node_outer_it->second;
00361 FlowStatSet &dest = station_outer_it->second;
00362
00363 for (FlowStatSet::iterator station_inner_it(dest.begin()); station_inner_it != dest.end();) {
00364 FlowViaMap::iterator node_inner_it(source.find(station_inner_it->Via()));
00365 if (node_inner_it != source.end()) {
00366 assert(node_inner_it->second >= 0);
00367 if (node_inner_it->second > 0) {
00368 new_flows.insert(FlowStat(*station_inner_it, node_inner_it->second));
00369 }
00370 source.erase(node_inner_it);
00371 }
00372 dest.erase(station_inner_it++);
00373 }
00374
00375 dest.swap(new_flows);
00376 assert(new_flows.empty());
00377
00378 ExportNewFlows(node_outer_it, dest, cargo);
00379
00380 ++station_outer_it;
00381 }
00382 }
00383
00384 for (FlowMap::iterator it(this->flows.begin()); it != this->flows.end();) {
00385 ExportNewFlows(it, station_flows[it->first], cargo);
00386 }
00387 assert(this->flows.empty());
00388 }
00389
00393 void LinkGraph::Join()
00394 {
00395 this->LinkGraphJob::Join();
00396
00397 for(NodeID node_id = 0; node_id < this->GetSize(); ++node_id) {
00398 Node &node = this->GetNode(node_id);
00399 if (Station::IsValidID(node.station)) {
00400 node.ExportFlows(this->cargo);
00401 Window *station_gui = FindWindowById(WC_STATION_VIEW, node.station);
00402 if (station_gui != NULL) {
00403 station_gui->OnInvalidateData(this->GetCargo());
00404 }
00405 }
00406 }
00407
00408 this->LinkGraphComponent::Clear();
00409 }
00410
00415 void LinkGraphJob::RunLinkGraphJob(void *j)
00416 {
00417 LinkGraphJob *job = (LinkGraphJob *)j;
00418 for (HandlerList::iterator i = _handlers.begin(); i != _handlers.end(); ++i) {
00419 (*i)->Run(job);
00420 }
00421 }
00422
00426 void LinkGraphJob::ClearHandlers()
00427 {
00428 for(HandlerList::iterator i = _handlers.begin(); i != _handlers.end(); ++i) {
00429 delete (*i);
00430 }
00431 _handlers.clear();
00432 }
00433
00441 void Path::Fork(Path *base, uint cap, int free_cap, uint dist)
00442 {
00443 this->capacity = min(base->capacity, cap);
00444 this->free_capacity = min(base->free_capacity, free_cap);
00445 this->distance = base->distance + dist;
00446 assert(this->distance > 0);
00447 if (this->parent != base) {
00448 this->UnFork();
00449 this->parent = base;
00450 this->parent->num_children++;
00451 }
00452 this->origin = base->origin;
00453 }
00454
00463 uint Path::AddFlow(uint new_flow, LinkGraphComponent *graph, bool only_positive)
00464 {
00465 if (this->parent != NULL) {
00466 Edge &edge = graph->GetEdge(this->parent->node, this->node);
00467 if (only_positive) {
00468 uint usable_cap = edge.capacity * graph->GetSettings().short_path_saturation / 100;
00469 if(usable_cap > edge.flow) {
00470 new_flow = min(new_flow, usable_cap - edge.flow);
00471 } else {
00472 return 0;
00473 }
00474 }
00475 new_flow = this->parent->AddFlow(new_flow, graph, only_positive);
00476 if (new_flow > 0) {
00477 graph->GetNode(parent->node).paths.insert(this);
00478 }
00479 edge.flow += new_flow;
00480 }
00481 this->flow += new_flow;
00482 return new_flow;
00483 }
00484
00490 Path::Path(NodeID n, bool source) :
00491 distance(source ? 0 : UINT_MAX),
00492 capacity(0),
00493 free_capacity(source ? INT_MAX : INT_MIN),
00494 flow(0), node(n), origin(source ? n : INVALID_NODE),
00495 num_children(0), parent(NULL)
00496 {}
00497
00501 FORCEINLINE void LinkGraphJob::Join()
00502 {
00503 if (this->thread != NULL) {
00504 this->thread->Join();
00505 delete this->thread;
00506 this->thread = NULL;
00507 }
00508 }
00509
00514 void LinkGraphJob::SpawnThread()
00515 {
00516 assert(this->thread == NULL);
00517 if (!ThreadObject::New(&(LinkGraphJob::RunLinkGraphJob), this, &(this->thread))) {
00518 this->thread = NULL;
00519
00520
00521
00522
00523
00524
00525
00526
00527 LinkGraphJob::RunLinkGraphJob(this);
00528 }
00529 }
00530
00536 void LinkGraph::Init(CargoID cargo)
00537 {
00538 this->LinkGraphJob::Join();
00539 this->LinkGraphComponent::Clear();
00540
00541 this->current_station_id = 0;
00542 this->LinkGraphComponent::cargo = cargo;
00543 }
00544
00548 void InitializeLinkGraphs()
00549 {
00550 for (CargoID c = 0; c < NUM_CARGO; ++c) _link_graphs[c].Init(c);
00551
00552 LinkGraphJob::ClearHandlers();
00553 LinkGraphJob::AddHandler(new DemandHandler);
00554 LinkGraphJob::AddHandler(new MCFHandler<MCF1stPass>);
00555 LinkGraphJob::AddHandler(new FlowMapper);
00556 LinkGraphJob::AddHandler(new MCFHandler<MCF2ndPass>);
00557 LinkGraphJob::AddHandler(new FlowMapper);
00558 }