[Lemon-commits] [lemon_svn] alpar: r261 - hugo/trunk/src/work/alpar
Lemon SVN
svn at lemon.cs.elte.hu
Mon Nov 6 20:38:24 CET 2006
Author: alpar
Date: Sat Mar 13 23:53:07 2004
New Revision: 261
Modified:
hugo/trunk/src/work/alpar/smart_graph.h
hugo/trunk/src/work/alpar/smart_graph_demo.cc
Log:
Dynamic maps became the defaults.
Maps got copy constructors and operator=. Also work between different types.
SymSmartGraph added
smart_graph_demo.cc was extended.
Modified: hugo/trunk/src/work/alpar/smart_graph.h
==============================================================================
--- hugo/trunk/src/work/alpar/smart_graph.h (original)
+++ hugo/trunk/src/work/alpar/smart_graph.h Sat Mar 13 23:53:07 2004
@@ -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 <vector>
#include <limits.h>
@@ -10,6 +10,10 @@
namespace hugo {
+ class SymSmartGraph;
+
+ // template<typename T> class SymSmartGraph::SymEdgeMap;
+
class SmartGraph {
struct NodeT
@@ -28,10 +32,12 @@
std::vector<EdgeT> edges;
+ protected:
+
template <typename Key> 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 <typename T> class DynEdgeMap;
- template <typename T> class DynEdgeMap;
+ template <typename T> class EdgeMap;
+ template <typename T> class EdgeMap;
class Node;
class Edge;
- protected:
+ // protected:
+ // HELPME:
+ public:
+ ///\bug It must be public because of SymEdgeMap.
+ ///
mutable std::vector<DynMapBase<Node> * > dyn_node_maps;
+ ///\bug It must be public because of SymEdgeMap.
+ ///
mutable std::vector<DynMapBase<Edge> * > dyn_edge_maps;
public:
@@ -168,7 +181,6 @@
class Node {
friend class SmartGraph;
template <typename T> friend class NodeMap;
- template <typename T> friend class DynNodeMap;
friend class Edge;
friend class OutEdgeIt;
@@ -197,7 +209,9 @@
class Edge {
friend class SmartGraph;
template <typename T> friend class EdgeMap;
- template <typename T> friend class DynEdgeMap;
+
+ //template <typename T> 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<i.n;}
+ ///\bug This is a workaround until somebody tells me how to
+ ///make class \c SymSmartGraph::SymEdgeMap friend of Edge
+ int &idref() {return n;}
+ const int &idref() const {return n;}
};
class EdgeIt : public Edge {
@@ -220,6 +238,9 @@
EdgeIt(const SmartGraph& G) : Edge(G.edges.size()-1) { }
EdgeIt (Invalid i) : Edge(i) { }
EdgeIt() : Edge() { }
+ ///\bug This is a workaround until somebody tells me how to
+ ///make class \c SymSmartGraph::SymEdgeMap friend of Edge
+ int &idref() {return n;}
};
class OutEdgeIt : public Edge {
@@ -242,43 +263,44 @@
// Map types
- template <typename T>
- class NodeMap {
- const SmartGraph& G;
- std::vector<T> 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 <typename T>
- class EdgeMap {
- const SmartGraph& G;
- std::vector<T> 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); }
- };
+// // Static Maps are not necessary.
+// template <typename T>
+// class NodeMap {
+// const SmartGraph& G;
+// std::vector<T> 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 <typename T>
+// class EdgeMap {
+// const SmartGraph& G;
+// std::vector<T> 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 <typename T> class DynNodeMap : public DynMapBase<Node>
+ template <typename T> class NodeMap : public DynMapBase<Node>
{
std::vector<T> container;
@@ -286,14 +308,38 @@
typedef T ValueType;
typedef Node KeyType;
- DynNodeMap(const SmartGraph &_G) :
+ NodeMap(const SmartGraph &_G) :
DynMapBase<Node>(_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<Node>(_G), container(_G.maxNodeId(),t)
+ {
+ G->dyn_node_maps.push_back(this);
+ }
+
+ NodeMap(const NodeMap<T> &m) :
+ DynMapBase<Node>(*m.G), container(m.container)
+ {
+ G->dyn_node_maps.push_back(this);
+ }
+
+ template<typename TT> friend class NodeMap;
+
+ ///\todo It can copy between different types.
+ ///
+ template<typename TT> NodeMap(const NodeMap<TT> &m) :
+ DynMapBase<Node>(*m.G)
+ {
+ G->dyn_node_maps.push_back(this);
+ typename std::vector<TT>::const_iterator i;
+ for(typename std::vector<TT>::const_iterator i=m.container.begin();
+ i!=m.container.end();
+ i++)
+ container.push_back(*i);
+ }
+ ~NodeMap()
{
if(G) {
std::vector<DynMapBase<Node>* >::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<T>& operator=(const NodeMap<T> &m)
+ {
+ container = m.container;
+ return *this;
+ }
+ template<typename TT>
+ const NodeMap<T>& operator=(const NodeMap<TT> &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 <typename T> class DynEdgeMap : public DynMapBase<Edge>
+ template <typename T> class EdgeMap : public DynMapBase<Edge>
{
std::vector<T> container;
@@ -339,14 +395,39 @@
typedef T ValueType;
typedef Edge KeyType;
- DynEdgeMap(const SmartGraph &_G) :
+ EdgeMap(const SmartGraph &_G) :
DynMapBase<Edge>(_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<Edge>(_G), container(_G.maxEdgeId(),t)
+ {
+ G->dyn_edge_maps.push_back(this);
+ }
+ EdgeMap(const EdgeMap<T> &m) :
+ DynMapBase<Edge>(*m.G), container(m.container)
+ {
+ G->dyn_node_maps.push_back(this);
+ }
+
+ template<typename TT> friend class EdgeMap;
+
+ ///\todo It can copy between different types.
+ ///
+ template<typename TT> EdgeMap(const EdgeMap<TT> &m) :
+ DynMapBase<Edge>(*m.G)
+ {
+ G->dyn_node_maps.push_back(this);
+ typename std::vector<TT>::const_iterator i;
+ for(typename std::vector<TT>::const_iterator i=m.container.begin();
+ i!=m.container.end();
+ i++)
+ container.push_back(*i);
+ }
+ ~EdgeMap()
{
if(G) {
std::vector<DynMapBase<Edge>* >::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<T>& operator=(const EdgeMap<T> &m)
+ {
+ container = m.container;
+ return *this;
+ }
+ template<typename TT>
+ const EdgeMap<T>& operator=(const EdgeMap<TT> &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 <typename T> class SymEdgeMap : public DynMapBase<Edge>
+ {
+ std::vector<T> container;
+
+ public:
+ typedef T ValueType;
+ typedef Edge KeyType;
+
+ SymEdgeMap(const SmartGraph &_G) :
+ DynMapBase<Edge>(_G), container(_G.maxEdgeId()/2)
+ {
+ G->dyn_edge_maps.push_back(this);
+ }
+ SymEdgeMap(const SmartGraph &_G,const T &t) :
+ DynMapBase<Edge>(_G), container(_G.maxEdgeId()/2,t)
+ {
+ G->dyn_edge_maps.push_back(this);
+ }
+
+ SymEdgeMap(const SymEdgeMap<T> &m) :
+ DynMapBase<SymEdge>(*m.G), container(m.container)
+ {
+ G->dyn_node_maps.push_back(this);
+ }
+
+ // template<typename TT> friend class SymEdgeMap;
+
+ ///\todo It can copy between different types.
+ ///
+
+ template<typename TT> SymEdgeMap(const SymEdgeMap<TT> &m) :
+ DynMapBase<SymEdge>(*m.G)
+ {
+ G->dyn_node_maps.push_back(this);
+ typename std::vector<TT>::const_iterator i;
+ for(typename std::vector<TT>::const_iterator i=m.container.begin();
+ i!=m.container.end();
+ i++)
+ container.push_back(*i);
+ }
+
+ ~SymEdgeMap()
+ {
+ if(G) {
+ std::vector<DynMapBase<Edge>* >::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<T>& operator=(const SymEdgeMap<T> &m)
+ {
+ container = m.container;
+ return *this;
+ }
+ template<typename TT>
+ const SymEdgeMap<T>& operator=(const SymEdgeMap<TT> &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
Modified: hugo/trunk/src/work/alpar/smart_graph_demo.cc
==============================================================================
--- hugo/trunk/src/work/alpar/smart_graph_demo.cc (original)
+++ hugo/trunk/src/work/alpar/smart_graph_demo.cc Sat Mar 13 23:53:07 2004
@@ -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;
-
-
- 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));
+ {
+ NodeIt n;
- InEdgeIt i(INVALID), j;
- InEdgeIt ii(i);
- ii=G.first(i,n);
- ii=G.next(i);
+ 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<InEdgeIt> v(10);
+ std::vector<InEdgeIt> w(10,INVALID);
+
+ }
- 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);
+ // Test of maps
- Edge eee(i);
- eee=o;
- eee=eie;
-
+ G.clear();
- bool tm;
- tm = G.valid(n) && G.valid(i) && G.valid(o) && G.valid(ei);
-
- std::vector<InEdgeIt> v(10);
- std::vector<InEdgeIt> w(10,INVALID);
+ 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<j) G.addEdge(i,j); //The iterators are comparable
+
+ Graph::NodeMap<int> n(G);
+ int count=0;
+ for(NodeIt i(G);G.valid(i);G.next(i)) n[i]=count++;
+
+ Graph::NodeMap<int> nn=n;
+ Graph::NodeMap<double> dd=n;
+
+ n = nn;
+
+ dd = nn;
+
+ Graph::EdgeMap<int> emap(G);
+
+ // Test of SymSmartGraph
+
+ {
+ 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<j) G.addEdge(i,j); //The iterators are comparable
+
+ Graph::EdgeMap<int> em(G);
+ Graph::SymEdgeMap<int> 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.head(e)) sm[e]=G.id(e);
+
+ for(EdgeIt e(G);G.valid(e);G.next(e))
+ std::cout << G.id(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";
+
+ }
}
More information about the Lemon-commits
mailing list