linkgraph.h

Go to the documentation of this file.
00001 /* $Id: linkgraph.h 25901 2013-10-22 16:19:31Z fonsinchen $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
00006  * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00007  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
00008  */
00009 
00012 #ifndef LINKGRAPH_H
00013 #define LINKGRAPH_H
00014 
00015 #include "../core/pool_type.hpp"
00016 #include "../core/smallmap_type.hpp"
00017 #include "../core/smallmatrix_type.hpp"
00018 #include "../station_base.h"
00019 #include "../cargotype.h"
00020 #include "../date_func.h"
00021 #include "linkgraph_type.h"
00022 
00023 struct SaveLoad;
00024 class LinkGraph;
00025 
00030 typedef Pool<LinkGraph, LinkGraphID, 32, 0xFFFFFF> LinkGraphPool;
00032 extern LinkGraphPool _link_graph_pool;
00033 
00040 class LinkGraph : public LinkGraphPool::PoolItem<&_link_graph_pool> {
00041 public:
00042 
00054   enum UpdateMode {
00055     REFRESH_RESTRICTED = UINT_MAX - 1, 
00056     REFRESH_UNRESTRICTED = UINT_MAX    
00057   };
00058 
00064   struct BaseNode {
00065     uint supply;             
00066     uint demand;             
00067     StationID station;       
00068     Date last_update;        
00069     void Init(StationID st = INVALID_STATION, uint demand = 0);
00070   };
00071 
00078   struct BaseEdge {
00079     uint distance;                 
00080     uint capacity;                 
00081     uint usage;                    
00082     Date last_unrestricted_update; 
00083     Date last_restricted_update;   
00084     NodeID next_edge;              
00085     void Init(uint distance = 0);
00086   };
00087 
00092   template<typename Tedge>
00093   class EdgeWrapper {
00094   protected:
00095     Tedge &edge; 
00096 
00097   public:
00098 
00103     EdgeWrapper (Tedge &edge) : edge(edge) {}
00104 
00109     uint Capacity() const { return this->edge.capacity; }
00110 
00115     uint Usage() const { return this->edge.usage; }
00116 
00121     uint Distance() const { return this->edge.distance; }
00122 
00127     Date LastUnrestrictedUpdate() const { return this->edge.last_unrestricted_update; }
00128 
00133     Date LastRestrictedUpdate() const { return this->edge.last_restricted_update; }
00134 
00139     Date LastUpdate() const { return max(this->edge.last_unrestricted_update, this->edge.last_restricted_update); }
00140   };
00141 
00147   template<typename Tnode, typename Tedge>
00148   class NodeWrapper {
00149   protected:
00150     Tnode &node;  
00151     Tedge *edges; 
00152     NodeID index; 
00153 
00154   public:
00155 
00162     NodeWrapper(Tnode &node, Tedge *edges, NodeID index) : node(node),
00163       edges(edges), index(index) {}
00164 
00169     uint Supply() const { return this->node.supply; }
00170 
00175     uint Demand() const { return this->node.demand; }
00176 
00181     StationID Station() const { return this->node.station; }
00182 
00187     Date LastUpdate() const { return this->node.last_update; }
00188   };
00189 
00197   template <class Tedge, class Tedge_wrapper, class Titer>
00198   class BaseEdgeIterator {
00199   protected:
00200     Tedge *base;    
00201     NodeID current; 
00202 
00209     class FakePointer : public SmallPair<NodeID, Tedge_wrapper> {
00210     public:
00211 
00216       FakePointer(const SmallPair<NodeID, Tedge_wrapper> &pair) : SmallPair<NodeID, Tedge_wrapper>(pair) {}
00217 
00222       SmallPair<NodeID, Tedge_wrapper> *operator->() { return this; }
00223     };
00224 
00225   public:
00231     BaseEdgeIterator (Tedge *base, NodeID current) :
00232       base(base),
00233       current(current == INVALID_NODE ? current : base[current].next_edge)
00234     {}
00235 
00240     Titer &operator++()
00241     {
00242       this->current = this->base[this->current].next_edge;
00243       return static_cast<Titer &>(*this);
00244     }
00245 
00250     Titer operator++(int)
00251     {
00252       Titer ret(static_cast<Titer &>(*this));
00253       this->current = this->base[this->current].next_edge;
00254       return ret;
00255     }
00256 
00264     template<class Tother>
00265     bool operator==(const Tother &other)
00266     {
00267       return this->base == other.base && this->current == other.current;
00268     }
00269 
00277     template<class Tother>
00278     bool operator!=(const Tother &other)
00279     {
00280       return this->base != other.base || this->current != other.current;
00281     }
00282 
00287     SmallPair<NodeID, Tedge_wrapper> operator*() const
00288     {
00289       return SmallPair<NodeID, Tedge_wrapper>(this->current, Tedge_wrapper(this->base[this->current]));
00290     }
00291 
00296     FakePointer operator->() const {
00297       return FakePointer(this->operator*());
00298     }
00299   };
00300 
00304   typedef EdgeWrapper<const BaseEdge> ConstEdge;
00305 
00309   class Edge : public EdgeWrapper<BaseEdge> {
00310   public:
00315     Edge(BaseEdge &edge) : EdgeWrapper<BaseEdge>(edge) {}
00316     void Update(uint capacity, uint usage);
00317     void Restrict() { this->edge.last_unrestricted_update = INVALID_DATE; }
00318     void Release() { this->edge.last_restricted_update = INVALID_DATE; }
00319   };
00320 
00325   class ConstEdgeIterator : public BaseEdgeIterator<const BaseEdge, ConstEdge, ConstEdgeIterator> {
00326   public:
00332     ConstEdgeIterator(const BaseEdge *edges, NodeID current) :
00333       BaseEdgeIterator<const BaseEdge, ConstEdge, ConstEdgeIterator>(edges, current) {}
00334   };
00335 
00340   class EdgeIterator : public BaseEdgeIterator<BaseEdge, Edge, EdgeIterator> {
00341   public:
00347     EdgeIterator(BaseEdge *edges, NodeID current) :
00348       BaseEdgeIterator<BaseEdge, Edge, EdgeIterator>(edges, current) {}
00349   };
00350 
00355   class ConstNode : public NodeWrapper<const BaseNode, const BaseEdge> {
00356   public:
00362     ConstNode(const LinkGraph *lg, NodeID node) :
00363       NodeWrapper<const BaseNode, const BaseEdge>(lg->nodes[node], lg->edges[node], node)
00364     {}
00365 
00372     ConstEdge operator[](NodeID to) const { return ConstEdge(this->edges[to]); }
00373 
00378     ConstEdgeIterator Begin() const { return ConstEdgeIterator(this->edges, this->index); }
00379 
00384     ConstEdgeIterator End() const { return ConstEdgeIterator(this->edges, INVALID_NODE); }
00385   };
00386 
00390   class Node : public NodeWrapper<BaseNode, BaseEdge> {
00391   public:
00397     Node(LinkGraph *lg, NodeID node) :
00398       NodeWrapper<BaseNode, BaseEdge>(lg->nodes[node], lg->edges[node], node)
00399     {}
00400 
00407     Edge operator[](NodeID to) { return Edge(this->edges[to]); }
00408 
00413     EdgeIterator Begin() { return EdgeIterator(this->edges, this->index); }
00414 
00419     EdgeIterator End() { return EdgeIterator(this->edges, INVALID_NODE); }
00420 
00425     void UpdateSupply(uint supply)
00426     {
00427       this->node.supply += supply;
00428       this->node.last_update = _date;
00429     }
00430 
00435     void SetDemand(uint demand)
00436     {
00437       this->node.demand = demand;
00438     }
00439 
00440     void AddEdge(NodeID to, uint capacity, uint usage = 0);
00441     void UpdateEdge(NodeID to, uint capacity, uint usage = 0);
00442     void RemoveEdge(NodeID to);
00443   };
00444 
00445   typedef SmallVector<BaseNode, 16> NodeVector;
00446   typedef SmallMatrix<BaseEdge> EdgeMatrix;
00447 
00449   static const uint MIN_TIMEOUT_DISTANCE = 32;
00450 
00452   static const uint COMPRESSION_INTERVAL = 256;
00453 
00462   inline static uint Scale(uint val, uint target_age, uint orig_age)
00463   {
00464     return val > 0 ? max(1U, val * target_age / orig_age) : 0;
00465   }
00466 
00468   LinkGraph() : cargo(INVALID_CARGO), last_compression(0) {}
00473   LinkGraph(CargoID cargo) : cargo(cargo), last_compression(_date) {}
00474 
00475   void Init(uint size);
00476   void ShiftDates(int interval);
00477   void Compress();
00478   void Merge(LinkGraph *other);
00479 
00480   /* Splitting link graphs is intentionally not implemented.
00481    * The overhead in determining connectedness would probably outweigh the
00482    * benefit of having to deal with smaller graphs. In real world examples
00483    * networks generally grow. Only rarely a network is permanently split.
00484    * Reacting to temporary splits here would obviously create performance
00485    * problems and detecting the temporary or permanent nature of splits isn't
00486    * trivial. */
00487 
00493   inline Node operator[](NodeID num) { return Node(this, num); }
00494 
00500   inline ConstNode operator[](NodeID num) const { return ConstNode(this, num); }
00501 
00506   inline uint Size() const { return this->nodes.Length(); }
00507 
00512   inline Date LastCompression() const { return this->last_compression; }
00513 
00518   inline CargoID Cargo() const { return this->cargo; }
00519 
00525   inline uint Monthly(uint base) const
00526   {
00527     return base * 30 / (_date - this->last_compression + 1);
00528   }
00529 
00530   NodeID AddNode(const Station *st);
00531   void RemoveNode(NodeID id);
00532 
00533 protected:
00534   friend class LinkGraph::ConstNode;
00535   friend class LinkGraph::Node;
00536   friend const SaveLoad *GetLinkGraphDesc();
00537   friend const SaveLoad *GetLinkGraphJobDesc();
00538   friend void SaveLoad_LinkGraph(LinkGraph &lg);
00539 
00540   CargoID cargo;         
00541   Date last_compression; 
00542   NodeVector nodes;      
00543   EdgeMatrix edges;      
00544 };
00545 
00546 #define FOR_ALL_LINK_GRAPHS(var) FOR_ALL_ITEMS_FROM(LinkGraph, link_graph_index, var, 0)
00547 
00548 #endif /* LINKGRAPH_H */