# HG changeset patch # User alpar # Date 1079218387 0 # Node ID 259540358bbfb5db023977c8043201ee8c6210f4 # Parent 08735c8704cdde258118bd13941bf539b73e034d Dynamic maps became the defaults. Maps got copy constructors and operator=. Also work between different types. SymSmartGraph added smart_graph_demo.cc was extended. 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 diff -r 08735c8704cd -r 259540358bbf src/work/alpar/smart_graph_demo.cc --- a/src/work/alpar/smart_graph_demo.cc Sat Mar 13 22:49:54 2004 +0000 +++ b/src/work/alpar/smart_graph_demo.cc Sat Mar 13 22:53:07 2004 +0000 @@ -6,8 +6,8 @@ using namespace hugo; -//typedef SmartGraph Graph; -typedef EmptyGraph Graph; +typedef SmartGraph Graph; +//typedef GraphSkeleton Graph; Graph::OutEdgeIt safeFirstOut(const Graph &G, Graph::Node n) @@ -26,42 +26,99 @@ typedef Graph::NodeIt NodeIt; Graph G; - NodeIt n; + + { + NodeIt n; + for(int i=0;i<10;i++) G.addNode(); + for(G.first(n);G.valid(n);G.next(n)) + for(NodeIt m(G);m!=INVALID;G.next(m)) + if(n!=m) G.addEdge(n,m); + + OutEdgeIt e = safeFirstOut(G,n); + OutEdgeIt f = safeFirstOut(G,NodeIt(G)); + + + InEdgeIt i(INVALID), j; + InEdgeIt ii(i); + ii=G.first(i,n); + ii=G.next(i); + + OutEdgeIt o(INVALID), oo; + OutEdgeIt ooo(oo); + oo=G.first(o,n); + oo=G.next(o); + + EdgeIt ei(INVALID), eie; + EdgeIt eiee(ei); + eie=G.first(ei); + eie=G.next(ei); + + Edge eee(i); + eee=o; + eee=eie; + + + bool tm; + tm = G.valid(n) && G.valid(i) && G.valid(o) && G.valid(ei); + + std::vector v(10); + std::vector w(10,INVALID); + + } + + // Test of maps + G.clear(); + for(int i=0;i<10;i++) G.addNode(); - for(G.first(n);G.valid(n);G.next(n)) - for(NodeIt m(G);m!=INVALID;G.next(m)) - if(n!=m) G.addEdge(n,m); + for(NodeIt i(G);G.valid(i);G.next(i)) + for(NodeIt j(G);G.valid(j);G.next(j)) + if(i n(G); + int count=0; + for(NodeIt i(G);G.valid(i);G.next(i)) n[i]=count++; + + Graph::NodeMap nn=n; + Graph::NodeMap dd=n; - OutEdgeIt e = safeFirstOut(G,n); - OutEdgeIt f = safeFirstOut(G,NodeIt(G)); + n = nn; + dd = nn; + + Graph::EdgeMap emap(G); - InEdgeIt i(INVALID), j; - InEdgeIt ii(i); - ii=G.first(i,n); - ii=G.next(i); + // Test of SymSmartGraph - OutEdgeIt o(INVALID), oo; - OutEdgeIt ooo(oo); - oo=G.first(o,n); - oo=G.next(o); + { + typedef SymSmartGraph Graph; + typedef Graph::Edge Edge; + typedef Graph::InEdgeIt InEdgeIt; + typedef Graph::OutEdgeIt OutEdgeIt; + typedef Graph::EdgeIt EdgeIt; + typedef Graph::Node Node; + typedef Graph::NodeIt NodeIt; + + Graph G; + + for(int i=0;i<10;i++) G.addNode(); + for(NodeIt i(G);G.valid(i);G.next(i)) + for(NodeIt j(G);G.valid(j);G.next(j)) + if(i v(10); - std::vector w(10,INVALID); + Graph::EdgeMap em(G); + Graph::SymEdgeMap sm(G); + for(EdgeIt e(G);G.valid(e);G.next(e)) em[e]=G.id(e); + for(EdgeIt e(G);G.valid(e);G.next(e)) + if(G.tail(e)" << G.id(G.head(e)) + << ": id=" << G.id(e) << " oppid=" << G.id(G.opposite(e)) + << " em=" << em[e] + << " sm=" << sm[e] << "\n"; + + } }