diff -r d8863141824d -r fb261e3a9a0f src/include/smart_graph.h --- a/src/include/smart_graph.h Thu May 06 09:26:23 2004 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,614 +0,0 @@ -// -*- mode:C++ -*- - -#ifndef HUGO_SMART_GRAPH_H -#define HUGO_SMART_GRAPH_H - -///\ingroup graphs -///\file -///\brief SmartGraph and SymSmartGraph classes. - -#include -#include - -#include "invalid.h" - -namespace hugo { - -/// \addtogroup graphs -/// @{ - class SymSmartGraph; - - ///A smart graph class. - - ///This is a simple and fast graph implementation. - ///It is also quite memory efficient, but at the price - ///that it does not support node and edge deletion. - ///It conforms to the graph interface documented under - ///the description of \ref GraphSkeleton. - ///\sa \ref GraphSkeleton. - /// - ///\todo Some member functions could be \c static. - ///\author Alpar Juttner - class SmartGraph { - - struct NodeT - { - int first_in,first_out; - NodeT() : first_in(-1), first_out(-1) {} - }; - struct EdgeT - { - int head, tail, next_in, next_out; - //FIXME: is this necessary? - EdgeT() : next_in(-1), next_out(-1) {} - }; - - std::vector nodes; - - std::vector edges; - - protected: - - template class DynMapBase - { - protected: - const SmartGraph* G; - public: - virtual void add(const Key k) = 0; - virtual void erase(const Key k) = 0; - DynMapBase(const SmartGraph &_G) : G(&_G) {} - virtual ~DynMapBase() {} - friend class SmartGraph; - }; - - public: - template class EdgeMap; - template class EdgeMap; - - class Node; - class Edge; - - // protected: - // HELPME: - protected: - ///\bug It must be public because of SymEdgeMap. - /// - mutable std::vector * > dyn_node_maps; - ///\bug It must be public because of SymEdgeMap. - /// - mutable std::vector * > dyn_edge_maps; - - public: - - - class NodeIt; - class EdgeIt; - class OutEdgeIt; - class InEdgeIt; - - template class NodeMap; - template class EdgeMap; - - public: - - SmartGraph() : nodes(), edges() { } - SmartGraph(const SmartGraph &_g) : nodes(_g.nodes), edges(_g.edges) { } - - ~SmartGraph() - { - for(std::vector * >::iterator i=dyn_node_maps.begin(); - i!=dyn_node_maps.end(); ++i) (**i).G=NULL; - for(std::vector * >::iterator i=dyn_edge_maps.begin(); - i!=dyn_edge_maps.end(); ++i) (**i).G=NULL; - } - - int nodeNum() const { return nodes.size(); } //FIXME: What is this? - int edgeNum() const { return edges.size(); } //FIXME: What is this? - - ///\bug This function does something different than - ///its name would suggests... - int maxNodeId() const { return nodes.size(); } //FIXME: What is this? - ///\bug This function does something different than - ///its name would suggests... - int maxEdgeId() const { return edges.size(); } //FIXME: What is this? - - Node tail(Edge e) const { return edges[e.n].tail; } - Node head(Edge e) const { return edges[e.n].head; } - - Node aNode(OutEdgeIt e) const { return edges[e.n].tail; } - Node aNode(InEdgeIt e) const { return edges[e.n].head; } - - Node bNode(OutEdgeIt e) const { return edges[e.n].head; } - Node bNode(InEdgeIt e) const { return edges[e.n].tail; } - - NodeIt& first(NodeIt& v) const { - v=NodeIt(*this); return v; } - EdgeIt& first(EdgeIt& e) const { - e=EdgeIt(*this); return e; } - OutEdgeIt& first(OutEdgeIt& e, const Node v) const { - e=OutEdgeIt(*this,v); return e; } - InEdgeIt& first(InEdgeIt& e, const Node v) const { - e=InEdgeIt(*this,v); return e; } - -// template< typename It > -// It first() const { It e; first(e); return e; } - -// template< typename It > -// It first(Node v) const { It e; first(e,v); return e; } - - bool valid(Edge e) const { return e.n!=-1; } - bool valid(Node n) const { return n.n!=-1; } - - ///\deprecated Use - ///\code - /// e=INVALID; - ///\endcode - ///instead. - void setInvalid(Edge &e) { e.n=-1; } - ///\deprecated Use - ///\code - /// e=INVALID; - ///\endcode - ///instead. - void setInvalid(Node &n) { n.n=-1; } - - template It getNext(It it) const - { It tmp(it); return next(tmp); } - - NodeIt& next(NodeIt& it) const { - it.n=(it.n+2)%(nodes.size()+1)-1; - return it; - } - OutEdgeIt& next(OutEdgeIt& it) const - { it.n=edges[it.n].next_out; return it; } - InEdgeIt& next(InEdgeIt& it) const - { it.n=edges[it.n].next_in; return it; } - EdgeIt& next(EdgeIt& it) const { --it.n; return it; } - - int id(Node v) const { return v.n; } - int id(Edge e) const { return e.n; } - - Node addNode() { - Node n; n.n=nodes.size(); - nodes.push_back(NodeT()); //FIXME: Hmmm... - - for(std::vector * >::iterator i=dyn_node_maps.begin(); - i!=dyn_node_maps.end(); ++i) (**i).add(n); - - return n; - } - - Edge addEdge(Node u, Node v) { - Edge e; e.n=edges.size(); edges.push_back(EdgeT()); //FIXME: Hmmm... - edges[e.n].tail=u.n; edges[e.n].head=v.n; - edges[e.n].next_out=nodes[u.n].first_out; - edges[e.n].next_in=nodes[v.n].first_in; - nodes[u.n].first_out=nodes[v.n].first_in=e.n; - - for(std::vector * >::iterator i=dyn_edge_maps.begin(); - i!=dyn_edge_maps.end(); ++i) (**i).add(e); - - return e; - } - - void clear() {nodes.clear();edges.clear();} - - class Node { - friend class SmartGraph; - template friend class NodeMap; - - friend class Edge; - friend class OutEdgeIt; - friend class InEdgeIt; - friend class SymEdge; - - protected: - int n; - friend int SmartGraph::id(Node v) const; - Node(int nn) {n=nn;} - public: - Node() {} - Node (Invalid) { n=-1; } - bool operator==(const Node i) const {return n==i.n;} - bool operator!=(const Node i) const {return n!=i.n;} - bool operator<(const Node i) const {return n friend class EdgeMap; - - //template friend class SymSmartGraph::SymEdgeMap; - //friend Edge SymSmartGraph::opposite(Edge) const; - - friend class Node; - friend class NodeIt; - protected: - int n; - friend int SmartGraph::id(Edge e) const; - - Edge(int nn) {n=nn;} - public: - Edge() { } - Edge (Invalid) { n=-1; } - bool operator==(const Edge i) const {return n==i.n;} - bool operator!=(const Edge i) const {return n!=i.n;} - bool operator<(const Edge i) const {return n class NodeMap : public DynMapBase - { - std::vector container; - - public: - typedef T ValueType; - typedef Node KeyType; - - NodeMap(const SmartGraph &_G) : - DynMapBase(_G), container(_G.maxNodeId()) - { - G->dyn_node_maps.push_back(this); - } - NodeMap(const SmartGraph &_G,const T &t) : - DynMapBase(_G), container(_G.maxNodeId(),t) - { - G->dyn_node_maps.push_back(this); - } - - NodeMap(const NodeMap &m) : - DynMapBase(*m.G), container(m.container) - { - G->dyn_node_maps.push_back(this); - } - - template friend class NodeMap; - - ///\todo It can copy between different types. - /// - template NodeMap(const NodeMap &m) : - DynMapBase(*m.G) - { - G->dyn_node_maps.push_back(this); - typename std::vector::const_iterator i; - for(typename std::vector::const_iterator i=m.container.begin(); - i!=m.container.end(); - i++) - container.push_back(*i); - } - ~NodeMap() - { - if(G) { - std::vector* >::iterator i; - for(i=G->dyn_node_maps.begin(); - i!=G->dyn_node_maps.end() && *i!=this; ++i) ; - //if(*i==this) G->dyn_node_maps.erase(i); //FIXME: Way too slow... - //A better way to do that: (Is this really important?) - if(*i==this) { - *i=G->dyn_node_maps.back(); - G->dyn_node_maps.pop_back(); - } - } - } - - void add(const Node k) - { - if(k.n>=int(container.size())) container.resize(k.n+1); - } - - void erase(const Node) { } - - void set(Node n, T a) { container[n.n]=a; } - //'T& operator[](Node n)' would be wrong here - typename std::vector::reference - operator[](Node n) { return container[n.n]; } - //'const T& operator[](Node n)' would be wrong here - typename std::vector::const_reference - operator[](Node n) const { return container[n.n]; } - - ///\warning There is no safety check at all! - ///Using operator = between maps attached to different graph may - ///cause serious problem. - ///\todo Is this really so? - ///\todo It can copy between different types. - const NodeMap& operator=(const NodeMap &m) - { - container = m.container; - return *this; - } - template - const NodeMap& operator=(const NodeMap &m) - { - std::copy(m.container.begin(), m.container.end(), container.begin()); - return *this; - } - - void update() {} //Useless for Dynamic Maps - void update(T a) {} //Useless for Dynamic Maps - }; - - template class EdgeMap : public DynMapBase - { - std::vector container; - - public: - typedef T ValueType; - typedef Edge KeyType; - - EdgeMap(const SmartGraph &_G) : - DynMapBase(_G), container(_G.maxEdgeId()) - { - //FIXME: What if there are empty Id's? - //FIXME: Can I use 'this' in a constructor? - G->dyn_edge_maps.push_back(this); - } - EdgeMap(const SmartGraph &_G,const T &t) : - DynMapBase(_G), container(_G.maxEdgeId(),t) - { - G->dyn_edge_maps.push_back(this); - } - EdgeMap(const EdgeMap &m) : - DynMapBase(*m.G), container(m.container) - { - G->dyn_edge_maps.push_back(this); - } - - template friend class EdgeMap; - - ///\todo It can copy between different types. - /// - template EdgeMap(const EdgeMap &m) : - DynMapBase(*m.G) - { - G->dyn_edge_maps.push_back(this); - typename std::vector::const_iterator i; - for(typename std::vector::const_iterator i=m.container.begin(); - i!=m.container.end(); - i++) - container.push_back(*i); - } - ~EdgeMap() - { - if(G) { - std::vector* >::iterator i; - for(i=G->dyn_edge_maps.begin(); - i!=G->dyn_edge_maps.end() && *i!=this; ++i) ; - //if(*i==this) G->dyn_edge_maps.erase(i); //Way too slow... - //A better way to do that: (Is this really important?) - if(*i==this) { - *i=G->dyn_edge_maps.back(); - G->dyn_edge_maps.pop_back(); - } - } - } - - void add(const Edge k) - { - if(k.n>=int(container.size())) container.resize(k.n+1); - } - void erase(const Edge) { } - - void set(Edge n, T a) { container[n.n]=a; } - //T get(Edge n) const { return container[n.n]; } - typename std::vector::reference - operator[](Edge n) { return container[n.n]; } - typename std::vector::const_reference - operator[](Edge n) const { return container[n.n]; } - - ///\warning There is no safety check at all! - ///Using operator = between maps attached to different graph may - ///cause serious problem. - ///\todo Is this really so? - ///\todo It can copy between different types. - const EdgeMap& operator=(const EdgeMap &m) - { - container = m.container; - return *this; - } - template - const EdgeMap& operator=(const EdgeMap &m) - { - std::copy(m.container.begin(), m.container.end(), container.begin()); - return *this; - } - - void update() {} //Useless for DynMaps - void update(T a) {} //Useless for DynMaps - }; - - }; - - ///Graph for bidirectional edges. - - ///The purpose of this graph structure is to handle graphs - ///having bidirectional edges. Here the function \c addEdge(u,v) adds a pair - ///of oppositely directed edges. - ///There is a new edge map type called - ///\ref SymSmartGraph::SymEdgeMap "SymEdgeMap" - ///that complements this - ///feature by - ///storing shared values for the edge pairs. The usual - ///\ref GraphSkeleton::EdgeMap "EdgeMap" - ///can be used - ///as well. - /// - ///The oppositely directed edge can also be obtained easily - ///using \ref opposite. - ///\warning It shares the similarity with \ref SmartGraph that - ///it is not possible to delete edges or nodes from the graph. - //\sa \ref SmartGraph. - - class SymSmartGraph : public SmartGraph - { - public: - template class SymEdgeMap; - template friend class SymEdgeMap; - - SymSmartGraph() : SmartGraph() { } - SymSmartGraph(const SmartGraph &_g) : SmartGraph(_g) { } - ///Adds a pair of oppositely directed edges to the graph. - Edge addEdge(Node u, Node v) - { - Edge e = SmartGraph::addEdge(u,v); - SmartGraph::addEdge(v,u); - return e; - } - - ///The oppositely directed edge. - - ///Returns the oppositely directed - ///pair of the edge \c e. - Edge opposite(Edge e) const - { - Edge f; - f.idref() = e.idref() - 2*(e.idref()%2) + 1; - return f; - } - - ///Common data storage for the edge pairs. - - ///This map makes it possible to store data shared by the oppositely - ///directed pairs of edges. - template class SymEdgeMap : public DynMapBase - { - std::vector container; - - public: - typedef T ValueType; - typedef Edge KeyType; - - SymEdgeMap(const SymSmartGraph &_G) : - DynMapBase(_G), container(_G.maxEdgeId()/2) - { - static_cast(G)->dyn_edge_maps.push_back(this); - } - SymEdgeMap(const SymSmartGraph &_G,const T &t) : - DynMapBase(_G), container(_G.maxEdgeId()/2,t) - { - G->dyn_edge_maps.push_back(this); - } - - SymEdgeMap(const SymEdgeMap &m) : - DynMapBase(*m.G), container(m.container) - { - G->dyn_node_maps.push_back(this); - } - - // template friend class SymEdgeMap; - - ///\todo It can copy between different types. - /// - - template SymEdgeMap(const SymEdgeMap &m) : - DynMapBase(*m.G) - { - G->dyn_node_maps.push_back(this); - typename std::vector::const_iterator i; - for(typename std::vector::const_iterator i=m.container.begin(); - i!=m.container.end(); - i++) - container.push_back(*i); - } - - ~SymEdgeMap() - { - if(G) { - std::vector* >::iterator i; - for(i=static_cast(G)->dyn_edge_maps.begin(); - i!=static_cast(G)->dyn_edge_maps.end() - && *i!=this; ++i) ; - //if(*i==this) G->dyn_edge_maps.erase(i); //Way too slow... - //A better way to do that: (Is this really important?) - if(*i==this) { - *i=static_cast(G)->dyn_edge_maps.back(); - static_cast(G)->dyn_edge_maps.pop_back(); - } - } - } - - void add(const Edge k) - { - if(!k.idref()%2&&k.idref()/2>=int(container.size())) - container.resize(k.idref()/2+1); - } - void erase(const Edge k) { } - - void set(Edge n, T a) { container[n.idref()/2]=a; } - //T get(Edge n) const { return container[n.idref()/2]; } - typename std::vector::reference - operator[](Edge n) { return container[n.idref()/2]; } - typename std::vector::const_reference - operator[](Edge n) const { return container[n.idref()/2]; } - - ///\warning There is no safety check at all! - ///Using operator = between maps attached to different graph may - ///cause serious problem. - ///\todo Is this really so? - ///\todo It can copy between different types. - const SymEdgeMap& operator=(const SymEdgeMap &m) - { - container = m.container; - return *this; - } - template - const SymEdgeMap& operator=(const SymEdgeMap &m) - { - std::copy(m.container.begin(), m.container.end(), container.begin()); - return *this; - } - - void update() {} //Useless for DynMaps - void update(T a) {} //Useless for DynMaps - - }; - - }; - - /// @} - -} //namespace hugo - - - - -#endif //SMART_GRAPH_H