bug fix, test...
3 #ifndef HUGO_SMART_GRAPH_H
4 #define HUGO_SMART_GRAPH_H
8 ///\brief SmartGraph and SymSmartGraph classes.
13 #include <hugo/invalid.h>
17 /// \addtogroup graphs
21 ///A smart graph class.
23 ///This is a simple and fast graph implementation.
24 ///It is also quite memory efficient, but at the price
25 ///that <b> it does not support node and edge deletion</b>.
26 ///It conforms to the graph interface documented under
27 ///the description of \ref GraphSkeleton.
28 ///\sa \ref GraphSkeleton.
30 ///\todo Some member functions could be \c static.
32 ///\todo A possibly useful functionality: a function saveState() would
33 ///give back a data sturcture X and then the function restoreState(X)
34 ///would remove the nodes and edges added after the call of saveState().
35 ///Of course it should be used as a stack. (Maybe X is not necessary.)
37 ///\author Alpar Juttner
42 int first_in,first_out;
43 NodeT() : first_in(-1), first_out(-1) {}
47 int head, tail, next_in, next_out;
48 //FIXME: is this necessary?
49 EdgeT() : next_in(-1), next_out(-1) {}
52 std::vector<NodeT> nodes;
54 std::vector<EdgeT> edges;
58 template <typename Key> class DynMapBase
63 virtual void add(const Key k) = 0;
64 virtual void erase(const Key k) = 0;
65 DynMapBase(const SmartGraph &_G) : G(&_G) {}
66 virtual ~DynMapBase() {}
67 friend class SmartGraph;
71 template <typename T> class EdgeMap;
72 template <typename T> class NodeMap;
80 ///\bug It must be public because of SymEdgeMap.
82 mutable std::vector<DynMapBase<Node> * > dyn_node_maps;
83 ///\bug It must be public because of SymEdgeMap.
85 mutable std::vector<DynMapBase<Edge> * > dyn_edge_maps;
95 template <typename T> class NodeMap;
96 template <typename T> class EdgeMap;
100 SmartGraph() : nodes(), edges() { }
101 SmartGraph(const SmartGraph &_g) : nodes(_g.nodes), edges(_g.edges) { }
105 for(std::vector<DynMapBase<Node> * >::iterator i=dyn_node_maps.begin();
106 i!=dyn_node_maps.end(); ++i) (**i).G=NULL;
107 for(std::vector<DynMapBase<Edge> * >::iterator i=dyn_edge_maps.begin();
108 i!=dyn_edge_maps.end(); ++i) (**i).G=NULL;
111 int nodeNum() const { return nodes.size(); } //FIXME: What is this?
112 int edgeNum() const { return edges.size(); } //FIXME: What is this?
114 ///\bug This function does something different than
115 ///its name would suggests...
116 int maxNodeId() const { return nodes.size(); } //FIXME: What is this?
117 ///\bug This function does something different than
118 ///its name would suggests...
119 int maxEdgeId() const { return edges.size(); } //FIXME: What is this?
121 Node tail(Edge e) const { return edges[e.n].tail; }
122 Node head(Edge e) const { return edges[e.n].head; }
124 Node aNode(OutEdgeIt e) const { return edges[e.n].tail; }
125 Node aNode(InEdgeIt e) const { return edges[e.n].head; }
127 Node bNode(OutEdgeIt e) const { return edges[e.n].head; }
128 Node bNode(InEdgeIt e) const { return edges[e.n].tail; }
130 NodeIt& first(NodeIt& v) const {
131 v=NodeIt(*this); return v; }
132 EdgeIt& first(EdgeIt& e) const {
133 e=EdgeIt(*this); return e; }
134 OutEdgeIt& first(OutEdgeIt& e, const Node v) const {
135 e=OutEdgeIt(*this,v); return e; }
136 InEdgeIt& first(InEdgeIt& e, const Node v) const {
137 e=InEdgeIt(*this,v); return e; }
139 // template< typename It >
140 // It first() const { It e; first(e); return e; }
142 // template< typename It >
143 // It first(Node v) const { It e; first(e,v); return e; }
145 static bool valid(Edge e) { return e.n!=-1; }
146 static bool valid(Node n) { return n.n!=-1; }
153 static void setInvalid(Edge &e) { e.n=-1; }
159 static void setInvalid(Node &n) { n.n=-1; }
161 template <typename It> It getNext(It it) const
162 { It tmp(it); return next(tmp); }
164 NodeIt& next(NodeIt& it) const {
165 it.n=(it.n+2)%(nodes.size()+1)-1;
168 OutEdgeIt& next(OutEdgeIt& it) const
169 { it.n=edges[it.n].next_out; return it; }
170 InEdgeIt& next(InEdgeIt& it) const
171 { it.n=edges[it.n].next_in; return it; }
172 EdgeIt& next(EdgeIt& it) const { --it.n; return it; }
174 static int id(Node v) { return v.n; }
175 static int id(Edge e) { return e.n; }
178 Node n; n.n=nodes.size();
179 nodes.push_back(NodeT()); //FIXME: Hmmm...
181 for(std::vector<DynMapBase<Node> * >::iterator i=dyn_node_maps.begin();
182 i!=dyn_node_maps.end(); ++i) (**i).add(n);
187 Edge addEdge(Node u, Node v) {
188 Edge e; e.n=edges.size(); edges.push_back(EdgeT()); //FIXME: Hmmm...
189 edges[e.n].tail=u.n; edges[e.n].head=v.n;
190 edges[e.n].next_out=nodes[u.n].first_out;
191 edges[e.n].next_in=nodes[v.n].first_in;
192 nodes[u.n].first_out=nodes[v.n].first_in=e.n;
194 for(std::vector<DynMapBase<Edge> * >::iterator i=dyn_edge_maps.begin();
195 i!=dyn_edge_maps.end(); ++i) (**i).add(e);
200 void clear() {nodes.clear();edges.clear();}
203 friend class SmartGraph;
204 template <typename T> friend class NodeMap;
207 friend class OutEdgeIt;
208 friend class InEdgeIt;
209 friend class SymEdge;
213 friend int SmartGraph::id(Node v);
217 Node (Invalid) { n=-1; }
218 bool operator==(const Node i) const {return n==i.n;}
219 bool operator!=(const Node i) const {return n!=i.n;}
220 bool operator<(const Node i) const {return n<i.n;}
223 class NodeIt : public Node {
224 friend class SmartGraph;
226 NodeIt() : Node() { }
227 NodeIt(Invalid i) : Node(i) { }
228 NodeIt(const SmartGraph& G) : Node(G.nodes.size()?0:-1) { }
229 ///\todo Undocumented conversion Node -\> NodeIt.
230 NodeIt(const SmartGraph& G, const Node &n) : Node(n) { }
234 friend class SmartGraph;
235 template <typename T> friend class EdgeMap;
237 //template <typename T> friend class SymSmartGraph::SymEdgeMap;
238 //friend Edge SymSmartGraph::opposite(Edge) const;
244 friend int SmartGraph::id(Edge e);
247 /// An Edge with id \c n.
249 /// \bug It should be
250 /// obtained by a member function of the Graph.
253 Edge (Invalid) { n=-1; }
254 bool operator==(const Edge i) const {return n==i.n;}
255 bool operator!=(const Edge i) const {return n!=i.n;}
256 bool operator<(const Edge i) const {return n<i.n;}
257 ///\bug This is a workaround until somebody tells me how to
258 ///make class \c SymSmartGraph::SymEdgeMap friend of Edge
259 int &idref() {return n;}
260 const int &idref() const {return n;}
263 class EdgeIt : public Edge {
264 friend class SmartGraph;
266 EdgeIt(const SmartGraph& G) : Edge(G.edges.size()-1) { }
267 EdgeIt (Invalid i) : Edge(i) { }
268 EdgeIt() : Edge() { }
269 ///\bug This is a workaround until somebody tells me how to
270 ///make class \c SymSmartGraph::SymEdgeMap friend of Edge
271 int &idref() {return n;}
274 class OutEdgeIt : public Edge {
275 friend class SmartGraph;
277 OutEdgeIt() : Edge() { }
278 OutEdgeIt (Invalid i) : Edge(i) { }
280 OutEdgeIt(const SmartGraph& G,const Node v)
281 : Edge(G.nodes[v.n].first_out) {}
284 class InEdgeIt : public Edge {
285 friend class SmartGraph;
287 InEdgeIt() : Edge() { }
288 InEdgeIt (Invalid i) : Edge(i) { }
289 InEdgeIt(const SmartGraph& G,Node v) :Edge(G.nodes[v.n].first_in){}
292 template <typename T> class NodeMap : public DynMapBase<Node>
294 std::vector<T> container;
298 typedef Node KeyType;
300 NodeMap(const SmartGraph &_G) :
301 DynMapBase<Node>(_G), container(_G.maxNodeId())
303 G->dyn_node_maps.push_back(this);
305 NodeMap(const SmartGraph &_G,const T &t) :
306 DynMapBase<Node>(_G), container(_G.maxNodeId(),t)
308 G->dyn_node_maps.push_back(this);
311 NodeMap(const NodeMap<T> &m) :
312 DynMapBase<Node>(*m.G), container(m.container)
314 G->dyn_node_maps.push_back(this);
317 template<typename TT> friend class NodeMap;
319 ///\todo It can copy between different types.
320 ///\todo We could use 'copy'
321 template<typename TT> NodeMap(const NodeMap<TT> &m) :
322 DynMapBase<Node>(*m.G), container(m.container.size())
324 G->dyn_node_maps.push_back(this);
325 typename std::vector<TT>::const_iterator i;
326 for(typename std::vector<TT>::const_iterator i=m.container.begin();
327 i!=m.container.end();
329 container.push_back(*i);
334 std::vector<DynMapBase<Node>* >::iterator i;
335 for(i=G->dyn_node_maps.begin();
336 i!=G->dyn_node_maps.end() && *i!=this; ++i) ;
337 //if(*i==this) G->dyn_node_maps.erase(i); //FIXME: Way too slow...
338 //A better way to do that: (Is this really important?)
340 *i=G->dyn_node_maps.back();
341 G->dyn_node_maps.pop_back();
346 void add(const Node k)
348 if(k.n>=int(container.size())) container.resize(k.n+1);
351 void erase(const Node) { }
353 void set(Node n, T a) { container[n.n]=a; }
354 //'T& operator[](Node n)' would be wrong here
355 typename std::vector<T>::reference
356 operator[](Node n) { return container[n.n]; }
357 //'const T& operator[](Node n)' would be wrong here
358 typename std::vector<T>::const_reference
359 operator[](Node n) const { return container[n.n]; }
361 ///\warning There is no safety check at all!
362 ///Using operator = between maps attached to different graph may
363 ///cause serious problem.
364 ///\todo Is this really so?
365 ///\todo It can copy between different types.
366 const NodeMap<T>& operator=(const NodeMap<T> &m)
368 container = m.container;
371 template<typename TT>
372 const NodeMap<T>& operator=(const NodeMap<TT> &m)
374 std::copy(m.container.begin(), m.container.end(), container.begin());
378 void update() {} //Useless for Dynamic Maps
379 void update(T a) {} //Useless for Dynamic Maps
382 template <typename T> class EdgeMap : public DynMapBase<Edge>
384 std::vector<T> container;
388 typedef Edge KeyType;
390 EdgeMap(const SmartGraph &_G) :
391 DynMapBase<Edge>(_G), container(_G.maxEdgeId())
393 //FIXME: What if there are empty Id's?
394 //FIXME: Can I use 'this' in a constructor?
395 G->dyn_edge_maps.push_back(this);
397 EdgeMap(const SmartGraph &_G,const T &t) :
398 DynMapBase<Edge>(_G), container(_G.maxEdgeId(),t)
400 G->dyn_edge_maps.push_back(this);
402 EdgeMap(const EdgeMap<T> &m) :
403 DynMapBase<Edge>(*m.G), container(m.container)
405 G->dyn_edge_maps.push_back(this);
408 template<typename TT> friend class EdgeMap;
410 ///\todo It can copy between different types.
411 template<typename TT> EdgeMap(const EdgeMap<TT> &m)
412 : DynMapBase<Edge>(*m.G), container(m.container.size())
414 G->dyn_edge_maps.push_back(this);
415 typename std::vector<TT>::const_iterator i;
416 for(typename std::vector<TT>::const_iterator i=m.container.begin();
417 i!=m.container.end();
419 container.push_back(*i);
424 std::vector<DynMapBase<Edge>* >::iterator i;
425 for(i=G->dyn_edge_maps.begin();
426 i!=G->dyn_edge_maps.end() && *i!=this; ++i) ;
427 //if(*i==this) G->dyn_edge_maps.erase(i); //Way too slow...
428 //A better way to do that: (Is this really important?)
430 *i=G->dyn_edge_maps.back();
431 G->dyn_edge_maps.pop_back();
436 void add(const Edge k)
438 if(k.n>=int(container.size())) container.resize(k.n+1);
440 void erase(const Edge) { }
442 void set(Edge n, T a) { container[n.n]=a; }
443 //T get(Edge n) const { return container[n.n]; }
444 typename std::vector<T>::reference
445 operator[](Edge n) { return container[n.n]; }
446 typename std::vector<T>::const_reference
447 operator[](Edge n) const { return container[n.n]; }
449 ///\warning There is no safety check at all!
450 ///Using operator = between maps attached to different graph may
451 ///cause serious problem.
452 ///\todo Is this really so?
453 ///\todo It can copy between different types.
454 const EdgeMap<T>& operator=(const EdgeMap<T> &m)
456 container = m.container;
459 template<typename TT>
460 const EdgeMap<T>& operator=(const EdgeMap<TT> &m)
462 std::copy(m.container.begin(), m.container.end(), container.begin());
466 void update() {} //Useless for DynMaps
467 void update(T a) {} //Useless for DynMaps
472 ///Graph for bidirectional edges.
474 ///The purpose of this graph structure is to handle graphs
475 ///having bidirectional edges. Here the function \c addEdge(u,v) adds a pair
476 ///of oppositely directed edges.
477 ///There is a new edge map type called
478 ///\ref SymSmartGraph::SymEdgeMap "SymEdgeMap"
479 ///that complements this
481 ///storing shared values for the edge pairs. The usual
482 ///\ref GraphSkeleton::EdgeMap "EdgeMap"
486 ///The oppositely directed edge can also be obtained easily
487 ///using \ref opposite.
488 ///\warning It shares the similarity with \ref SmartGraph that
489 ///it is not possible to delete edges or nodes from the graph.
490 //\sa \ref SmartGraph.
492 class SymSmartGraph : public SmartGraph
495 template<typename T> class SymEdgeMap;
496 template<typename T> friend class SymEdgeMap;
498 SymSmartGraph() : SmartGraph() { }
499 SymSmartGraph(const SmartGraph &_g) : SmartGraph(_g) { }
500 ///Adds a pair of oppositely directed edges to the graph.
501 Edge addEdge(Node u, Node v)
503 Edge e = SmartGraph::addEdge(u,v);
504 SmartGraph::addEdge(v,u);
508 ///The oppositely directed edge.
510 ///Returns the oppositely directed
511 ///pair of the edge \c e.
512 static Edge opposite(Edge e)
515 f.idref() = e.idref() - 2*(e.idref()%2) + 1;
519 ///Common data storage for the edge pairs.
521 ///This map makes it possible to store data shared by the oppositely
522 ///directed pairs of edges.
523 template <typename T> class SymEdgeMap : public DynMapBase<Edge>
525 std::vector<T> container;
529 typedef Edge KeyType;
531 SymEdgeMap(const SymSmartGraph &_G) :
532 DynMapBase<Edge>(_G), container(_G.maxEdgeId()/2)
534 static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.push_back(this);
536 SymEdgeMap(const SymSmartGraph &_G,const T &t) :
537 DynMapBase<Edge>(_G), container(_G.maxEdgeId()/2,t)
539 G->dyn_edge_maps.push_back(this);
542 SymEdgeMap(const SymEdgeMap<T> &m) :
543 DynMapBase<SymEdge>(*m.G), container(m.container)
545 G->dyn_node_maps.push_back(this);
548 // template<typename TT> friend class SymEdgeMap;
550 ///\todo It can copy between different types.
553 template<typename TT> SymEdgeMap(const SymEdgeMap<TT> &m)
554 : DynMapBase<SymEdge>(*m.G), container(m.container.size())
556 G->dyn_node_maps.push_back(this);
557 typename std::vector<TT>::const_iterator i;
558 for(typename std::vector<TT>::const_iterator i=m.container.begin();
559 i!=m.container.end();
561 container.push_back(*i);
567 std::vector<DynMapBase<Edge>* >::iterator i;
568 for(i=static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.begin();
569 i!=static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.end()
571 //if(*i==this) G->dyn_edge_maps.erase(i); //Way too slow...
572 //A better way to do that: (Is this really important?)
574 *i=static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.back();
575 static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.pop_back();
580 void add(const Edge k)
582 if(!k.idref()%2&&k.idref()/2>=int(container.size()))
583 container.resize(k.idref()/2+1);
585 void erase(const Edge k) { }
587 void set(Edge n, T a) { container[n.idref()/2]=a; }
588 //T get(Edge n) const { return container[n.idref()/2]; }
589 typename std::vector<T>::reference
590 operator[](Edge n) { return container[n.idref()/2]; }
591 typename std::vector<T>::const_reference
592 operator[](Edge n) const { return container[n.idref()/2]; }
594 ///\warning There is no safety check at all!
595 ///Using operator = between maps attached to different graph may
596 ///cause serious problem.
597 ///\todo Is this really so?
598 ///\todo It can copy between different types.
599 const SymEdgeMap<T>& operator=(const SymEdgeMap<T> &m)
601 container = m.container;
604 template<typename TT>
605 const SymEdgeMap<T>& operator=(const SymEdgeMap<TT> &m)
607 std::copy(m.container.begin(), m.container.end(), container.begin());
611 void update() {} //Useless for DynMaps
612 void update(T a) {} //Useless for DynMaps
625 #endif //HUGO_SMART_GRAPH_H