FullGraph class.
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/work/alpar/fullgraph.h Sun May 09 16:22:49 2004 +0000
1.3 @@ -0,0 +1,295 @@
1.4 +// -*- mode:C++ -*-
1.5 +
1.6 +#ifndef HUGO_FULL_GRAPH_H
1.7 +#define HUGO_FULL_GRAPH_H
1.8 +
1.9 +///\ingroup graphs
1.10 +///\file
1.11 +///\brief FullGraph and SymFullGraph classes.
1.12 +
1.13 +#include <vector>
1.14 +#include <limits.h>
1.15 +
1.16 +#include <hugo/invalid.h>
1.17 +
1.18 +namespace hugo {
1.19 +
1.20 +/// \addtogroup graphs
1.21 +/// @{
1.22 +
1.23 + ///A full graph class.
1.24 +
1.25 + ///This is a simple and fast directed full graph implementation.
1.26 + ///It it completely static, so you can neither add nor delete either
1.27 + ///edges or nodes.
1.28 + ///Otherwise it conforms to the graph interface documented under
1.29 + ///the description of \ref GraphSkeleton.
1.30 + ///\sa \ref GraphSkeleton.
1.31 + ///\todo Shouldn't we avoid loops?
1.32 + ///
1.33 + ///\author Alpar Juttner
1.34 + class FullGraph {
1.35 + int NodeNum;
1.36 + int EdgeNum;
1.37 + public:
1.38 + template <typename T> class EdgeMap;
1.39 + template <typename T> class NodeMap;
1.40 +
1.41 + class Node;
1.42 + class Edge;
1.43 + class NodeIt;
1.44 + class EdgeIt;
1.45 + class OutEdgeIt;
1.46 + class InEdgeIt;
1.47 +
1.48 + template <typename T> class NodeMap;
1.49 + template <typename T> class EdgeMap;
1.50 +
1.51 + public:
1.52 +
1.53 + ///Creates a full graph with \c n nodes.
1.54 + FullGraph(int n) : NodeNum(n), EdgeNum(NodeNum*NodeNum) { }
1.55 + ///
1.56 + FullGraph(const FullGraph &_g)
1.57 + : NodeNum(_g.nodeNum()), EdgeNum(NodeNum*NodeNum) { }
1.58 +
1.59 + int nodeNum() const { return NodeNum; } //FIXME: What is this?
1.60 + int edgeNum() const { return EdgeNum; } //FIXME: What is this?
1.61 +
1.62 + int maxNodeId() const { return NodeNum; } //FIXME: What is this?
1.63 + int maxEdgeId() const { return EdgeNum; } //FIXME: What is this?
1.64 +
1.65 + Node tail(Edge e) const { return e.n%NodeNum; }
1.66 + Node head(Edge e) const { return e.n/NodeNum; }
1.67 +
1.68 + Node aNode(OutEdgeIt e) const { return tail(e); }
1.69 + Node aNode(InEdgeIt e) const { return head(e); }
1.70 +
1.71 + Node bNode(OutEdgeIt e) const { return head(e); }
1.72 + Node bNode(InEdgeIt e) const { return tail(e); }
1.73 +
1.74 + NodeIt& first(NodeIt& v) const {
1.75 + v=NodeIt(*this); return v; }
1.76 + EdgeIt& first(EdgeIt& e) const {
1.77 + e=EdgeIt(*this); return e; }
1.78 + OutEdgeIt& first(OutEdgeIt& e, const Node v) const {
1.79 + e=OutEdgeIt(*this,v); return e; }
1.80 + InEdgeIt& first(InEdgeIt& e, const Node v) const {
1.81 + e=InEdgeIt(*this,v); return e; }
1.82 +
1.83 + bool valid(Edge e) const { return e.n!=-1; }
1.84 + bool valid(Node n) const { return n.n!=-1; }
1.85 +
1.86 + template <typename It> It getNext(It it) const
1.87 + { It tmp(it); return next(tmp); }
1.88 +
1.89 + NodeIt& next(NodeIt& it) const {
1.90 + it.n=(it.n+2)%(NodeNum+1)-1;
1.91 + return it;
1.92 + }
1.93 + OutEdgeIt& next(OutEdgeIt& it) const
1.94 + { it.n+=NodeNum; if(it.n>=EdgeNum) it.n=-1; return it; }
1.95 + InEdgeIt& next(InEdgeIt& it) const
1.96 + { if(!((++it.n)%NodeNum)) it.n=-1; return it; }
1.97 + EdgeIt& next(EdgeIt& it) const { --it.n; return it; }
1.98 +
1.99 + int id(Node v) const { return v.n; }
1.100 + int id(Edge e) const { return e.n; }
1.101 +
1.102 + class Node {
1.103 + friend class FullGraph;
1.104 + template <typename T> friend class NodeMap;
1.105 +
1.106 + friend class Edge;
1.107 + friend class OutEdgeIt;
1.108 + friend class InEdgeIt;
1.109 + friend class SymEdge;
1.110 +
1.111 + protected:
1.112 + int n;
1.113 + friend int FullGraph::id(Node v) const;
1.114 + Node(int nn) {n=nn;}
1.115 + public:
1.116 + Node() {}
1.117 + Node (Invalid) { n=-1; }
1.118 + bool operator==(const Node i) const {return n==i.n;}
1.119 + bool operator!=(const Node i) const {return n!=i.n;}
1.120 + bool operator<(const Node i) const {return n<i.n;}
1.121 + };
1.122 +
1.123 + class NodeIt : public Node {
1.124 + friend class FullGraph;
1.125 + public:
1.126 + NodeIt() : Node() { }
1.127 + NodeIt(Invalid i) : Node(i) { }
1.128 + NodeIt(const FullGraph& G) : Node(G.NodeNum?0:-1) { }
1.129 + ///\todo Undocumented conversion Node -\> NodeIt.
1.130 + NodeIt(const FullGraph& G, const Node &n) : Node(n) { }
1.131 + };
1.132 +
1.133 + class Edge {
1.134 + friend class FullGraph;
1.135 + template <typename T> friend class EdgeMap;
1.136 +
1.137 + friend class Node;
1.138 + friend class NodeIt;
1.139 + protected:
1.140 + int n; //NodeNum*head+tail;
1.141 + friend int FullGraph::id(Edge e) const;
1.142 +
1.143 + Edge(int nn) {n=nn;}
1.144 + public:
1.145 + Edge() { }
1.146 + Edge (Invalid) { n=-1; }
1.147 + bool operator==(const Edge i) const {return n==i.n;}
1.148 + bool operator!=(const Edge i) const {return n!=i.n;}
1.149 + bool operator<(const Edge i) const {return n<i.n;}
1.150 + ///\bug This is a workaround until somebody tells me how to
1.151 + ///make class \c SymFullGraph::SymEdgeMap friend of Edge
1.152 + int &idref() {return n;}
1.153 + const int &idref() const {return n;}
1.154 + };
1.155 +
1.156 + class EdgeIt : public Edge {
1.157 + friend class FullGraph;
1.158 + public:
1.159 + EdgeIt(const FullGraph& G) : Edge(G.EdgeNum-1) { }
1.160 + EdgeIt (Invalid i) : Edge(i) { }
1.161 + EdgeIt() : Edge() { }
1.162 + ///\bug This is a workaround until somebody tells me how to
1.163 + ///make class \c SymFullGraph::SymEdgeMap friend of Edge
1.164 + int &idref() {return n;}
1.165 + };
1.166 +
1.167 + class OutEdgeIt : public Edge {
1.168 + friend class FullGraph;
1.169 + public:
1.170 + OutEdgeIt() : Edge() { }
1.171 + OutEdgeIt (Invalid i) : Edge(i) { }
1.172 +
1.173 + OutEdgeIt(const FullGraph& G,const Node v)
1.174 + : Edge(v.n) {}
1.175 + };
1.176 +
1.177 + class InEdgeIt : public Edge {
1.178 + friend class FullGraph;
1.179 + public:
1.180 + InEdgeIt() : Edge() { }
1.181 + InEdgeIt (Invalid i) : Edge(i) { }
1.182 + InEdgeIt(const FullGraph& G,Node v) :Edge(v.n*G.NodeNum){}
1.183 + };
1.184 +
1.185 + template <typename T> class NodeMap
1.186 + {
1.187 + std::vector<T> container;
1.188 +
1.189 + public:
1.190 + typedef T ValueType;
1.191 + typedef Node KeyType;
1.192 +
1.193 + NodeMap(const FullGraph &_G) : container(_G.NodeNum) { }
1.194 + NodeMap(const FullGraph &_G,const T &t) : container(_G.NodeNum,t) { }
1.195 + NodeMap(const NodeMap<T> &m) : container(m.container) { }
1.196 +
1.197 + template<typename TT> friend class NodeMap;
1.198 + ///\todo It can copy between different types.
1.199 + template<typename TT> NodeMap(const NodeMap<TT> &m)
1.200 + : container(m.container.size())
1.201 + {
1.202 + typename std::vector<TT>::const_iterator i;
1.203 + for(typename std::vector<TT>::const_iterator i=m.container.begin();
1.204 + i!=m.container.end();
1.205 + i++)
1.206 + container.push_back(*i);
1.207 + }
1.208 + void set(Node n, T a) { container[n.n]=a; }
1.209 + //'T& operator[](Node n)' would be wrong here
1.210 + typename std::vector<T>::reference
1.211 + operator[](Node n) { return container[n.n]; }
1.212 + //'const T& operator[](Node n)' would be wrong here
1.213 + typename std::vector<T>::const_reference
1.214 + operator[](Node n) const { return container[n.n]; }
1.215 +
1.216 + ///\warning There is no safety check at all!
1.217 + ///Using operator = between maps attached to different graph may
1.218 + ///cause serious problem.
1.219 + ///\todo Is this really so?
1.220 + ///\todo It can copy between different types.
1.221 + const NodeMap<T>& operator=(const NodeMap<T> &m)
1.222 + {
1.223 + container = m.container;
1.224 + return *this;
1.225 + }
1.226 + template<typename TT>
1.227 + const NodeMap<T>& operator=(const NodeMap<TT> &m)
1.228 + {
1.229 + std::copy(m.container.begin(), m.container.end(), container.begin());
1.230 + return *this;
1.231 + }
1.232 +
1.233 + void update() {} //Useless for Dynamic Maps
1.234 + void update(T a) {} //Useless for Dynamic Maps
1.235 + };
1.236 +
1.237 + template <typename T> class EdgeMap
1.238 + {
1.239 + std::vector<T> container;
1.240 +
1.241 + public:
1.242 + typedef T ValueType;
1.243 + typedef Edge KeyType;
1.244 +
1.245 + EdgeMap(const FullGraph &_G) : container(_G.EdgeNum) { }
1.246 + EdgeMap(const FullGraph &_G,const T &t) : container(_G.EdgeNum,t) { }
1.247 + EdgeMap(const EdgeMap<T> &m) : container(m.container) { }
1.248 +
1.249 + template<typename TT> friend class EdgeMap;
1.250 + ///\todo It can copy between different types.
1.251 + ///\todo We could use 'copy'
1.252 + template<typename TT> EdgeMap(const EdgeMap<TT> &m) :
1.253 + container(m.container.size())
1.254 + {
1.255 + typename std::vector<TT>::const_iterator i;
1.256 + for(typename std::vector<TT>::const_iterator i=m.container.begin();
1.257 + i!=m.container.end();
1.258 + i++)
1.259 + container.push_back(*i);
1.260 + }
1.261 + void set(Edge n, T a) { container[n.n]=a; }
1.262 + //T get(Edge n) const { return container[n.n]; }
1.263 + typename std::vector<T>::reference
1.264 + operator[](Edge n) { return container[n.n]; }
1.265 + typename std::vector<T>::const_reference
1.266 + operator[](Edge n) const { return container[n.n]; }
1.267 +
1.268 + ///\warning There is no safety check at all!
1.269 + ///Using operator = between maps attached to different graph may
1.270 + ///cause serious problem.
1.271 + ///\todo Is this really so?
1.272 + ///\todo It can copy between different types.
1.273 + const EdgeMap<T>& operator=(const EdgeMap<T> &m)
1.274 + {
1.275 + container = m.container;
1.276 + return *this;
1.277 + }
1.278 + template<typename TT>
1.279 + const EdgeMap<T>& operator=(const EdgeMap<TT> &m)
1.280 + {
1.281 + std::copy(m.container.begin(), m.container.end(), container.begin());
1.282 + return *this;
1.283 + }
1.284 +
1.285 + void update() {}
1.286 + void update(T a) {}
1.287 + };
1.288 +
1.289 + };
1.290 +
1.291 + /// @}
1.292 +
1.293 +} //namespace hugo
1.294 +
1.295 +
1.296 +
1.297 +
1.298 +#endif //HUGO_FULL_GRAPH_H