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 "linkgraph.h"
00019 #include "demands.h"
00020 #include "mcf.h"
00021 #include "flowmapper.h"
00022 #include <queue>
00023
00027 LinkGraph _link_graphs[NUM_CARGO];
00028
00032 LinkGraphJob::HandlerList LinkGraphJob::_handlers;
00033
00040 inline 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 inline 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
00069
00076 void LinkGraph::CreateComponent(Station *first)
00077 {
00078 std::map<Station *, NodeID> index;
00079 index[first] = this->AddNode(first);
00080
00081 std::queue<Station *> search_queue;
00082 search_queue.push(first);
00083
00084
00085 while (!search_queue.empty()) {
00086 Station *source = search_queue.front();
00087 search_queue.pop();
00088
00089 const LinkStatMap &links = source->goods[this->cargo].link_stats;
00090 for (LinkStatMap::const_iterator i = links.begin(); i != links.end(); ++i) {
00091 Station *target = Station::GetIfValid(i->first);
00092 if (target == NULL) continue;
00093
00094 std::map<Station *, NodeID>::iterator index_it = index.find(target);
00095 if (index_it == index.end()) {
00096 search_queue.push(target);
00097 NodeID node = this->AddNode(target);
00098 index[target] = node;
00099
00100 this->AddEdge(index[source], node, i->second.Capacity());
00101 } else {
00102 this->AddEdge(index[source], index_it->second, i->second.Capacity());
00103 }
00104 }
00105 }
00106
00107
00108 this->SpawnThread();
00109 }
00110
00124 void LinkGraph::NextComponent()
00125 {
00126
00127
00128
00129 if (Station::GetNumItems() == 0) return;
00130
00131
00132 if (this->GetSize() > 0) return;
00133
00134
00135
00136
00137
00138
00139 StationID last_station_id = min(this->current_station_id, Station::GetPoolSize() - 1);
00140 LinkGraphComponentID current_component_id = this->LinkGraphComponent::index;
00141
00142 do {
00143 if (++this->current_station_id >= Station::GetPoolSize()) {
00144
00145
00146
00147
00148 this->current_station_id = 0;
00149 if (current_component_id % 2 == 0) {
00150 current_component_id = 1;
00151 } else {
00152 current_component_id = 0;
00153 }
00154 }
00155
00156
00157 Station *station = Station::GetIfValid(this->current_station_id);
00158 if (station != NULL) {
00159 GoodsEntry &ge = station->goods[this->cargo];
00160 if (ge.last_component == INVALID_LINKGRAPH_COMPONENT ||
00161 (ge.last_component + current_component_id) % 2 != 0) {
00162
00163
00164
00165
00166 if (!ge.link_stats.empty()) {
00167 this->LinkGraphComponent::Init(current_component_id + 2);
00168 CreateComponent(station);
00169 return;
00170 }
00171 }
00172 }
00173
00174 } while (this->current_station_id != last_station_id);
00175 }
00176
00182 void OnTick_LinkGraph()
00183 {
00184 if (_date_fract == LinkGraph::COMPONENTS_SPAWN_TICK ||
00185 _date_fract == LinkGraph::COMPONENTS_JOIN_TICK) {
00186
00187
00188
00189
00190 for (uint cargo = _date % _settings_game.linkgraph.recalc_interval; cargo < NUM_CARGO;
00191 cargo += _settings_game.linkgraph.recalc_interval) {
00192
00193
00194 if (_settings_game.linkgraph.GetDistributionType(cargo) == DT_MANUAL) continue;
00195
00196 if (_date_fract == LinkGraph::COMPONENTS_SPAWN_TICK) {
00197 _link_graphs[cargo].NextComponent();
00198 } else {
00199 _link_graphs[cargo].Join();
00200 }
00201 }
00202 }
00203 }
00204
00213 NodeID LinkGraphComponent::AddNode(Station *st)
00214 {
00215 GoodsEntry &good = st->goods[this->cargo];
00216 good.last_component = this->index;
00217
00218 bool do_resize = (this->nodes.size() == this->num_nodes);
00219
00220 if (do_resize) {
00221 this->nodes.push_back(Node());
00222 this->edges.push_back(std::vector<Edge>(this->num_nodes + 1));
00223 }
00224
00225 this->nodes[this->num_nodes].Init(st->index, good.supply,
00226 HasBit(good.acceptance_pickup, GoodsEntry::GES_ACCEPTANCE));
00227
00228 std::vector<Edge> &new_edges = this->edges[this->num_nodes];
00229
00230
00231 new_edges[this->num_nodes].next_edge = INVALID_NODE;
00232
00233 for (NodeID i = 0; i < this->num_nodes; ++i) {
00234 uint distance = DistanceManhattan(st->xy, Station::Get(this->nodes[i].station)->xy);
00235 if (do_resize) this->edges[i].push_back(Edge());
00236 new_edges[i].Init(distance);
00237 this->edges[i][this->num_nodes].Init(distance);
00238 }
00239 return this->num_nodes++;
00240 }
00241
00248 inline void LinkGraphComponent::AddEdge(NodeID from, NodeID to, uint capacity)
00249 {
00250 assert(from != to);
00251 Edge &edge = this->edges[from][to];
00252 Edge &first = this->edges[from][from];
00253 edge.capacity = capacity;
00254 edge.next_edge = first.next_edge;
00255 first.next_edge = to;
00256 }
00257
00267 void LinkGraphComponent::SetSize()
00268 {
00269 if (this->nodes.size() < this->num_nodes) {
00270 for (EdgeMatrix::iterator i = this->edges.begin(); i != this->edges.end(); ++i) {
00271 i->resize(this->num_nodes);
00272 }
00273 this->nodes.resize(this->num_nodes);
00274 this->edges.resize(this->num_nodes, std::vector<Edge>(this->num_nodes));
00275 }
00276
00277 for (uint i = 0; i < this->num_nodes; ++i) {
00278 this->nodes[i].Init();
00279 for (uint j = 0; j < this->num_nodes; ++j) {
00280 this->edges[i][j].Init();
00281 }
00282 }
00283 }
00284
00288 LinkGraphComponent::LinkGraphComponent() :
00289 settings(_settings_game.linkgraph),
00290 cargo(INVALID_CARGO),
00291 num_nodes(0),
00292 index(INVALID_LINKGRAPH_COMPONENT)
00293 {}
00294
00298 void LinkGraphComponent::Init(LinkGraphComponentID id)
00299 {
00300 assert(this->num_nodes == 0);
00301 this->index = id;
00302 this->settings = _settings_game.linkgraph;
00303 }
00304
00305
00314 void Node::ExportFlows(FlowMap::iterator &it, FlowStatMap &station_flows, CargoID cargo)
00315 {
00316 FlowStat *dest = NULL;
00317 StationID source = it->first;
00318 FlowViaMap &source_flows = it->second;
00319 if (!Station::IsValidID(source)) {
00320 source_flows.clear();
00321 } else {
00322 Station *curr_station = Station::Get(this->station);
00323 for (FlowViaMap::iterator update = source_flows.begin(); update != source_flows.end();) {
00324 StationID next = update->first;
00325 int planned = update->second;
00326 assert(planned >= 0);
00327
00328 Station *via = Station::GetIfValid(next);
00329 if (planned > 0 && via != NULL) {
00330 if (next == this->station ||
00331 curr_station->goods[cargo].link_stats.find(next) !=
00332 curr_station->goods[cargo].link_stats.end()) {
00333 if (dest == NULL) {
00334 dest = &(station_flows.insert(std::make_pair(it->first, FlowStat(next, planned))).first->second);
00335 } else {
00336 dest->AddShare(next, planned);
00337 }
00338 }
00339 }
00340 source_flows.erase(update++);
00341 }
00342 }
00343
00344 assert(source_flows.empty());
00345
00346 this->flows.erase(it++);
00347 }
00348
00353 void Node::ExportFlows(CargoID cargo)
00354 {
00355 FlowStatMap &station_flows = Station::Get(this->station)->goods[cargo].flows;
00356 station_flows.clear();
00357
00358
00359 for (FlowMap::iterator it(this->flows.begin()); it != this->flows.end();) {
00360 this->ExportFlows(it, station_flows, cargo);
00361 }
00362 assert(this->flows.empty());
00363 }
00364
00368 void LinkGraph::Join()
00369 {
00370 this->LinkGraphJob::Join();
00371
00372 for (NodeID node_id = 0; node_id < this->GetSize(); ++node_id) {
00373 Node &node = this->GetNode(node_id);
00374 if (Station::IsValidID(node.station)) {
00375 node.ExportFlows(this->cargo);
00376 InvalidateWindowData(WC_STATION_VIEW, node.station, this->GetCargo());
00377 }
00378 }
00379
00380 this->LinkGraphComponent::Clear();
00381 }
00382
00387 void LinkGraphJob::RunLinkGraphJob(void *j)
00388 {
00389 LinkGraphJob *job = (LinkGraphJob *)j;
00390 for (HandlerList::iterator i = LinkGraphJob::_handlers.begin(); i != LinkGraphJob::_handlers.end(); ++i) {
00391 (*i)->Run(job);
00392 }
00393 }
00394
00398 void LinkGraphJob::ClearHandlers()
00399 {
00400 for (HandlerList::iterator i = LinkGraphJob::_handlers.begin(); i != LinkGraphJob::_handlers.end(); ++i) {
00401 delete *i;
00402 }
00403 LinkGraphJob::_handlers.clear();
00404 }
00405
00413 void Path::Fork(Path *base, uint cap, int free_cap, uint dist)
00414 {
00415 this->capacity = min(base->capacity, cap);
00416 this->free_capacity = min(base->free_capacity, free_cap);
00417 this->distance = base->distance + dist;
00418 assert(this->distance > 0);
00419 if (this->parent != base) {
00420 this->Detach();
00421 this->parent = base;
00422 this->parent->num_children++;
00423 }
00424 this->origin = base->origin;
00425 }
00426
00435 uint Path::AddFlow(uint new_flow, LinkGraphComponent *graph, bool only_positive)
00436 {
00437 if (this->parent != NULL) {
00438 Edge &edge = graph->GetEdge(this->parent->node, this->node);
00439 if (only_positive) {
00440 uint usable_cap = edge.capacity * graph->GetSettings().short_path_saturation / 100;
00441 if (usable_cap > edge.flow) {
00442 new_flow = min(new_flow, usable_cap - edge.flow);
00443 } else {
00444 return 0;
00445 }
00446 }
00447 new_flow = this->parent->AddFlow(new_flow, graph, only_positive);
00448 if (new_flow > 0) {
00449 graph->GetNode(this->parent->node).paths.insert(this);
00450 }
00451 edge.flow += new_flow;
00452 }
00453 this->flow += new_flow;
00454 return new_flow;
00455 }
00456
00462 Path::Path(NodeID n, bool source) :
00463 distance(source ? 0 : UINT_MAX),
00464 capacity(0),
00465 free_capacity(source ? INT_MAX : INT_MIN),
00466 flow(0), node(n), origin(source ? n : INVALID_NODE),
00467 num_children(0), parent(NULL)
00468 {}
00469
00473 inline void LinkGraphJob::Join()
00474 {
00475 if (this->thread == NULL) return;
00476 this->thread->Join();
00477 delete this->thread;
00478 this->thread = NULL;
00479 }
00480
00485 void LinkGraphJob::SpawnThread()
00486 {
00487 assert(this->thread == NULL);
00488 if (!ThreadObject::New(&(LinkGraphJob::RunLinkGraphJob), this, &(this->thread))) {
00489 this->thread = NULL;
00490
00491
00492
00493
00494
00495
00496
00497
00498 LinkGraphJob::RunLinkGraphJob(this);
00499 }
00500 }
00501
00507 void LinkGraph::Init(CargoID cargo)
00508 {
00509 this->LinkGraphJob::Join();
00510 this->LinkGraphComponent::Clear();
00511
00512 this->current_station_id = 0;
00513 this->LinkGraphComponent::cargo = cargo;
00514 }
00515
00519 void InitializeLinkGraphs()
00520 {
00521 for (CargoID c = 0; c < NUM_CARGO; ++c) _link_graphs[c].Init(c);
00522
00523 LinkGraphJob::ClearHandlers();
00524 LinkGraphJob::AddHandler(new DemandHandler);
00525 LinkGraphJob::AddHandler(new MCFHandler<MCF1stPass>);
00526 LinkGraphJob::AddHandler(new FlowMapper);
00527 LinkGraphJob::AddHandler(new MCFHandler<MCF2ndPass>);
00528 LinkGraphJob::AddHandler(new FlowMapper);
00529 }