[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