00001
00002
00003
00004
00005
00006
00007
00008
00009
00012 #ifndef LINKGRAPHJOB_H
00013 #define LINKGRAPHJOB_H
00014
00015 #include "../thread/thread.h"
00016 #include "linkgraph.h"
00017 #include <list>
00018
00019 class LinkGraphJob;
00020 class Path;
00021 typedef std::list<Path *> PathList;
00022
00024 typedef Pool<LinkGraphJob, LinkGraphJobID, 32, 0xFFFFFF> LinkGraphJobPool;
00026 extern LinkGraphJobPool _link_graph_job_pool;
00027
00031 class LinkGraphJob : public LinkGraphJobPool::PoolItem<&_link_graph_job_pool>{
00032 private:
00036 struct EdgeAnnotation {
00037 uint demand;
00038 uint unsatisfied_demand;
00039 uint flow;
00040 void Init();
00041 };
00042
00046 struct NodeAnnotation {
00047 uint undelivered_supply;
00048 PathList paths;
00049 FlowStatMap flows;
00050 void Init(uint supply);
00051 };
00052
00053 typedef SmallVector<NodeAnnotation, 16> NodeAnnotationVector;
00054 typedef SmallMatrix<EdgeAnnotation> EdgeAnnotationMatrix;
00055
00056 friend const SaveLoad *GetLinkGraphJobDesc();
00057 friend class LinkGraphSchedule;
00058
00059 protected:
00060 const LinkGraph link_graph;
00061 const LinkGraphSettings settings;
00062 ThreadObject *thread;
00063 Date join_date;
00064 NodeAnnotationVector nodes;
00065 EdgeAnnotationMatrix edges;
00066
00067 void EraseFlows(NodeID from);
00068
00069 public:
00070
00075 class Edge : public LinkGraph::ConstEdge {
00076 private:
00077 EdgeAnnotation &anno;
00078 public:
00084 Edge(const LinkGraph::BaseEdge &edge, EdgeAnnotation &anno) :
00085 LinkGraph::ConstEdge(edge), anno(anno) {}
00086
00091 uint Demand() const { return this->anno.demand; }
00092
00097 uint UnsatisfiedDemand() const { return this->anno.unsatisfied_demand; }
00098
00103 uint Flow() const { return this->anno.flow; }
00104
00109 void AddFlow(uint flow) { this->anno.flow += flow; }
00110
00115 void RemoveFlow(uint flow)
00116 {
00117 assert(flow <= this->anno.flow);
00118 this->anno.flow -= flow;
00119 }
00120
00125 void AddDemand(uint demand)
00126 {
00127 this->anno.demand += demand;
00128 this->anno.unsatisfied_demand += demand;
00129 }
00130
00135 void SatisfyDemand(uint demand)
00136 {
00137 assert(demand <= this->anno.unsatisfied_demand);
00138 this->anno.unsatisfied_demand -= demand;
00139 }
00140 };
00141
00145 class EdgeIterator : public LinkGraph::BaseEdgeIterator<const LinkGraph::BaseEdge, Edge, EdgeIterator> {
00146 EdgeAnnotation *base_anno;
00147 public:
00154 EdgeIterator(const LinkGraph::BaseEdge *base, EdgeAnnotation *base_anno, NodeID current) :
00155 LinkGraph::BaseEdgeIterator<const LinkGraph::BaseEdge, Edge, EdgeIterator>(base, current),
00156 base_anno(base_anno) {}
00157
00163 SmallPair<NodeID, Edge> operator*() const
00164 {
00165 return SmallPair<NodeID, Edge>(this->current, Edge(this->base[this->current], this->base_anno[this->current]));
00166 }
00167
00173 FakePointer operator->() const {
00174 return FakePointer(this->operator*());
00175 }
00176 };
00177
00182 class Node : public LinkGraph::ConstNode {
00183 private:
00184 NodeAnnotation &node_anno;
00185 EdgeAnnotation *edge_annos;
00186 public:
00187
00193 Node (LinkGraphJob *lgj, NodeID node) :
00194 LinkGraph::ConstNode(&lgj->link_graph, node),
00195 node_anno(lgj->nodes[node]), edge_annos(lgj->edges[node])
00196 {}
00197
00204 Edge operator[](NodeID to) const { return Edge(this->edges[to], this->edge_annos[to]); }
00205
00211 EdgeIterator Begin() const { return EdgeIterator(this->edges, this->edge_annos, index); }
00212
00218 EdgeIterator End() const { return EdgeIterator(this->edges, this->edge_annos, INVALID_NODE); }
00219
00224 uint UndeliveredSupply() const { return this->node_anno.undelivered_supply; }
00225
00230 FlowStatMap &Flows() { return this->node_anno.flows; }
00231
00236 const FlowStatMap &Flows() const { return this->node_anno.flows; }
00237
00243 PathList &Paths() { return this->node_anno.paths; }
00244
00249 const PathList &Paths() const { return this->node_anno.paths; }
00250
00256 void DeliverSupply(NodeID to, uint amount)
00257 {
00258 this->node_anno.undelivered_supply -= amount;
00259 (*this)[to].AddDemand(amount);
00260 }
00261 };
00262
00267 LinkGraphJob() : settings(_settings_game.linkgraph), thread(NULL),
00268 join_date(INVALID_DATE) {}
00269
00270 LinkGraphJob(const LinkGraph &orig);
00271 ~LinkGraphJob();
00272
00273 void Init();
00274
00279 inline bool IsFinished() const { return this->join_date <= _date; }
00280
00285 inline Date JoinDate() const { return join_date; }
00286
00291 inline void ShiftJoinDate(int interval) { this->join_date += interval; }
00292
00297 inline const LinkGraphSettings &Settings() const { return this->settings; }
00298
00304 inline Node operator[](NodeID num) { return Node(this, num); }
00305
00310 inline uint Size() const { return this->link_graph.Size(); }
00311
00316 inline CargoID Cargo() const { return this->link_graph.Cargo(); }
00317
00322 inline Date LastCompression() const { return this->link_graph.LastCompression(); }
00323
00328 inline LinkGraphID LinkGraphIndex() const { return this->link_graph.index; }
00329
00334 inline const LinkGraph &Graph() const { return this->link_graph; }
00335 };
00336
00337 #define FOR_ALL_LINK_GRAPH_JOBS(var) FOR_ALL_ITEMS_FROM(LinkGraphJob, link_graph_job_index, var, 0)
00338
00342 class Path {
00343 public:
00344 Path(NodeID n, bool source = false);
00345
00347 inline NodeID GetNode() const { return this->node; }
00348
00350 inline NodeID GetOrigin() const { return this->origin; }
00351
00353 inline Path *GetParent() { return this->parent; }
00354
00356 inline uint GetCapacity() const { return this->capacity; }
00357
00359 inline int GetFreeCapacity() const { return this->free_capacity; }
00360
00368 inline static int GetCapacityRatio(int free, uint total)
00369 {
00370 return Clamp(free, PATH_CAP_MIN_FREE, PATH_CAP_MAX_FREE) * PATH_CAP_MULTIPLIER / max(total, 1U);
00371 }
00372
00377 inline int GetCapacityRatio() const
00378 {
00379 return Path::GetCapacityRatio(this->free_capacity, this->capacity);
00380 }
00381
00383 inline uint GetDistance() const { return this->distance; }
00384
00386 inline void ReduceFlow(uint f) { this->flow -= f; }
00387
00389 inline void AddFlow(uint f) { this->flow += f; }
00390
00392 inline uint GetFlow() const { return this->flow; }
00393
00395 inline uint GetNumChildren() const { return this->num_children; }
00396
00400 inline void Detach()
00401 {
00402 if (this->parent != NULL) {
00403 this->parent->num_children--;
00404 this->parent = NULL;
00405 }
00406 }
00407
00408 uint AddFlow(uint f, LinkGraphJob &job, uint max_saturation);
00409 void Fork(Path *base, uint cap, int free_cap, uint dist);
00410
00411 protected:
00412
00416 enum PathCapacityBoundaries {
00417 PATH_CAP_MULTIPLIER = 16,
00418 PATH_CAP_MIN_FREE = (INT_MIN + 1) / PATH_CAP_MULTIPLIER,
00419 PATH_CAP_MAX_FREE = (INT_MAX - 1) / PATH_CAP_MULTIPLIER
00420 };
00421
00422 uint distance;
00423 uint capacity;
00424 int free_capacity;
00425 uint flow;
00426 NodeID node;
00427 NodeID origin;
00428 uint num_children;
00429 Path *parent;
00430 };
00431
00432 #endif