diff -r 08735c8704cd -r 259540358bbf src/work/alpar/smart_graph.h --- a/src/work/alpar/smart_graph.h Sat Mar 13 22:49:54 2004 +0000 +++ b/src/work/alpar/smart_graph.h Sat Mar 13 22:53:07 2004 +0000 @@ -1,7 +1,7 @@ // -*- mode:C++ -*- -#ifndef SMART_GRAPH_H -#define SMART_GRAPH_H +#ifndef HUGO_SMART_GRAPH_H +#define HUGO_SMART_GRAPH_H #include #include @@ -10,6 +10,10 @@ namespace hugo { + class SymSmartGraph; + + // template class SymSmartGraph::SymEdgeMap; + class SmartGraph { struct NodeT @@ -28,10 +32,12 @@ std::vector edges; + protected: + template class DynMapBase { protected: - SmartGraph* G; + const SmartGraph* G; public: virtual void add(const Key k) = NULL; virtual void erase(const Key k) = NULL; @@ -39,15 +45,22 @@ virtual ~DynMapBase() {} friend class SmartGraph; }; + public: - template class DynEdgeMap; - template class DynEdgeMap; + template class EdgeMap; + template class EdgeMap; class Node; class Edge; - protected: + // protected: + // HELPME: + public: + ///\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: @@ -168,7 +181,6 @@ class Node { friend class SmartGraph; template friend class NodeMap; - template friend class DynNodeMap; friend class Edge; friend class OutEdgeIt; @@ -197,7 +209,9 @@ class Edge { friend class SmartGraph; template friend class EdgeMap; - template friend class DynEdgeMap; + + //template friend class SymSmartGraph::SymEdgeMap; + //friend Edge SymSmartGraph::opposite(Edge) const; friend class Node; friend class NodeIt; @@ -212,6 +226,10 @@ 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 { - const SmartGraph& G; - std::vector container; - public: - typedef T ValueType; - typedef Node KeyType; - NodeMap(const SmartGraph& _G) : G(_G), container(G.maxNodeId()) { } - NodeMap(const SmartGraph& _G, T a) : - G(_G), container(G.maxNodeId(), a) { } - void set(Node n, T a) { container[n.n]=a; } - T get(Node n) const { return container[n.n]; } - T& operator[](Node n) { return container[n.n]; } - const T& operator[](Node n) const { return container[n.n]; } - void update() { container.resize(G.maxNodeId()); } - void update(T a) { container.resize(G.maxNodeId(), a); } - }; +// // Static Maps are not necessary. +// template +// class NodeMap { +// const SmartGraph& G; +// std::vector container; +// public: +// typedef T ValueType; +// typedef Node KeyType; +// NodeMap(const SmartGraph& _G) : G(_G), container(G.maxNodeId()) { } +// NodeMap(const SmartGraph& _G, T a) : +// G(_G), container(G.maxNodeId(), a) { } +// void set(Node n, T a) { container[n.n]=a; } +// T get(Node n) const { return container[n.n]; } +// T& operator[](Node n) { return container[n.n]; } +// const T& operator[](Node n) const { return container[n.n]; } +// void update() { container.resize(G.maxNodeId()); } +// void update(T a) { container.resize(G.maxNodeId(), a); } +// }; - template - class EdgeMap { - const SmartGraph& G; - std::vector container; - public: - typedef T ValueType; - typedef Edge KeyType; - EdgeMap(const SmartGraph& _G) : G(_G), container(G.maxEdgeId()) { } - EdgeMap(const SmartGraph& _G, T a) : - G(_G), container(G.maxEdgeId(), a) { } - void set(Edge e, T a) { container[e.n]=a; } - T get(Edge e) const { return container[e.n]; } - T& operator[](Edge e) { return container[e.n]; } - const T& operator[](Edge e) const { return container[e.n]; } - void update() { container.resize(G.maxEdgeId()); } - void update(T a) { container.resize(G.maxEdgeId(), a); } - }; +// template +// class EdgeMap { +// const SmartGraph& G; +// std::vector container; +// public: +// typedef T ValueType; +// typedef Edge KeyType; +// EdgeMap(const SmartGraph& _G) : G(_G), container(G.maxEdgeId()) { } +// EdgeMap(const SmartGraph& _G, T a) : +// G(_G), container(G.maxEdgeId(), a) { } +// void set(Edge e, T a) { container[e.n]=a; } +// T get(Edge e) const { return container[e.n]; } +// T& operator[](Edge e) { return container[e.n]; } +// const T& operator[](Edge e) const { return container[e.n]; } +// void update() { container.resize(G.maxEdgeId()); } +// void update(T a) { container.resize(G.maxEdgeId(), a); } +// }; - template class DynNodeMap : public DynMapBase + template class NodeMap : public DynMapBase { std::vector container; @@ -286,14 +308,38 @@ typedef T ValueType; typedef Node KeyType; - DynNodeMap(const SmartGraph &_G) : + NodeMap(const SmartGraph &_G) : DynMapBase(_G), container(_G.maxNodeId()) { - //FIXME: What if there are empty Id's? - //FIXME: Can I use 'this' in a constructor? G->dyn_node_maps.push_back(this); } - ~DynNodeMap() + 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; @@ -310,28 +356,38 @@ void add(const Node k) { - if(k.n>=container.size()) container.resize(k.n+1); + if(k.n>=int(container.size())) container.resize(k.n+1); } -// void erase(const Node k) -// { -// //FIXME: Please implement me. -// } -// void erase(const Edge k) -// { -// //FIXME: Please implement me. -// } + void erase(const Node k) { } void set(Node n, T a) { container[n.n]=a; } T get(Node n) const { return container[n.n]; } T& operator[](Node n) { return container[n.n]; } const T& 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 DynMaps void update(T a) {} //Useless for DynMaps }; - template class DynEdgeMap : public DynMapBase + template class EdgeMap : public DynMapBase { std::vector container; @@ -339,14 +395,39 @@ typedef T ValueType; typedef Edge KeyType; - DynEdgeMap(const SmartGraph &_G) : + 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); } - ~DynEdgeMap() + 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; @@ -365,21 +446,158 @@ { if(k.n>=int(container.size())) container.resize(k.n+1); } - void erase(const Edge k) - { - //FIXME: Please implement me. - } + void erase(const Edge k) { } void set(Edge n, T a) { container[n.n]=a; } T get(Edge n) const { return container[n.n]; } T& operator[](Edge n) { return container[n.n]; } const T& 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. You can define edge maps which + ///stores a common value for the edge pairs. The usual edge maps can be used + ///as well. + /// + ///The oppositely directed edge can also be obtained easily. + + class SymSmartGraph : public SmartGraph + { + public: + 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; + } + + Edge opposite(Edge e) const + { + Edge f; + f.idref() = e.idref() - 2*(e.idref()%2) + 1; + return f; + } + + template class SymEdgeMap : public DynMapBase + { + std::vector container; + + public: + typedef T ValueType; + typedef Edge KeyType; + + SymEdgeMap(const SmartGraph &_G) : + DynMapBase(_G), container(_G.maxEdgeId()/2) + { + G->dyn_edge_maps.push_back(this); + } + SymEdgeMap(const SmartGraph &_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=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.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]; } + T& operator[](Edge n) { return container[n.idref()/2]; } + const T& 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