# HG changeset patch # User alpar # Date 1082903104 0 # Node ID 639c9daed784c6967fd22040e0796be2b2d49bca # Parent b619f369a9ef39d6604dd42b437581cbb2911d3a Some day this file will contain an erasable version of SmartGraph. diff -r b619f369a9ef -r 639c9daed784 src/work/alpar/list_graph.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/work/alpar/list_graph.h Sun Apr 25 14:25:04 2004 +0000 @@ -0,0 +1,594 @@ +// -*- mode:C++ -*- + +#ifndef HUGO_SMART_GRAPH_H +#define HUGO_SMART_GRAPH_H + +///\file +///\brief SmartGraph and SymSmartGraph classes. + +#include +#include + +#include "invalid.h" + +namespace hugo { + + 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. + 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) = NULL; + virtual void erase(const Key k) = NULL; + 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; } + + void setInvalid(Edge &e) { e.n=-1; } + 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.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 i) { 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) + { + 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_node_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_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); + } + ~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) + { + 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) { } + 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) + { + 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