Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifndef LINKGRAPH_H
00013 #define LINKGRAPH_H
00014
00015 #include "../core/pool_type.hpp"
00016 #include "../core/smallvec_type.hpp"
00017 #include "../core/smallmatrix_type.hpp"
00018 #include "../station_base.h"
00019 #include "../cargo_type.h"
00020 #include "../thread/thread.h"
00021 #include "../settings_type.h"
00022 #include "../date_func.h"
00023 #include "linkgraph_type.h"
00024 #include <list>
00025 #include <set>
00026
00027 struct SaveLoad;
00028 class LinkGraph;
00029 class LinkGraphJob;
00030 class Path;
00031
00032 typedef std::set<Path *> PathSet;
00033 typedef std::map<NodeID, Path *> PathViaMap;
00034
00035 class GraphItem {
00036 protected:
00037 uint Monthly(uint base, uint last_compression) const
00038 {
00039 return base * 30 / (_date - last_compression + 1);
00040 }
00041 };
00042
00048 class Node : public GraphItem{
00049 public:
00050 uint supply;
00051 uint demand;
00052 StationID station;
00053 Date last_update;
00054
00058 ~Node() { this->Init(); }
00059
00060 void Init(StationID st = INVALID_STATION, uint demand = 0);
00061
00062 uint MonthlySupply(Date last_compression) const
00063 {
00064 return this->Monthly(this->supply, last_compression);
00065 }
00066 };
00067
00074 class Edge : public GraphItem {
00075 public:
00076 static const uint MIN_DISTANCE = 48;
00077
00078 uint distance;
00079 uint capacity;
00080 uint usage;
00081 Date last_update;
00082 NodeID next_edge;
00083
00084 void Init(uint distance = 0);
00085
00086 uint MonthlyCapacity(Date last_compression) const
00087 {
00088 return this->Monthly(this->capacity, last_compression);
00089 }
00090
00091 uint MonthlyUsage(Date last_compression) const
00092 {
00093 return this->Monthly(this->usage, last_compression);
00094 }
00095 };
00096
00101 class ComponentHandler {
00102 public:
00106 virtual ~ComponentHandler() {}
00107
00113 virtual void Run(LinkGraphJob *job) = 0;
00114 };
00115
00120 typedef Pool<LinkGraph, LinkGraphID, 32, 0xFFFFFF> LinkGraphPool;
00122 extern LinkGraphPool _link_graph_pool;
00123
00130 class LinkGraph : public LinkGraphPool::PoolItem<&_link_graph_pool> {
00131 private:
00132 typedef SmallVector<Node, 16> NodeVector;
00133 typedef SmallMatrix<Edge> EdgeMatrix;
00134
00135 friend const SaveLoad *GetLinkGraphDesc();
00136 friend const SaveLoad *GetLinkGraphJobDesc();
00137
00138 public:
00139 static const uint COMPRESSION_TICK = 58;
00140
00142 LinkGraph() : cargo(INVALID_CARGO), num_nodes(0), last_compression(0) {}
00143 LinkGraph(CargoID cargo) : cargo(cargo), num_nodes(0), last_compression(_date) {}
00144
00145 void Compress();
00146 void Merge(LinkGraph *other);
00147
00148
00149
00150
00151
00152
00153
00154
00155
00162 inline Edge &GetEdge(NodeID from, NodeID to)
00163 {
00164 return this->edges[from][to];
00165 }
00166
00173 inline const Edge &GetEdge(NodeID from, NodeID to) const
00174 {
00175 return this->edges[from][to];
00176 }
00177
00183 inline Node &GetNode(NodeID num)
00184 {
00185 return this->nodes[num];
00186 }
00187
00193 inline const Node &GetNode(NodeID num) const
00194 {
00195 return this->nodes[num];
00196 }
00197
00202 inline uint GetSize() const
00203 {
00204 return this->num_nodes;
00205 }
00206
00211 inline Date GetLastCompression() const
00212 {
00213 return this->last_compression;
00214 }
00215
00220 inline CargoID GetCargo() const
00221 {
00222 return this->cargo;
00223 }
00224
00225 void SetSize();
00226
00227 NodeID AddNode(const Station *st);
00228 void RemoveNode(NodeID id);
00229
00230 void AddEdge(NodeID from, NodeID to, uint capacity);
00231 void UpdateEdge(NodeID from, NodeID to, uint capacity, uint usage);
00232 void RemoveEdge(NodeID from, NodeID to);
00233
00239 inline NodeID GetFirstEdge(NodeID from) const { return edges[from][from].next_edge; }
00240
00247 inline NodeID GetNextEdge(NodeID from, NodeID to) const { return edges[from][to].next_edge; }
00248
00249 protected:
00250 void ResizeNodes();
00251
00252 CargoID cargo;
00253 uint16 num_nodes;
00254 Date last_compression;
00255 NodeVector nodes;
00256 EdgeMatrix edges;
00257 };
00258
00259 #define FOR_ALL_LINK_GRAPHS(var) FOR_ALL_ITEMS_FROM(LinkGraph, link_graph_index, var, 0)
00260
00262 typedef Pool<LinkGraphJob, LinkGraphJobID, 32, 0xFFFFFF> LinkGraphJobPool;
00264 extern LinkGraphJobPool _link_graph_job_pool;
00265
00266 class EdgeAnnotation {
00267 public:
00268 uint demand;
00269 uint unsatisfied_demand;
00270 uint flow;
00271 };
00272
00273 class NodeAnnotation {
00274 public:
00275 uint undelivered_supply;
00276 PathSet paths;
00277 FlowStatMap flows;
00278 };
00279
00280 class LinkGraphJob : public LinkGraphJobPool::PoolItem<&_link_graph_job_pool>{
00281 private:
00282 typedef SmallVector<NodeAnnotation, 16> NodeAnnotationVector;
00283 typedef SmallMatrix<EdgeAnnotation> EdgeAnnotationMatrix;
00284
00285 friend const SaveLoad *GetLinkGraphJobDesc();
00286 friend class LinkGraphSchedule;
00287
00288 protected:
00289 LinkGraph link_graph;
00290 LinkGraphSettings settings;
00291 ThreadObject *thread;
00292 Date join_date;
00293 NodeAnnotationVector nodes;
00294 EdgeAnnotationMatrix edges;
00295
00296 void SpawnThread();
00297 void JoinThread();
00298
00299 public:
00301 LinkGraphJob() : thread(NULL), join_date(INVALID_DATE) {}
00302 LinkGraphJob(const LinkGraph &orig);
00303 ~LinkGraphJob();
00304
00305 inline bool IsFinished() const
00306 {
00307 return this->join_date < _date;
00308 }
00309
00310 inline Date JoinDate() const { return join_date; }
00311
00316 inline const LinkGraphSettings &Settings() const
00317 {
00318 return this->settings;
00319 }
00320
00324 inline LinkGraph &Graph()
00325 {
00326 return this->link_graph;
00327 }
00328
00329 inline EdgeAnnotationMatrix &Edges()
00330 {
00331 return this->edges;
00332 }
00333
00334 inline NodeAnnotationVector &Nodes()
00335 {
00336 return this->nodes;
00337 }
00338
00345 inline EdgeAnnotation &GetEdge(NodeID from, NodeID to)
00346 {
00347 return this->edges[from][to];
00348 }
00349
00355 inline NodeAnnotation &GetNode(NodeID num)
00356 {
00357 return this->nodes[num];
00358 }
00359 };
00360
00361 #define FOR_ALL_LINK_GRAPH_JOBS(var) FOR_ALL_ITEMS_FROM(LinkGraphJob, link_graph_job_index, var, 0)
00362
00363 class LinkGraphSchedule {
00364 private:
00365 LinkGraphSchedule();
00366 ~LinkGraphSchedule();
00367 typedef std::list<LinkGraph *> GraphList;
00368 typedef std::list<LinkGraphJob *> JobList;
00369 friend const SaveLoad *GetLinkGraphScheduleDesc();
00370
00371 protected:
00372 ComponentHandler *handlers[6];
00373 GraphList schedule;
00374 JobList running;
00375
00376 public:
00377
00378 static const uint SPAWN_JOIN_TICK = 21;
00379
00380 static LinkGraphSchedule *Instance();
00381 static void Run(void *j);
00382 static void Clear();
00383 void SpawnNext();
00384 void JoinNext();
00385 void Queue(LinkGraph *lg)
00386 {
00387 assert(LinkGraph::Get(lg->index) == lg);
00388 this->schedule.push_back(lg);
00389 }
00390 void Unqueue(LinkGraph *lg) { this->schedule.remove(lg); }
00391 void SpawnAll();
00392 };
00393
00397 class Path {
00398 public:
00399 Path(NodeID n, bool source = false);
00400
00402 inline NodeID GetNode() const { return this->node; }
00403
00405 inline NodeID GetOrigin() const { return this->origin; }
00406
00408 inline Path *GetParent() { return this->parent; }
00409
00411 inline uint GetCapacity() const { return this->capacity; }
00412
00414 inline int GetFreeCapacity() const { return this->free_capacity; }
00415
00423 inline static int GetCapacityRatio(int free, int total)
00424 {
00425 return (free << 4) / (total + 1);
00426 }
00427
00432 inline int GetCapacityRatio() const
00433 {
00434 return Path::GetCapacityRatio(this->free_capacity, this->capacity);
00435 }
00436
00438 inline uint GetDistance() const { return this->distance; }
00439
00441 inline void ReduceFlow(uint f) { this->flow -= f; }
00442
00444 inline void AddFlow(uint f) { this->flow += f; }
00445
00447 inline uint GetFlow() const { return this->flow; }
00448
00450 inline uint GetNumChildren() const { return this->num_children; }
00451
00455 inline void Detach()
00456 {
00457 if (this->parent != NULL) {
00458 this->parent->num_children--;
00459 this->parent = NULL;
00460 }
00461 }
00462
00463 uint AddFlow(uint f, LinkGraphJob *job, uint max_saturation);
00464 void Fork(Path *base, uint cap, int free_cap, uint dist);
00465
00466 protected:
00467 uint distance;
00468 uint capacity;
00469 int free_capacity;
00470 uint flow;
00471 NodeID node;
00472 NodeID origin;
00473 uint num_children;
00474 Path *parent;
00475 };
00476
00477 #endif