[Lemon-commits] [lemon_svn] deba: r1220 - in hugo/trunk/src: hugo hugo/skeletons test

Lemon SVN svn at lemon.cs.elte.hu
Mon Nov 6 20:43:57 CET 2006


Author: deba
Date: Sun Sep 26 23:43:38 2004
New Revision: 1220

Added:
   hugo/trunk/src/hugo/skeletons/sym_graph.h
   hugo/trunk/src/test/sym_graph_test.cc
   hugo/trunk/src/test/sym_graph_test.h
Removed:
   hugo/trunk/src/hugo/sym_map.h
Modified:
   hugo/trunk/src/hugo/Makefile.am
   hugo/trunk/src/hugo/default_map.h
   hugo/trunk/src/hugo/list_graph.h
   hugo/trunk/src/hugo/map_bits.h
   hugo/trunk/src/hugo/map_defines.h
   hugo/trunk/src/hugo/map_registry.h
   hugo/trunk/src/hugo/smart_graph.h
   hugo/trunk/src/test/Makefile.am
   hugo/trunk/src/test/graph_test.cc
   hugo/trunk/src/test/test_tools.h

Log:
New symmetric Graph concept.
New symmetric list and smart graph.
Symmetric Graph tests based on the Graph Tests.


Modified: hugo/trunk/src/hugo/Makefile.am
==============================================================================
--- hugo/trunk/src/hugo/Makefile.am	(original)
+++ hugo/trunk/src/hugo/Makefile.am	Sun Sep 26 23:43:38 2004
@@ -18,12 +18,11 @@
 	map_registry.h                                                  \
 	map_bits.h							\
 	maps.h								\
-	min_cost_flow.h                                                \
+	min_cost_flow.h                                                 \
 	suurballe.h                                                     \
 	preflow.h                                                       \
 	path.h                                                          \
 	smart_graph.h							\
-	sym_map.h                                                       \
 	time_measure.h							\
 	unionfind.h							\
 	vector_map.h                                                    \
@@ -31,5 +30,6 @@
 
 noinst_HEADERS =							\
 	skeletons/graph.h						\
+	skeletons/sym_graph.h                                           \
 	skeletons/maps.h                                                \
 	skeletons/path.h

Modified: hugo/trunk/src/hugo/default_map.h
==============================================================================
--- hugo/trunk/src/hugo/default_map.h	(original)
+++ hugo/trunk/src/hugo/default_map.h	Sun Sep 26 23:43:38 2004
@@ -59,12 +59,9 @@
   : Parent(static_cast<const Parent&>(copy)) {} \
 template <typename TT> \
 DefaultMap(const DefaultMap<MapRegistry, TT>& copy) \
-  : { \
-  Parent::MapBase::operator= \
-    (static_cast<const typename Parent::MapBase&>(copy)); \
+  : Parent(*copy.getGraph()) { \
   if (Parent::getGraph()) { \
     for (typename Parent::KeyIt it(*Parent::getGraph()); it!=INVALID; ++it) {\
-      Parent::add(it); \
       Parent::operator[](it) = copy[it]; \
     } \
   } \

Modified: hugo/trunk/src/hugo/list_graph.h
==============================================================================
--- hugo/trunk/src/hugo/list_graph.h	(original)
+++ hugo/trunk/src/hugo/list_graph.h	Sun Sep 26 23:43:38 2004
@@ -29,8 +29,6 @@
 #include <hugo/map_registry.h>
 #include <hugo/array_map.h>
 
-#include <hugo/sym_map.h>
-
 #include <hugo/map_defines.h>
 
 
@@ -438,7 +436,7 @@
   ///
   ///\todo this date structure need some reconsiderations. Maybe it
   ///should be implemented independently from ListGraph.
-  
+  /*  
   class SymListGraph : public ListGraph
   {
   public:
@@ -483,8 +481,402 @@
       ListGraph::erase(f);
       ListGraph::erase(e);
     }    
-  };
+    };*/
+
+  class SymListGraph : public ListGraph {
+    typedef ListGraph Parent;
+  public:
+
+    typedef SymListGraph Graph;
+
+    typedef ListGraph::Node Node;
+    typedef ListGraph::NodeIt NodeIt;
+
+    class SymEdge;
+    class SymEdgeIt;
+
+    class Edge;
+    class EdgeIt;
+    class OutEdgeIt;
+    class InEdgeIt;
+
+    template <typename Value>
+    class NodeMap : public Parent::NodeMap<Value> {      
+    public:
+      NodeMap(const SymListGraph& g) 
+	: SymListGraph::Parent::NodeMap<Value>(g) {}
+      NodeMap(const SymListGraph& g, Value v) 
+	: SymListGraph::Parent::NodeMap<Value>(g, v) {}
+      template<typename TT> 
+      NodeMap(const NodeMap<TT>& copy) 
+	: SymListGraph::Parent::NodeMap<Value>(copy) { }            
+    };
+
+    template <typename Value>
+    class SymEdgeMap : public Parent::EdgeMap<Value> {
+    public:
+      typedef SymEdge KeyType;
+
+      SymEdgeMap(const SymListGraph& g) 
+	: SymListGraph::Parent::EdgeMap<Value>(g) {}
+      SymEdgeMap(const SymListGraph& g, Value v) 
+	: SymListGraph::Parent::EdgeMap<Value>(g, v) {}
+      template<typename TT> 
+      SymEdgeMap(const SymEdgeMap<TT>& copy) 
+	: SymListGraph::Parent::EdgeMap<Value>(copy) { }
+      
+    };
+
+    // Create edge map registry.
+    CREATE_EDGE_MAP_REGISTRY;
+    // Create edge maps.
+    CREATE_EDGE_MAP(ArrayMap);
+
+    class Edge {
+      friend class SymListGraph;
+      friend class SymListGraph::EdgeIt;
+      friend class SymListGraph::OutEdgeIt;
+      friend class SymListGraph::InEdgeIt;
+      
+    protected:
+      int id;
+
+      Edge(int pid) { id = pid; }
+
+    public:
+      /// An Edge with id \c n.
+
+      Edge() { }
+      Edge (Invalid) { id = -1; }
+
+      operator SymEdge(){ return SymEdge(id >> 1);}
+      
+      bool operator==(const Edge i) const {return id == i.id;}
+      bool operator!=(const Edge i) const {return id != i.id;}
+      bool operator<(const Edge i) const {return id < i.id;}
+      //      ///Validity check
+      //      operator bool() { return n!=-1; }
+    };
+
+    class SymEdge : public ListGraph::Edge {
+      friend class SymListGraph;
+      friend class SymListGraph::Edge;
+      typedef ListGraph::Edge Parent;
+
+    protected:      
+      SymEdge(int pid) : Parent(pid) {}
+    public:
+
+      SymEdge() { }
+      SymEdge(const ListGraph::Edge& i) : Parent(i) {} 
+      SymEdge (Invalid) : Parent(INVALID) {}
+
+    };
+
+    class OutEdgeIt {
+      Parent::OutEdgeIt out;
+      Parent::InEdgeIt in;      
+    public: 
+      OutEdgeIt() {}
+      OutEdgeIt(const SymListGraph& g, Edge e) { 
+	if (e.id & 1 == 0) {	
+	  out = Parent::OutEdgeIt(g, SymEdge(e));
+	  in = Parent::InEdgeIt(g, g.tail(e));
+	} else {
+	  out = Parent::OutEdgeIt(INVALID);
+	  in = Parent::InEdgeIt(g, SymEdge(e));
+	}
+      }
+      OutEdgeIt (Invalid i) : out(INVALID), in(INVALID) { }
+
+      OutEdgeIt(const SymListGraph& g, const Node v)
+	: out(g, v), in(g, v) {}
+      OutEdgeIt &operator++() { 
+	if (out != INVALID) {
+	  ++out;
+	} else {
+	  ++in;
+	}
+	return *this; 
+      }
+
+      operator Edge() const {
+	if (out == INVALID && in == INVALID) return INVALID;
+	return out != INVALID ? forward(out) : backward(in);
+      }
+
+      bool operator==(const Edge i) const {return Edge(*this) == i;}
+      bool operator!=(const Edge i) const {return Edge(*this) != i;}
+      bool operator<(const Edge i) const {return Edge(*this) < i;}
+    };
+
+    class InEdgeIt {
+      Parent::OutEdgeIt out;
+      Parent::InEdgeIt in;      
+    public: 
+      InEdgeIt() {}
+      InEdgeIt(const SymListGraph& g, Edge e) { 
+	if (e.id & 1 == 0) {	
+	  out = Parent::OutEdgeIt(g, SymEdge(e));
+	  in = Parent::InEdgeIt(g, g.tail(e));
+	} else {
+	  out = Parent::OutEdgeIt(INVALID);
+	  in = Parent::InEdgeIt(g, SymEdge(e));
+	}
+      }
+      InEdgeIt (Invalid i) : out(INVALID), in(INVALID) { }
+
+      InEdgeIt(const SymListGraph& g, const Node v)
+	: out(g, v), in(g, v) {}
+
+      InEdgeIt &operator++() { 
+	if (out != INVALID) {
+	  ++out;
+	} else {
+	  ++in;
+	}
+	return *this; 
+      }
+
+      operator Edge() const {
+	if (out == INVALID && in == INVALID) return INVALID;
+	return out != INVALID ? backward(out) : forward(in);
+      }
+
+      bool operator==(const Edge i) const {return Edge(*this) == i;}
+      bool operator!=(const Edge i) const {return Edge(*this) != i;}
+      bool operator<(const Edge i) const {return Edge(*this) < i;}
+    };
+
+    class SymEdgeIt : public Parent::EdgeIt {
+
+    public:
+      SymEdgeIt() {}
+
+      SymEdgeIt(const SymListGraph& g) 
+	: SymListGraph::Parent::EdgeIt(g) {}
+
+      SymEdgeIt(const SymListGraph& g, SymEdge e) 
+	: SymListGraph::Parent::EdgeIt(g, e) {}
+
+      SymEdgeIt(Invalid i) 
+	: SymListGraph::Parent::EdgeIt(INVALID) {}
+
+      SymEdgeIt& operator++() {
+	SymListGraph::Parent::EdgeIt::operator++();
+	return *this;
+      }
+
+      operator SymEdge() const {
+	return SymEdge
+	  (static_cast<const SymListGraph::Parent::EdgeIt&>(*this));
+      }
+      bool operator==(const SymEdge i) const {return SymEdge(*this) == i;}
+      bool operator!=(const SymEdge i) const {return SymEdge(*this) != i;}
+      bool operator<(const SymEdge i) const {return SymEdge(*this) < i;}
+    };
+
+    class EdgeIt {
+      SymEdgeIt it;
+      bool fw;
+    public:
+      EdgeIt(const SymListGraph& g) : it(g), fw(true) {}
+      EdgeIt (Invalid i) : it(i) { }
+      EdgeIt(const SymListGraph& g, Edge e) 
+	: it(g, SymEdge(e)), fw(id(e) & 1 == 0) { }
+      EdgeIt() { }
+      EdgeIt& operator++() {
+	fw = !fw;
+	if (fw) ++it;
+	return *this;
+      }
+      operator Edge() const {
+	if (it == INVALID) return INVALID;
+	return fw ? forward(it) : backward(it);
+      }
+      bool operator==(const Edge i) const {return Edge(*this) == i;}
+      bool operator!=(const Edge i) const {return Edge(*this) != i;}
+      bool operator<(const Edge i) const {return Edge(*this) < i;}
+
+    };
+
+    ///Number of nodes.
+    int nodeNum() const { return Parent::nodeNum(); }
+    ///Number of edges.
+    int edgeNum() const { return 2*Parent::edgeNum(); }
+    ///Number of symmetric edges.
+    int symEdgeNum() const { return Parent::edgeNum(); }
 
+    ///Set the expected maximum number of edges.
+
+    ///With this function, it is possible to set the expected number of edges.
+    ///The use of this fasten the building of the graph and makes
+    ///it possible to avoid the superfluous memory allocation.
+    void reserveSymEdge(int n) { Parent::reserveEdge(n); };
+    
+    /// Maximum node ID.
+    
+    /// Maximum node ID.
+    ///\sa id(Node)
+    int maxNodeId() const { return Parent::maxNodeId(); } 
+    /// Maximum edge ID.
+    
+    /// Maximum edge ID.
+    ///\sa id(Edge)
+    int maxEdgeId() const { return 2*Parent::maxEdgeId(); }
+    /// Maximum symmetric edge ID.
+    
+    /// Maximum symmetric edge ID.
+    ///\sa id(SymEdge)
+    int maxSymEdgeId() const { return Parent::maxEdgeId(); }
+
+
+    Node tail(Edge e) const { 
+      return e.id & 1 == 0 ? 
+	Parent::tail(SymEdge(e)) : Parent::head(SymEdge(e)); 
+    }
+
+    Node head(Edge e) const { 
+      return e.id & 1 == 0 ? 
+	Parent::head(SymEdge(e)) : Parent::tail(SymEdge(e)); 
+    }
+
+    Node tail(SymEdge e) const { 
+      return Parent::tail(e); 
+    }
+
+    Node head(SymEdge e) const { 
+      return Parent::head(e); 
+    }
+
+    NodeIt& first(NodeIt& v) const { 
+      v=NodeIt(*this); return v; }
+    EdgeIt& first(EdgeIt& e) const { 
+      e=EdgeIt(*this); return e; }
+    SymEdgeIt& first(SymEdgeIt& e) const {
+      e=SymEdgeIt(*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; }
+
+    /// Node ID.
+    
+    /// The ID of a valid Node is a nonnegative integer not greater than
+    /// \ref maxNodeId(). The range of the ID's is not surely continuous
+    /// and the greatest node ID can be actually less then \ref maxNodeId().
+    ///
+    /// The ID of the \ref INVALID node is -1.
+    ///\return The ID of the node \c v. 
+    static int id(Node v) { return Parent::id(v); }
+    /// Edge ID.
+    
+    /// The ID of a valid Edge is a nonnegative integer not greater than
+    /// \ref maxEdgeId(). The range of the ID's is not surely continuous
+    /// and the greatest edge ID can be actually less then \ref maxEdgeId().
+    ///
+    /// The ID of the \ref INVALID edge is -1.
+    ///\return The ID of the edge \c e. 
+    static int id(Edge e) { return e.id; }
+
+    /// The ID of a valid SymEdge is a nonnegative integer not greater than
+    /// \ref maxSymEdgeId(). The range of the ID's is not surely continuous
+    /// and the greatest edge ID can be actually less then \ref maxSymEdgeId().
+    ///
+    /// The ID of the \ref INVALID symmetric edge is -1.
+    ///\return The ID of the edge \c e. 
+    static int id(SymEdge e) { return Parent::id(e); }
+
+    /// Adds a new node to the graph.
+
+    /// \warning It adds the new node to the front of the list.
+    /// (i.e. the lastly added node becomes the first.)
+    Node addNode() {
+      return Parent::addNode();
+    }
+    
+    SymEdge addEdge(Node u, Node v) {
+      SymEdge se = Parent::addEdge(u, v);
+      edge_maps.add(forward(se));
+      edge_maps.add(backward(se));
+      return se;
+    }
+    
+    /// Finds an edge between two nodes.
+
+    /// Finds an edge from node \c u to node \c v.
+    ///
+    /// If \c prev is \ref INVALID (this is the default value), then
+    /// It finds the first edge from \c u to \c v. Otherwise it looks for
+    /// the next edge from \c u to \c v after \c prev.
+    /// \return The found edge or INVALID if there is no such an edge.
+    Edge findEdge(Node u, Node v, Edge prev = INVALID) 
+    {     
+      if (prev == INVALID || id(prev) & 1 == 0) {
+	SymEdge se = Parent::findEdge(u, v, SymEdge(prev));
+	if (se != INVALID) return forward(se);
+      } else {
+	SymEdge se = Parent::findEdge(v, u, SymEdge(prev));
+	if (se != INVALID) return backward(se);	
+      }
+      return INVALID;
+    }
+
+    /// Finds an symmetric edge between two nodes.
+
+    /// Finds an symmetric edge from node \c u to node \c v.
+    ///
+    /// If \c prev is \ref INVALID (this is the default value), then
+    /// It finds the first edge from \c u to \c v. Otherwise it looks for
+    /// the next edge from \c u to \c v after \c prev.
+    /// \return The found edge or INVALID if there is no such an edge.
+
+//     SymEdge findEdge(Node u, Node v, SymEdge prev = INVALID) 
+//     {     
+//       if (prev == INVALID || id(prev) & 1 == 0) {
+// 	SymEdge se = Parent::findEdge(u, v, SymEdge(prev));
+// 	if (se != INVALID) return se;
+//       } else {
+// 	SymEdge se = Parent::findEdge(v, u, SymEdge(prev));
+// 	if (se != INVALID) return se;	
+//       }
+//       return INVALID;
+//     }
+    
+  public:
+
+    void erase(Node n) {      
+      for (OutEdgeIt it(*this, n); it != INVALID; ++it) {
+	edge_maps.erase(it);
+	edge_maps.erase(opposite(it));
+      }
+      Parent::erase(n);
+    }
+    
+    void erase(SymEdge e) { 
+      edge_maps.erase(forward(e));
+      edge_maps.erase(backward(e));
+      Parent::erase(e); 
+    };
+
+    void clear() {
+      edge_maps.clear();
+      Parent::clear();
+    }
+
+    static Edge opposite(Edge e) {
+      return Edge(id(e) ^ 1);
+    }
+
+    static Edge forward(SymEdge e) {
+      return Edge(id(e) << 1);
+    }
+
+    static Edge backward(SymEdge e) {
+      return Edge((id(e) << 1) & 1);
+    }
+
+  };
 
   ///A graph class containing only nodes.
 

Modified: hugo/trunk/src/hugo/map_bits.h
==============================================================================
--- hugo/trunk/src/hugo/map_bits.h	(original)
+++ hugo/trunk/src/hugo/map_bits.h	Sun Sep 26 23:43:38 2004
@@ -54,10 +54,10 @@
   template <typename Graph>
   struct KeyInfo<Graph, typename Graph::SymEdgeIt> {
     static int maxId(const Graph& graph) {
-      return graph.maxEdgeId() >> 1;
+      return graph.maxSymEdgeId();
     }
-    static int id(const Graph& graph, const typename Graph::Edge& edge) {
-      return graph.id(edge) >> 1;
+    static int id(const Graph& graph, const typename Graph::SymEdge& edge) {
+      return graph.id(edge);
     }
   };
 

Modified: hugo/trunk/src/hugo/map_defines.h
==============================================================================
--- hugo/trunk/src/hugo/map_defines.h	(original)
+++ hugo/trunk/src/hugo/map_defines.h	Sun Sep 26 23:43:38 2004
@@ -114,8 +114,7 @@
 /** This macro creates MapRegistry for Symmetric Edge Maps.
  */
 #define CREATE_SYM_EDGE_MAP_REGISTRY \
-typedef SymEdgeIt<Graph, Edge, EdgeIt> SymEdgeIt; \
-typedef MapRegistry<Graph, Edge, SymEdgeIt> SymEdgeMapRegistry; \
+typedef MapRegistry<Graph, SymEdge, SymEdgeIt> SymEdgeMapRegistry; \
 mutable SymEdgeMapRegistry sym_edge_maps;
 
 
@@ -127,9 +126,9 @@
  */
 #define CREATE_SYM_EDGE_MAP(DynMap) \
 template <typename Value> \
-class SymEdgeMap : public SymMap<DynMap, SymEdgeMapRegistry, Value> { \
+class SymEdgeMap : public DynMap<SymEdgeMapRegistry, Value> { \
 public: \
-typedef SymMap<DynMap, SymEdgeMapRegistry, Value> Parent; \
+typedef DynMap<SymEdgeMapRegistry, Value> Parent; \
 \
 SymEdgeMap(const typename Parent::Graph& g) \
   : Parent(g, g.sym_edge_maps) {} \

Modified: hugo/trunk/src/hugo/map_registry.h
==============================================================================
--- hugo/trunk/src/hugo/map_registry.h	(original)
+++ hugo/trunk/src/hugo/map_registry.h	Sun Sep 26 23:43:38 2004
@@ -252,7 +252,7 @@
     /**
      * Notify all the registered maps about a Key added.
      */
-    void add(KeyType& key) {
+    void add(const KeyType& key) {
       typename Container::iterator it;
       for (it = container.begin(); it != container.end(); ++it) {
 	(*it)->add(key);
@@ -262,7 +262,7 @@
     /**
      * Notify all the registered maps about a Key erased.
      */ 
-    void erase(KeyType& key) {
+    void erase(const KeyType& key) {
       typename Container::iterator it;
       for (it = container.begin(); it != container.end(); ++it) {
 	(*it)->erase(key);

Added: hugo/trunk/src/hugo/skeletons/sym_graph.h
==============================================================================
--- (empty file)
+++ hugo/trunk/src/hugo/skeletons/sym_graph.h	Sun Sep 26 23:43:38 2004
@@ -0,0 +1,653 @@
+/* -*- C++ -*-
+ * src/hugo/skeletons/graph.h - Part of HUGOlib, a generic C++ optimization library
+ *
+ * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Combinatorial Optimization Research Group, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef HUGO_SKELETON_SYM_GRAPH_H
+#define HUGO_SKELETON_SYM_GRAPH_H
+
+///\ingroup skeletons
+///\file
+///\brief Declaration of SymGraph.
+
+#include <hugo/invalid.h>
+#include <hugo/skeletons/graph.h>
+#include <hugo/skeletons/maps.h>
+
+namespace hugo {
+  namespace skeleton {
+    
+    /// \addtogroup skeletons
+    /// @{
+
+    /// An empty static graph class.
+  
+    /// This class provides all the common features of a symmetric
+    /// graph structure, however completely without implementations and 
+    /// real data structures behind the interface.
+    /// All graph algorithms should compile with this class, but it will not
+    /// run properly, of course.
+    ///
+    /// It can be used for checking the interface compatibility,
+    /// or it can serve as a skeleton of a new symmetric graph structure.
+    /// 
+    /// Also, you will find here the full documentation of a certain graph
+    /// feature, the documentation of a real symmetric graph imlementation
+    /// like @ref SymListGraph or
+    /// @ref SymSmartGraph will just refer to this structure.
+    class StaticSymGraph
+    {
+    public:
+      /// Defalult constructor.
+
+      /// Defalult constructor.
+      ///
+      StaticSymGraph() { }
+      ///Copy consructor.
+
+//       ///\todo It is not clear, what we expect from a copy constructor.
+//       ///E.g. How to assign the nodes/edges to each other? What about maps?
+//       StaticGraph(const StaticGraph& g) { }
+
+      /// The base type of node iterators, 
+      /// or in other words, the trivial node iterator.
+
+      /// This is the base type of each node iterator,
+      /// thus each kind of node iterator converts to this.
+      /// More precisely each kind of node iterator should be inherited 
+      /// from the trivial node iterator.
+      class Node {
+      public:
+	/// Default constructor
+
+	/// @warning The default constructor sets the iterator
+	/// to an undefined value.
+	Node() { }
+	/// Copy constructor.
+
+	/// Copy constructor.
+	///
+	Node(const Node&) { }
+
+	/// Invalid constructor \& conversion.
+
+	/// This constructor initializes the iterator to be invalid.
+	/// \sa Invalid for more details.
+	Node(Invalid) { }
+	/// Equality operator
+
+	/// Two iterators are equal if and only if they point to the
+	/// same object or both are invalid.
+	bool operator==(Node) const { return true; }
+
+	/// Inequality operator
+	
+	/// \sa \ref operator==(Node n)
+	///
+	bool operator!=(Node) const { return true; }
+
+ 	///Comparison operator.
+
+	///This is a strict ordering between the nodes.
+	///
+	///This ordering can be different from the order in which NodeIt
+	///goes through the nodes.
+	///\todo Possibly we don't need it.
+	bool operator<(Node) const { return true; }
+      };
+    
+      /// This iterator goes through each node.
+
+      /// This iterator goes through each node.
+      /// Its usage is quite simple, for example you can count the number
+      /// of nodes in graph \c g of type \c Graph like this:
+      /// \code
+      /// int count=0;
+      /// for (Graph::NodeIt n(g); n!=INVALID; ++n) ++count;
+      /// \endcode
+      class NodeIt : public Node {
+      public:
+	/// Default constructor
+
+	/// @warning The default constructor sets the iterator
+	/// to an undefined value.
+	NodeIt() { }
+	/// Copy constructor.
+	
+	/// Copy constructor.
+	///
+	NodeIt(const NodeIt&) { }
+	/// Invalid constructor \& conversion.
+
+	/// Initialize the iterator to be invalid.
+	/// \sa Invalid for more details.
+	NodeIt(Invalid) { }
+	/// Sets the iterator to the first node.
+
+	/// Sets the iterator to the first node of \c g.
+	///
+	NodeIt(const StaticSymGraph& g) { }
+	/// Node -> NodeIt conversion.
+
+	/// Sets the iterator to the node of \c g pointed by the trivial 
+	/// iterator n.
+	/// This feature necessitates that each time we 
+	/// iterate the edge-set, the iteration order is the same.
+	NodeIt(const StaticSymGraph& g, const Node& n) { }
+	/// Next node.
+
+	/// Assign the iterator to the next node.
+	///
+	NodeIt& operator++() { return *this; }
+      };
+    
+    
+      /// The base type of the symmetric edge iterators.
+
+      /// The base type of the symmetric edge iterators.
+      ///
+      class SymEdge {
+      public:
+	/// Default constructor
+
+	/// @warning The default constructor sets the iterator
+	/// to an undefined value.
+	SymEdge() { }
+	/// Copy constructor.
+
+	/// Copy constructor.
+	///
+	SymEdge(const SymEdge&) { }
+	/// Initialize the iterator to be invalid.
+
+	/// Initialize the iterator to be invalid.
+	///
+	SymEdge(Invalid) { }
+	/// Equality operator
+
+	/// Two iterators are equal if and only if they point to the
+	/// same object or both are invalid.
+	bool operator==(SymEdge) const { return true; }
+	/// Inequality operator
+
+	/// \sa \ref operator==(Node n)
+	///
+	bool operator!=(SymEdge) const { return true; }
+ 	///Comparison operator.
+
+	///This is a strict ordering between the nodes.
+	///
+	///This ordering can be different from the order in which NodeIt
+	///goes through the nodes.
+	///\todo Possibly we don't need it.
+ 	bool operator<(SymEdge) const { return true; }
+      };
+
+
+      /// The base type of the edge iterators.
+
+      /// The base type of the edge iterators.
+      ///
+      class Edge : public SymEdge {
+      public:
+	/// Default constructor
+
+	/// @warning The default constructor sets the iterator
+	/// to an undefined value.
+	Edge() { }
+	/// Copy constructor.
+
+	/// Copy constructor.
+	///
+	Edge(const Edge&) { }
+	/// Initialize the iterator to be invalid.
+
+	/// Initialize the iterator to be invalid.
+	///
+	Edge(Invalid) { }
+	/// Equality operator
+
+	/// Two iterators are equal if and only if they point to the
+	/// same object or both are invalid.
+	bool operator==(Edge) const { return true; }
+	/// Inequality operator
+
+	/// \sa \ref operator==(Node n)
+	///
+	bool operator!=(Edge) const { return true; }
+ 	///Comparison operator.
+
+	///This is a strict ordering between the nodes.
+	///
+	///This ordering can be different from the order in which NodeIt
+	///goes through the nodes.
+	///\todo Possibly we don't need it.
+ 	bool operator<(Edge) const { return true; }
+      };
+    
+      /// This iterator goes trough the outgoing edges of a node.
+
+      /// This iterator goes trough the \e outgoing edges of a certain node
+      /// of a graph.
+      /// Its usage is quite simple, for example you can count the number
+      /// of outgoing edges of a node \c n
+      /// in graph \c g of type \c Graph as follows.
+      /// \code
+      /// int count=0;
+      /// for (Graph::OutEdgeIt e(g, n); e!=INVALID; ++e) ++count;
+      /// \endcode
+    
+      class OutEdgeIt : public Edge {
+      public:
+	/// Default constructor
+
+	/// @warning The default constructor sets the iterator
+	/// to an undefined value.
+	OutEdgeIt() { }
+	/// Copy constructor.
+
+	/// Copy constructor.
+	///
+	OutEdgeIt(const OutEdgeIt&) { }
+	/// Initialize the iterator to be invalid.
+
+	/// Initialize the iterator to be invalid.
+	///
+	OutEdgeIt(Invalid) { }
+	/// This constructor sets the iterator to first outgoing edge.
+    
+	/// This constructor set the iterator to the first outgoing edge of
+	/// node
+	///@param n the node
+	///@param g the graph
+	OutEdgeIt(const StaticSymGraph& g, const Node& n) { }
+	/// Edge -> OutEdgeIt conversion
+
+	/// Sets the iterator to the value of the trivial iterator \c e.
+	/// This feature necessitates that each time we 
+	/// iterate the edge-set, the iteration order is the same.
+	OutEdgeIt(const StaticSymGraph& g, const Edge& e) { }
+	///Next outgoing edge
+	
+	/// Assign the iterator to the next 
+	/// outgoing edge of the corresponding node.
+	OutEdgeIt& operator++() { return *this; }
+      };
+
+      /// This iterator goes trough the incoming edges of a node.
+
+      /// This iterator goes trough the \e incoming edges of a certain node
+      /// of a graph.
+      /// Its usage is quite simple, for example you can count the number
+      /// of outgoing edges of a node \c n
+      /// in graph \c g of type \c Graph as follows.
+      /// \code
+      /// int count=0;
+      /// for(Graph::InEdgeIt e(g, n); e!=INVALID; ++e) ++count;
+      /// \endcode
+
+      class InEdgeIt : public Edge {
+      public:
+	/// Default constructor
+
+	/// @warning The default constructor sets the iterator
+	/// to an undefined value.
+	InEdgeIt() { }
+	/// Copy constructor.
+
+	/// Copy constructor.
+	///
+	InEdgeIt(const InEdgeIt&) { }
+	/// Initialize the iterator to be invalid.
+
+	/// Initialize the iterator to be invalid.
+	///
+	InEdgeIt(Invalid) { }
+	/// This constructor sets the iterator to first incoming edge.
+    
+	/// This constructor set the iterator to the first incoming edge of
+	/// node
+	///@param n the node
+	///@param g the graph
+	InEdgeIt(const StaticSymGraph& g, const Node& n) { }
+	/// Edge -> InEdgeIt conversion
+
+	/// Sets the iterator to the value of the trivial iterator \c e.
+	/// This feature necessitates that each time we 
+	/// iterate the edge-set, the iteration order is the same.
+	InEdgeIt(const StaticSymGraph& g, const Edge& n) { }
+	/// Next incoming edge
+
+	/// Assign the iterator to the next inedge of the corresponding node.
+	///
+	InEdgeIt& operator++() { return *this; }
+      };
+      /// This iterator goes through each symmetric edge.
+
+      /// This iterator goes through each symmetric edge of a graph.
+      /// Its usage is quite simple, for example you can count the number
+      /// of symmetric edges in a graph \c g of type \c Graph as follows:
+      /// \code
+      /// int count=0;
+      /// for(Graph::SymEdgeIt e(g); e!=INVALID; ++e) ++count;
+      /// \endcode
+      class SymEdgeIt : public SymEdge {
+      public:
+	/// Default constructor
+
+	/// @warning The default constructor sets the iterator
+	/// to an undefined value.
+	SymEdgeIt() { }
+	/// Copy constructor.
+
+	/// Copy constructor.
+	///
+	SymEdgeIt(const SymEdgeIt&) { }
+	/// Initialize the iterator to be invalid.
+
+	/// Initialize the iterator to be invalid.
+	///
+	SymEdgeIt(Invalid) { }
+	/// This constructor sets the iterator to first edge.
+    
+	/// This constructor set the iterator to the first edge of
+	/// node
+	///@param g the graph
+	SymEdgeIt(const StaticSymGraph& g) { }
+	/// Edge -> EdgeIt conversion
+
+	/// Sets the iterator to the value of the trivial iterator \c e.
+	/// This feature necessitates that each time we 
+	/// iterate the edge-set, the iteration order is the same.
+	SymEdgeIt(const StaticSymGraph&, const SymEdge&) { } 
+    	///Next edge
+	
+	/// Assign the iterator to the next 
+	/// edge of the corresponding node.
+	SymEdgeIt& operator++() { return *this; }
+      };
+      /// This iterator goes through each edge.
+
+      /// This iterator goes through each edge of a graph.
+      /// Its usage is quite simple, for example you can count the number
+      /// of edges in a graph \c g of type \c Graph as follows:
+      /// \code
+      /// int count=0;
+      /// for(Graph::EdgeIt e(g); e!=INVALID; ++e) ++count;
+      /// \endcode
+      class EdgeIt : public Edge {
+      public:
+	/// Default constructor
+
+	/// @warning The default constructor sets the iterator
+	/// to an undefined value.
+	EdgeIt() { }
+	/// Copy constructor.
+
+	/// Copy constructor.
+	///
+	EdgeIt(const EdgeIt&) { }
+	/// Initialize the iterator to be invalid.
+
+	/// Initialize the iterator to be invalid.
+	///
+	EdgeIt(Invalid) { }
+	/// This constructor sets the iterator to first edge.
+    
+	/// This constructor set the iterator to the first edge of
+	/// node
+	///@param g the graph
+	EdgeIt(const StaticSymGraph& g) { }
+	/// Edge -> EdgeIt conversion
+
+	/// Sets the iterator to the value of the trivial iterator \c e.
+	/// This feature necessitates that each time we 
+	/// iterate the edge-set, the iteration order is the same.
+	EdgeIt(const StaticSymGraph&, const Edge&) { } 
+    	///Next edge
+	
+	/// Assign the iterator to the next 
+	/// edge of the corresponding node.
+	EdgeIt& operator++() { return *this; }
+      };
+
+      /// First node of the graph.
+
+      /// \retval i the first node.
+      /// \return the first node.
+      ///
+      NodeIt& first(NodeIt& i) const { return i; }
+
+      /// The first incoming edge.
+
+      /// The first incoming edge.
+      ///
+      InEdgeIt& first(InEdgeIt &i, Node) const { return i; }
+      /// The first outgoing edge.
+
+      /// The first outgoing edge.
+      ///
+      OutEdgeIt& first(OutEdgeIt& i, Node) const { return i; }
+      /// The first edge of the Graph.
+
+      /// The first edge of the Graph.
+      ///
+      EdgeIt& first(EdgeIt& i) const { return i; }
+      /// The first symmetric edge of the Graph.
+
+      /// The first symmetric edge of the Graph.
+      ///
+      SymEdgeIt& first(SymEdgeIt& i) const { return i; }
+
+      ///Gives back the head node of an edge.
+
+      ///Gives back the head node of an edge.
+      ///
+      Node head(Edge) const { return INVALID; }
+      ///Gives back the tail node of an edge.
+
+      ///Gives back the tail node of an edge.
+      ///
+      Node tail(Edge) const { return INVALID; }
+  
+      ///Gives back the first node of an symmetric edge.
+
+      ///Gives back the first node of an symmetric edge.
+      ///
+      Node head(SymEdge) const { return INVALID; }
+      ///Gives back the second node of an symmetric edge.
+
+      ///Gives back the second node of an symmetric edge.
+      ///
+      Node tail(SymEdge) const { return INVALID; }
+      ///Gives back the \e id of a node.
+
+      ///\warning Not all graph structures provide this feature.
+      ///
+      ///\todo Should each graph provide \c id?
+      int id(const Node&) const { return 0; }
+      ///Gives back the \e id of an edge.
+
+      ///\warning Not all graph structures provide this feature.
+      ///
+      ///\todo Should each graph provide \c id?
+      int id(const Edge&) const { return 0; }
+
+      ///\warning Not all graph structures provide this feature.
+      ///
+      ///\todo Should each graph provide \c id?
+      int id(const SymEdge&) const { return 0; }
+
+      /// .
+      
+      ///\todo Should it be in the concept?
+      ///
+      int nodeNum() const { return 0; }
+      /// .
+
+      ///\todo Should it be in the concept?
+      ///
+      int edgeNum() const { return 0; }
+
+      ///\todo Should it be in the concept?
+      ///
+      int symEdgeNum() const { return 0; }
+
+
+      /// Gives back the forward directed edge of the symmetric edge.
+      Edge forward(SymEdge) const {return INVALID;} 
+
+      /// Gives back the backward directed edge of the symmetric edge.
+      Edge backward(SymEdge) const {return INVALID;};
+
+      /// Gives back the opposite of the edge.
+      Edge opposite(Edge) const {return INVALID;}
+
+      ///Reference map of the nodes to type \c T.
+      /// \ingroup skeletons
+      ///Reference map of the nodes to type \c T.
+      /// \sa Reference
+      /// \warning Making maps that can handle bool type (NodeMap<bool>)
+      /// needs some extra attention!
+      template<class T> class NodeMap : public ReferenceMap< Node, T >
+      {
+      public:
+
+	/// .
+	NodeMap(const StaticSymGraph&) { }
+	/// .
+	NodeMap(const StaticSymGraph&, T) { }
+
+	///Copy constructor
+	template<typename TT> NodeMap(const NodeMap<TT>&) { }
+	///Assignment operator
+	template<typename TT> NodeMap& operator=(const NodeMap<TT>&)
+	{ return *this; }
+      };
+
+      ///Reference map of the edges to type \c T.
+
+      /// \ingroup skeletons
+      ///Reference map of the edges to type \c T.
+      /// \sa Reference
+      /// \warning Making maps that can handle bool type (EdgeMap<bool>)
+      /// needs some extra attention!
+      template<class T> class EdgeMap
+	: public ReferenceMap<Edge,T>
+      {
+      public:
+
+	/// .
+	EdgeMap(const StaticSymGraph&) { }
+	/// .
+	EdgeMap(const StaticSymGraph&, T) { }
+    
+	///Copy constructor
+	template<typename TT> EdgeMap(const EdgeMap<TT>&) { }
+	///Assignment operator
+	template<typename TT> EdgeMap &operator=(const EdgeMap<TT>&)
+	{ return *this; }
+      };
+
+      ///Reference map of the edges to type \c T.
+
+      /// \ingroup skeletons
+      ///Reference map of the symmetric edges to type \c T.
+      /// \sa Reference
+      /// \warning Making maps that can handle bool type (EdgeMap<bool>)
+      /// needs some extra attention!
+      template<class T> class SymEdgeMap
+	: public ReferenceMap<SymEdge,T>
+      {
+      public:
+
+	/// .
+	SymEdgeMap(const StaticSymGraph&) { }
+	/// .
+	SymEdgeMap(const StaticSymGraph&, T) { }
+    
+	///Copy constructor
+	template<typename TT> SymEdgeMap(const SymEdgeMap<TT>&) { }
+	///Assignment operator
+	template<typename TT> SymEdgeMap &operator=(const SymEdgeMap<TT>&)
+	{ return *this; }
+      };
+    };
+
+
+  
+    /// An empty non-static graph class.
+
+    /// This class provides everything that \ref StaticGraph
+    /// with additional functionality which enables to build a
+    /// graph from scratch.
+    class ExtendableSymGraph : public StaticSymGraph
+    {
+    public:
+      /// Defalult constructor.
+
+      /// Defalult constructor.
+      ///
+      ExtendableSymGraph() { }
+      ///Add a new node to the graph.
+
+      /// \return the new node.
+      ///
+      Node addNode() { return INVALID; }
+      ///Add a new edge to the graph.
+
+      ///Add a new symmetric edge to the graph with tail node \c t
+      ///and head node \c h.
+      ///\return the new edge.
+      SymEdge addEdge(Node h, Node t) { return INVALID; }
+    
+      /// Resets the graph.
+
+      /// This function deletes all edges and nodes of the graph.
+      /// It also frees the memory allocated to store them.
+      /// \todo It might belong to \ref ErasableGraph.
+      void clear() { }
+    };
+
+    /// An empty erasable graph class.
+  
+    /// This class is an extension of \ref ExtendableGraph. It also makes it
+    /// possible to erase edges or nodes.
+    class ErasableSymGraph : public ExtendableSymGraph
+    {
+    public:
+      /// Defalult constructor.
+
+      /// Defalult constructor.
+      ///
+      ErasableSymGraph() { }
+      /// Deletes a node.
+
+      /// Deletes node \c n node.
+      ///
+      void erase(Node n) { }
+      /// Deletes an edge.
+
+      /// Deletes edge \c e edge.
+      ///
+      void erase(SymEdge e) { }
+    };
+
+    // @}
+  } //namespace skeleton  
+} //namespace hugo
+
+
+
+#endif // HUGO_SKELETON_GRAPH_H

Modified: hugo/trunk/src/hugo/smart_graph.h
==============================================================================
--- hugo/trunk/src/hugo/smart_graph.h	(original)
+++ hugo/trunk/src/hugo/smart_graph.h	Sun Sep 26 23:43:38 2004
@@ -27,8 +27,6 @@
 #include <hugo/invalid.h>
 
 #include <hugo/array_map.h>
-#include <hugo/sym_map.h>
-
 #include <hugo/map_registry.h>
 
 #include <hugo/map_defines.h>
@@ -298,6 +296,381 @@
 
   };
 
+
+
+  class SymSmartGraph : public SmartGraph {
+    typedef SmartGraph Parent;
+  public:
+
+    typedef SymSmartGraph Graph;
+
+    typedef SmartGraph::Node Node;
+    typedef SmartGraph::NodeIt NodeIt;
+
+    class SymEdge;
+    class SymEdgeIt;
+
+    class Edge;
+    class EdgeIt;
+    class OutEdgeIt;
+    class InEdgeIt;
+
+    template <typename Value>
+    class NodeMap : public Parent::NodeMap<Value> {      
+    public:
+      NodeMap(const SymSmartGraph& g) 
+	: SymSmartGraph::Parent::NodeMap<Value>(g) {}
+      NodeMap(const SymSmartGraph& g, Value v) 
+	: SymSmartGraph::Parent::NodeMap<Value>(g, v) {}
+      template<typename TT> 
+      NodeMap(const NodeMap<TT>& copy) 
+	: SymSmartGraph::Parent::NodeMap<Value>(copy) { }            
+    };
+
+    template <typename Value>
+    class SymEdgeMap : public Parent::EdgeMap<Value> {
+    public:
+      typedef SymEdge KeyType;
+
+      SymEdgeMap(const SymSmartGraph& g) 
+	: SymSmartGraph::Parent::EdgeMap<Value>(g) {}
+      SymEdgeMap(const SymSmartGraph& g, Value v) 
+	: SymSmartGraph::Parent::EdgeMap<Value>(g, v) {}
+      template<typename TT> 
+      SymEdgeMap(const SymEdgeMap<TT>& copy) 
+	: SymSmartGraph::Parent::EdgeMap<Value>(copy) { }
+      
+    };
+
+    // Create edge map registry.
+    CREATE_EDGE_MAP_REGISTRY;
+    // Create edge maps.
+    CREATE_EDGE_MAP(ArrayMap);
+
+    class Edge {
+      friend class SymSmartGraph;
+      friend class SymSmartGraph::EdgeIt;
+      friend class SymSmartGraph::OutEdgeIt;
+      friend class SymSmartGraph::InEdgeIt;
+      
+    protected:
+      int id;
+
+      Edge(int pid) { id = pid; }
+
+    public:
+      /// An Edge with id \c n.
+
+      Edge() { }
+      Edge (Invalid) { id = -1; }
+
+      operator SymEdge(){ return SymEdge(id >> 1);}
+      
+      bool operator==(const Edge i) const {return id == i.id;}
+      bool operator!=(const Edge i) const {return id != i.id;}
+      bool operator<(const Edge i) const {return id < i.id;}
+      //      ///Validity check
+      //      operator bool() { return n!=-1; }
+    };
+
+    class SymEdge : public SmartGraph::Edge {
+      friend class SymSmartGraph;
+      friend class SymSmartGraph::Edge;
+      typedef SmartGraph::Edge Parent;
+
+    protected:      
+      SymEdge(int pid) : Parent(pid) {}
+    public:
+
+      SymEdge() { }
+      SymEdge(const SmartGraph::Edge& i) : Parent(i) {} 
+      SymEdge (Invalid) : Parent(INVALID) {}
+
+    };
+
+    class OutEdgeIt {
+      Parent::OutEdgeIt out;
+      Parent::InEdgeIt in;      
+    public: 
+      OutEdgeIt() {}
+      OutEdgeIt(const SymSmartGraph& g, Edge e) { 
+	if (e.id & 1 == 0) {	
+	  out = Parent::OutEdgeIt(g, SymEdge(e));
+	  in = Parent::InEdgeIt(g, g.tail(e));
+	} else {
+	  out = Parent::OutEdgeIt(INVALID);
+	  in = Parent::InEdgeIt(g, SymEdge(e));
+	}
+      }
+      OutEdgeIt (Invalid i) : out(INVALID), in(INVALID) { }
+
+      OutEdgeIt(const SymSmartGraph& g, const Node v)
+	: out(g, v), in(g, v) {}
+      OutEdgeIt &operator++() { 
+	if (out != INVALID) {
+	  ++out;
+	} else {
+	  ++in;
+	}
+	return *this; 
+      }
+
+      operator Edge() const {
+	if (out == INVALID && in == INVALID) return INVALID;
+	return out != INVALID ? forward(out) : backward(in);
+      }
+
+      bool operator==(const Edge i) const {return Edge(*this) == i;}
+      bool operator!=(const Edge i) const {return Edge(*this) != i;}
+      bool operator<(const Edge i) const {return Edge(*this) < i;}
+    };
+
+    class InEdgeIt {
+      Parent::OutEdgeIt out;
+      Parent::InEdgeIt in;      
+    public: 
+      InEdgeIt() {}
+      InEdgeIt(const SymSmartGraph& g, Edge e) { 
+	if (e.id & 1 == 0) {	
+	  out = Parent::OutEdgeIt(g, SymEdge(e));
+	  in = Parent::InEdgeIt(g, g.tail(e));
+	} else {
+	  out = Parent::OutEdgeIt(INVALID);
+	  in = Parent::InEdgeIt(g, SymEdge(e));
+	}
+      }
+      InEdgeIt (Invalid i) : out(INVALID), in(INVALID) { }
+
+      InEdgeIt(const SymSmartGraph& g, const Node v)
+	: out(g, v), in(g, v) {}
+
+      InEdgeIt &operator++() { 
+	if (out != INVALID) {
+	  ++out;
+	} else {
+	  ++in;
+	}
+	return *this; 
+      }
+
+      operator Edge() const {
+	if (out == INVALID && in == INVALID) return INVALID;
+	return out != INVALID ? backward(out) : forward(in);
+      }
+
+      bool operator==(const Edge i) const {return Edge(*this) == i;}
+      bool operator!=(const Edge i) const {return Edge(*this) != i;}
+      bool operator<(const Edge i) const {return Edge(*this) < i;}
+    };
+
+    class SymEdgeIt : public Parent::EdgeIt {
+
+    public:
+      SymEdgeIt() {}
+
+      SymEdgeIt(const SymSmartGraph& g) 
+	: SymSmartGraph::Parent::EdgeIt(g) {}
+
+      SymEdgeIt(const SymSmartGraph& g, SymEdge e) 
+	: SymSmartGraph::Parent::EdgeIt(g, e) {}
+
+      SymEdgeIt(Invalid i) 
+	: SymSmartGraph::Parent::EdgeIt(INVALID) {}
+
+      SymEdgeIt& operator++() {
+	SymSmartGraph::Parent::EdgeIt::operator++();
+	return *this;
+      }
+
+      operator SymEdge() const {
+	return SymEdge
+	  (static_cast<const SymSmartGraph::Parent::EdgeIt&>(*this));
+      }
+      bool operator==(const SymEdge i) const {return SymEdge(*this) == i;}
+      bool operator!=(const SymEdge i) const {return SymEdge(*this) != i;}
+      bool operator<(const SymEdge i) const {return SymEdge(*this) < i;}
+    };
+
+    class EdgeIt {
+      SymEdgeIt it;
+      bool fw;
+    public:
+      EdgeIt(const SymSmartGraph& g) : it(g), fw(true) {}
+      EdgeIt (Invalid i) : it(i) { }
+      EdgeIt(const SymSmartGraph& g, Edge e) 
+	: it(g, SymEdge(e)), fw(id(e) & 1 == 0) { }
+      EdgeIt() { }
+      EdgeIt& operator++() {
+	fw = !fw;
+	if (fw) ++it;
+	return *this;
+      }
+      operator Edge() const {
+	if (it == INVALID) return INVALID;
+	return fw ? forward(it) : backward(it);
+      }
+      bool operator==(const Edge i) const {return Edge(*this) == i;}
+      bool operator!=(const Edge i) const {return Edge(*this) != i;}
+      bool operator<(const Edge i) const {return Edge(*this) < i;}
+
+    };
+
+    ///Number of nodes.
+    int nodeNum() const { return Parent::nodeNum(); }
+    ///Number of edges.
+    int edgeNum() const { return 2*Parent::edgeNum(); }
+    ///Number of symmetric edges.
+    int symEdgeNum() const { return Parent::edgeNum(); }
+
+    /// Maximum node ID.
+    
+    /// Maximum node ID.
+    ///\sa id(Node)
+    int maxNodeId() const { return Parent::maxNodeId(); } 
+    /// Maximum edge ID.
+    
+    /// Maximum edge ID.
+    ///\sa id(Edge)
+    int maxEdgeId() const { return 2*Parent::maxEdgeId(); }
+    /// Maximum symmetric edge ID.
+    
+    /// Maximum symmetric edge ID.
+    ///\sa id(SymEdge)
+    int maxSymEdgeId() const { return Parent::maxEdgeId(); }
+
+
+    Node tail(Edge e) const { 
+      return e.id & 1 == 0 ? 
+	Parent::tail(SymEdge(e)) : Parent::head(SymEdge(e)); 
+    }
+
+    Node head(Edge e) const { 
+      return e.id & 1 == 0 ? 
+	Parent::head(SymEdge(e)) : Parent::tail(SymEdge(e)); 
+    }
+
+    Node tail(SymEdge e) const { 
+      return Parent::tail(e); 
+    }
+
+    Node head(SymEdge e) const { 
+      return Parent::head(e); 
+    }
+
+    NodeIt& first(NodeIt& v) const { 
+      v=NodeIt(*this); return v; }
+    EdgeIt& first(EdgeIt& e) const { 
+      e=EdgeIt(*this); return e; }
+    SymEdgeIt& first(SymEdgeIt& e) const {
+      e=SymEdgeIt(*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; }
+
+    /// Node ID.
+    
+    /// The ID of a valid Node is a nonnegative integer not greater than
+    /// \ref maxNodeId(). The range of the ID's is not surely continuous
+    /// and the greatest node ID can be actually less then \ref maxNodeId().
+    ///
+    /// The ID of the \ref INVALID node is -1.
+    ///\return The ID of the node \c v. 
+    static int id(Node v) { return Parent::id(v); }
+    /// Edge ID.
+    
+    /// The ID of a valid Edge is a nonnegative integer not greater than
+    /// \ref maxEdgeId(). The range of the ID's is not surely continuous
+    /// and the greatest edge ID can be actually less then \ref maxEdgeId().
+    ///
+    /// The ID of the \ref INVALID edge is -1.
+    ///\return The ID of the edge \c e. 
+    static int id(Edge e) { return e.id; }
+
+    /// The ID of a valid SymEdge is a nonnegative integer not greater than
+    /// \ref maxSymEdgeId(). The range of the ID's is not surely continuous
+    /// and the greatest edge ID can be actually less then \ref maxSymEdgeId().
+    ///
+    /// The ID of the \ref INVALID symmetric edge is -1.
+    ///\return The ID of the edge \c e. 
+    static int id(SymEdge e) { return Parent::id(e); }
+
+    /// Adds a new node to the graph.
+
+    /// \warning It adds the new node to the front of the list.
+    /// (i.e. the lastly added node becomes the first.)
+    Node addNode() {
+      return Parent::addNode();
+    }
+    
+    SymEdge addEdge(Node u, Node v) {
+      SymEdge se = Parent::addEdge(u, v);
+      edge_maps.add(forward(se));
+      edge_maps.add(backward(se));
+      return se;
+    }
+    
+    /// Finds an edge between two nodes.
+
+    /// Finds an edge from node \c u to node \c v.
+    ///
+    /// If \c prev is \ref INVALID (this is the default value), then
+    /// It finds the first edge from \c u to \c v. Otherwise it looks for
+    /// the next edge from \c u to \c v after \c prev.
+    /// \return The found edge or INVALID if there is no such an edge.
+    Edge findEdge(Node u, Node v, Edge prev = INVALID) 
+    {     
+      if (prev == INVALID || id(prev) & 1 == 0) {
+	SymEdge se = Parent::findEdge(u, v, SymEdge(prev));
+	if (se != INVALID) return forward(se);
+      } else {
+	SymEdge se = Parent::findEdge(v, u, SymEdge(prev));
+	if (se != INVALID) return backward(se);	
+      }
+      return INVALID;
+    }
+
+    /// Finds an symmetric edge between two nodes.
+
+    /// Finds an symmetric edge from node \c u to node \c v.
+    ///
+    /// If \c prev is \ref INVALID (this is the default value), then
+    /// It finds the first edge from \c u to \c v. Otherwise it looks for
+    /// the next edge from \c u to \c v after \c prev.
+    /// \return The found edge or INVALID if there is no such an edge.
+
+//     SymEdge findEdge(Node u, Node v, SymEdge prev = INVALID) 
+//     {     
+//       if (prev == INVALID || id(prev) & 1 == 0) {
+// 	SymEdge se = Parent::findEdge(u, v, SymEdge(prev));
+// 	if (se != INVALID) return se;
+//       } else {
+// 	SymEdge se = Parent::findEdge(v, u, SymEdge(prev));
+// 	if (se != INVALID) return se;	
+//       }
+//       return INVALID;
+//     }
+    
+  public:
+
+    void clear() {
+      edge_maps.clear();
+      Parent::clear();
+    }
+
+    static Edge opposite(Edge e) {
+      return Edge(id(e) ^ 1);
+    }
+
+    static Edge forward(SymEdge e) {
+      return Edge(id(e) << 1);
+    }
+
+    static Edge backward(SymEdge e) {
+      return Edge((id(e) << 1) & 1);
+    }
+
+  };
   ///Graph for bidirectional edges.
 
   ///The purpose of this graph structure is to handle graphs
@@ -318,7 +691,7 @@
   ///it is not possible to delete edges or nodes from the graph.
   //\sa SmartGraph.
 
-  class SymSmartGraph : public SmartGraph
+  /*  class SymSmartGraph : public SmartGraph
   {
   public:
     typedef SymSmartGraph Graph;
@@ -353,7 +726,7 @@
     }
     
 
-  };
+    };*/
   
   /// @}  
 } //namespace hugo

Modified: hugo/trunk/src/test/Makefile.am
==============================================================================
--- hugo/trunk/src/test/Makefile.am	(original)
+++ hugo/trunk/src/test/Makefile.am	Sun Sep 26 23:43:38 2004
@@ -9,6 +9,7 @@
 	dfs_test \
 	dijkstra_test \
 	graph_test \
+	sym_graph_test \
 	graph_wrapper_test \
 	kruskal_test \
 	min_cost_flow_test \
@@ -28,6 +29,7 @@
 dfs_test_SOURCES = dfs_test.cc
 dijkstra_test_SOURCES = dijkstra_test.cc
 graph_test_SOURCES = graph_test.cc
+sym_graph_test_SOURCES = sym_graph_test.cc
 graph_wrapper_test_SOURCES = graph_wrapper_test.cc
 kruskal_test_SOURCES = kruskal_test.cc
 min_cost_flow_test_SOURCES = min_cost_flow_test.cc

Modified: hugo/trunk/src/test/graph_test.cc
==============================================================================
--- hugo/trunk/src/test/graph_test.cc	(original)
+++ hugo/trunk/src/test/graph_test.cc	Sun Sep 26 23:43:38 2004
@@ -63,7 +63,6 @@
   for(NodeIt n(G);n!=INVALID;++n) {
     checkGraphInEdgeList(G,n,3);
     checkGraphOutEdgeList(G,n,3);
-    ++n;
   }  
 }
 
@@ -82,8 +81,8 @@
 template void hugo::checkCompileGraphFindEdge<SmartGraph>(SmartGraph &);
 
 //Compile SymSmartGraph
-template void hugo::checkCompileGraph<SymSmartGraph>(SymSmartGraph &);
-template void hugo::checkCompileGraphFindEdge<SymSmartGraph>(SymSmartGraph &);
+//template void hugo::checkCompileGraph<SymSmartGraph>(SymSmartGraph &);
+//template void hugo::checkCompileGraphFindEdge<SymSmartGraph>(SymSmartGraph &);
 
 //Compile ListGraph
 template void hugo::checkCompileGraph<ListGraph>(ListGraph &);
@@ -92,9 +91,9 @@
 
 
 //Compile SymListGraph
-template void hugo::checkCompileGraph<SymListGraph>(SymListGraph &);
-template void hugo::checkCompileErasableGraph<SymListGraph>(SymListGraph &);
-template void hugo::checkCompileGraphFindEdge<SymListGraph>(SymListGraph &);
+//template void hugo::checkCompileGraph<SymListGraph>(SymListGraph &);
+//template void hugo::checkCompileErasableGraph<SymListGraph>(SymListGraph &);
+//template void hugo::checkCompileGraphFindEdge<SymListGraph>(SymListGraph &);
 
 //Compile FullGraph
 template void hugo::checkCompileStaticGraph<FullGraph>(FullGraph &);
@@ -131,14 +130,14 @@
     checkPetersen(G);
   }
   {
-    SymSmartGraph G;
-    addPetersen(G);
-    checkPetersen(G);
+    //    SymSmartGraph G;
+    //    addPetersen(G);
+    //    checkPetersen(G);
   }
   {
-    SymListGraph G;
-    addPetersen(G);
-    checkPetersen(G);
+    //    SymListGraph G;
+    //    addPetersen(G);
+    //    checkPetersen(G);
   }
 
   ///\file

Added: hugo/trunk/src/test/sym_graph_test.cc
==============================================================================
--- (empty file)
+++ hugo/trunk/src/test/sym_graph_test.cc	Sun Sep 26 23:43:38 2004
@@ -0,0 +1,96 @@
+/* -*- C++ -*-
+ * src/test/sym_graph_test.cc - Part of HUGOlib, a generic C++ optimization library
+ *
+ * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Combinatorial Optimization Research Group, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include<iostream>
+
+#include<hugo/skeletons/sym_graph.h>
+
+#include<hugo/list_graph.h>
+#include<hugo/smart_graph.h>
+#include<hugo/full_graph.h>
+
+#include"test_tools.h"
+#include"graph_test.h"
+#include"sym_graph_test.h"
+
+/**
+\file
+This test makes consistency checks of list graph structures.
+
+G.addNode(), G.addEdge(), G.tail(), G.head()
+
+\todo Checks for empty graphs and isolated points.
+conversion.
+*/
+
+using namespace hugo;
+
+template<class Graph> void checkPetersen(Graph &G)
+{
+  typedef typename Graph::NodeIt NodeIt;
+
+
+  checkGraphNodeList(G,10);
+  checkGraphEdgeList(G,30);
+  checkGraphSymEdgeList(G,15);
+
+  for(NodeIt n(G);n!=INVALID;++n) {
+    checkGraphInEdgeList(G,n,3);
+    checkGraphOutEdgeList(G,n,3);
+  }  
+}
+
+//Compile Graph
+template void hugo::checkCompileStaticSymGraph<skeleton::StaticSymGraph>
+(skeleton::StaticSymGraph &);
+
+template void hugo::checkCompileSymGraph<skeleton::ExtendableSymGraph>
+(skeleton::ExtendableSymGraph &);
+
+template void hugo::checkCompileErasableSymGraph<skeleton::ErasableSymGraph>
+(skeleton::ErasableSymGraph &);
+
+
+//Compile SymSmartGraph
+template void hugo::checkCompileSymGraph<SymSmartGraph>(SymSmartGraph &);
+template void hugo::checkCompileGraphFindEdge<SymSmartGraph>(SymSmartGraph &);
+
+//Compile SymListGraph
+template void hugo::checkCompileSymGraph<SymListGraph>(SymListGraph &);
+template void hugo::checkCompileErasableSymGraph<SymListGraph>(SymListGraph &);
+template void hugo::checkCompileGraphFindEdge<SymListGraph>(SymListGraph &);
+
+int main() 
+{
+  {
+    SymSmartGraph G;
+    addSymPetersen(G);
+    checkPetersen(G);
+  }
+  {
+    SymListGraph G;
+    addSymPetersen(G);
+    checkPetersen(G);
+  }
+
+  ///\file
+  ///\todo map tests.
+  ///\todo copy constr tests.
+
+  std::cout << __FILE__ ": All tests passed.\n";
+
+  return 0;
+}

Added: hugo/trunk/src/test/sym_graph_test.h
==============================================================================
--- (empty file)
+++ hugo/trunk/src/test/sym_graph_test.h	Sun Sep 26 23:43:38 2004
@@ -0,0 +1,179 @@
+/* -*- C++ -*-
+ * src/test/sym_graph_test.h - Part of HUGOlib, a generic C++ optimization library
+ *
+ * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Combinatorial Optimization Research Group, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+#ifndef HUGO_TEST_SYM_GRAPH_TEST_H
+#define HUGO_TEST_SYM_GRAPH_TEST_H
+
+
+#include "graph_test.h"
+#include "test_tools.h"
+
+//! \ingroup misc
+//! \file
+//! \brief Some utility to test symmetric graph classes.
+namespace hugo {
+
+  template<class Graph> void checkCompileStaticSymGraph(Graph &G) 
+    {
+      typedef typename Graph::Node Node;
+      typedef typename Graph::NodeIt NodeIt;
+      typedef typename Graph::SymEdge SymEdge;
+      typedef typename Graph::SymEdgeIt SymEdgeIt;
+      typedef typename Graph::Edge Edge;
+      typedef typename Graph::EdgeIt EdgeIt;
+      typedef typename Graph::InEdgeIt InEdgeIt;
+      typedef typename Graph::OutEdgeIt OutEdgeIt;
+
+      checkCompileStaticGraph(G);
+  
+      {
+	SymEdge i; SymEdge j(i); SymEdge k(INVALID);
+	i=j;
+	bool b; b=true;
+	b=(i==INVALID); b=(i!=INVALID);
+	b=(i==j); b=(i!=j); b=(i<j);
+	Edge e;
+	e = G.forward(i);
+	e = G.backward(i);
+      }
+      {
+	SymEdgeIt i; SymEdgeIt j(i); SymEdgeIt k(INVALID); SymEdgeIt l(G);
+	i=j;
+	j=G.first(i);
+	j=++i;
+	bool b; b=true;
+	b=(i==INVALID); b=(i!=INVALID);
+	SymEdge n(i);
+	n=i;
+	b=(i==j); b=(i!=j); b=(i<j);
+	//SymEdge ->SymEdgeIt conversion
+	SymEdgeIt ni(G,n);
+      }
+      {
+	Edge i, j;
+	j = G.opposite(i);
+      }      
+      {
+	Node n;
+	SymEdge se;
+	se=INVALID;
+	n=G.tail(se);
+	n=G.head(se);
+      }
+      // id tests
+      { SymEdge n; int i=G.id(n); i=i; }
+      //SymEdgeMap tests
+      {
+	SymEdge k;
+	typename Graph::template SymEdgeMap<int> m(G);
+	typename Graph::template SymEdgeMap<int> const &cm = m;  //Const map
+	//Inicialize with default value
+	typename Graph::template SymEdgeMap<int> mdef(G,12);
+	typename Graph::template SymEdgeMap<int> mm(cm);   //Copy
+	typename Graph::template SymEdgeMap<double> dm(cm); //Copy from another type
+	int v;
+	v=m[k]; m[k]=v; m.set(k,v);
+	v=cm[k];
+    
+	m=cm;  
+	dm=cm; //Copy from another type
+	{
+	  //Check the typedef's
+	  typename Graph::template SymEdgeMap<int>::ValueType val;
+	  val = 1;
+	  typename Graph::template SymEdgeMap<int>::KeyType key;
+	  key = typename Graph::SymEdgeIt(G);
+	}
+      }  
+      { //bool SymEdgeMap
+	SymEdge k;
+	typename Graph::template SymEdgeMap<bool> m(G);
+	typename Graph::template SymEdgeMap<bool> const &cm = m;  //Const map
+	//Inicialize with default value
+	typename Graph::template SymEdgeMap<bool> mdef(G,12);
+	typename Graph::template SymEdgeMap<bool> mm(cm);   //Copy
+	typename Graph::template SymEdgeMap<int> dm(cm); //Copy from another type
+	bool v;
+	v=m[k]; m[k]=v; m.set(k,v);
+	v=cm[k];
+    
+	m=cm;  
+	dm=cm; //Copy from another type
+	m=dm; //Copy to another type
+	{
+	  //Check the typedef's
+	  typename Graph::template SymEdgeMap<bool>::ValueType val;
+	  val=true;
+	  typename Graph::template SymEdgeMap<bool>::KeyType key;
+	  key= typename Graph::SymEdgeIt(G);
+	}
+      }
+    }
+
+  template<class Graph> void checkCompileSymGraph(Graph &G) 
+    {
+      checkCompileStaticSymGraph(G);
+
+      typedef typename Graph::Node Node;
+      typedef typename Graph::NodeIt NodeIt;
+      typedef typename Graph::SymEdge SymEdge;
+      typedef typename Graph::SymEdgeIt SymEdgeIt;
+      typedef typename Graph::Edge Edge;
+      typedef typename Graph::EdgeIt EdgeIt;
+      typedef typename Graph::InEdgeIt InEdgeIt;
+      typedef typename Graph::OutEdgeIt OutEdgeIt;
+  
+      Node n,m;
+      n=G.addNode();
+      m=G.addNode();
+      SymEdge e;
+      e = G.addEdge(n,m); 
+  
+      //  G.clear();
+    }
+
+  template<class Graph> void checkCompileSymGraphEraseSymEdge(Graph &G) 
+    {
+      typename Graph::SymEdge n;
+      G.erase(n);
+    }
+
+  template<class Graph> void checkCompileErasableSymGraph(Graph &G) 
+    {
+      checkCompileSymGraph(G);
+      checkCompileGraphEraseNode(G);
+      checkCompileSymGraphEraseSymEdge(G);
+    }
+
+  template<class Graph> void checkGraphSymEdgeList(Graph &G, int nn)
+    {
+      typedef typename Graph::SymEdgeIt SymEdgeIt;
+
+      SymEdgeIt e(G);
+      for(int i=0;i<nn;i++) {
+	check(e!=INVALID,"Wrong SymEdge list linking.");
+	++e;
+      }
+      check(e==INVALID,"Wrong SymEdge list linking.");
+    }
+
+  ///\file
+  ///\todo Check head(), tail() as well;
+
+  
+} //namespace hugo
+
+
+#endif

Modified: hugo/trunk/src/test/test_tools.h
==============================================================================
--- hugo/trunk/src/test/test_tools.h	(original)
+++ hugo/trunk/src/test/test_tools.h	Sun Sep 26 23:43:38 2004
@@ -67,7 +67,7 @@
 ///Adds a Petersen graph to \c G.
 
 ///Adds a Petersen graph to \c G.
-///\return The nodes end edges og the generated graph.
+///\return The nodes and edges of the generated graph.
 
 template<typename Graph>
 PetStruct<Graph> addPetersen(Graph &G,int num=5)
@@ -87,6 +87,45 @@
  return n;
 }
 
+///Structure returned by \ref addSymPetersen().
 
+///Structure returned by \ref addSymPetersen().
+///
+template<class Graph> struct SymPetStruct
+{
+  ///Vector containing the outer nodes.
+  std::vector<typename Graph::Node> outer;
+  ///Vector containing the inner nodes.
+  std::vector<typename Graph::Node> inner;
+  ///Vector containing the edges of the inner circle.
+  std::vector<typename Graph::SymEdge> incir;
+  ///Vector containing the edges of the outer circle.
+  std::vector<typename Graph::SymEdge> outcir;
+  ///Vector containing the chord edges.
+  std::vector<typename Graph::SymEdge> chords;
+};
+
+///Adds a Petersen graph to the symmetric \c G.
+
+///Adds a Petersen graph to the symmetric \c G.
+///\return The nodes and edges of the generated graph.
+
+template<typename Graph>
+SymPetStruct<Graph> addSymPetersen(Graph &G,int num=5)
+{
+  SymPetStruct<Graph> n;
+
+  for(int i=0;i<num;i++) {
+    n.outer.push_back(G.addNode());
+    n.inner.push_back(G.addNode());
+  }
+
+ for(int i=0;i<num;i++) {
+   n.chords.push_back(G.addEdge(n.outer[i],n.inner[i]));
+   n.outcir.push_back(G.addEdge(n.outer[i],n.outer[(i+1)%5]));
+   n.incir.push_back(G.addEdge(n.inner[i],n.inner[(i+2)%5]));
+  }
+ return n;
+}
 
 #endif



More information about the Lemon-commits mailing list