[Lemon-commits] [lemon_svn] marci: r1403 - in hugo/trunk/src: lemon work/marci

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


Author: marci
Date: Sat Nov 20 15:09:27 2004
New Revision: 1403

Modified:
   hugo/trunk/src/lemon/graph_wrapper.h
   hugo/trunk/src/work/marci/merge_node_graph_wrapper.h
   hugo/trunk/src/work/marci/merge_node_graph_wrapper_test.cc

Log:
MergeGraphWrapper


Modified: hugo/trunk/src/lemon/graph_wrapper.h
==============================================================================
--- hugo/trunk/src/lemon/graph_wrapper.h	(original)
+++ hugo/trunk/src/lemon/graph_wrapper.h	Sat Nov 20 15:09:27 2004
@@ -1175,17 +1175,6 @@
       EdgeMap(const SubBidirGraphWrapperBase<_Graph, 
 	      ForwardFilterMap, BackwardFilterMap>& g, T a) : 
 	forward_map(*(g.graph), a), backward_map(*(g.graph), a) { }
-
-//       template <typename TT>
-//       EdgeMap(const EdgeMap<TT>& copy) 
-// 	: forward_map(copy.forward_map), backward_map(copy.backward_map) {}
-
-//       template <typename TT>
-//       EdgeMap& operator=(const EdgeMap<TT>& copy) {
-// 	forward_map = copy.forward_map;
-// 	backward_map = copy.backward_map;
-// 	return *this;
-//       }
       
       void set(Edge e, T a) { 
 	if (!e.backward) 

Modified: hugo/trunk/src/work/marci/merge_node_graph_wrapper.h
==============================================================================
--- hugo/trunk/src/work/marci/merge_node_graph_wrapper.h	(original)
+++ hugo/trunk/src/work/marci/merge_node_graph_wrapper.h	Sat Nov 20 15:09:27 2004
@@ -22,6 +22,7 @@
 #include <lemon/map_defines.h>
 #include <lemon/graph_wrapper.h>
 #include <iostream>
+
 using std::cout;
 using std::endl;
 
@@ -38,14 +39,17 @@
   class P2 : public GraphWrapperBase<_Graph2> {
   };
 
-  /*! A base class for merging the node-set of two node-disjoint graphs 
-    into the node-set of one graph.
+
+  /*! A graph wrapper base class 
+    for merging the node-set of two node-disjoint graphs 
+    into the node-set of one graph. 
+    Generic implementation for unrelated _Graph1::Node and _Graph2::Node.
    */
   template <typename _Graph1, typename _Graph2, typename Enable=void>
   class MergeNodeGraphWrapperBase : 
     public P1<_Graph1>, public P2<_Graph2> {
   public:
-    void printNode() const { std::cout << "generic" << std::endl; }
+    static void printNode() { std::cout << "node: generic" << std::endl; }
     typedef _Graph1 Graph1;
     typedef _Graph2 Graph2;
     typedef P1<_Graph1> Parent1;
@@ -59,7 +63,7 @@
 
     class Node : public Graph1Node, public Graph2Node {
       friend class MergeNodeGraphWrapperBase<_Graph1, _Graph2>;
-      template <typename Value> friend class NodeMap;
+      template <typename _Value> friend class NodeMap;
     protected:
       bool backward; //true, iff backward
     public:
@@ -72,18 +76,15 @@
 	Graph1Node(n1), Graph2Node(n2), backward(_backward) { }
       Node(Invalid i) : Graph1Node(i), Graph2Node(i), backward(true) { }
       bool operator==(const Node& v) const { 
-	return (this->backward==v.backward && 
-		static_cast<Graph1Node>(*this)==
-		static_cast<Graph1Node>(v) && 
-		static_cast<Graph2Node>(*this)==
-		static_cast<Graph2Node>(v));
+	if (backward) 
+	  return (v.backward && 
+		  static_cast<Graph2Node>(*this)==static_cast<Graph2Node>(v)); 
+	else 
+	  return (!v.backward && 
+		  static_cast<Graph1Node>(*this)==static_cast<Graph1Node>(v)); 
       } 
       bool operator!=(const Node& v) const { 
-	return (this->backward!=v.backward || 
-		static_cast<Graph1Node>(*this)!=
-		static_cast<Graph1Node>(v) || 
-		static_cast<Graph2Node>(*this)!=
-		static_cast<Graph2Node>(v));
+	return !(*this==v);
       }
     };
 
@@ -118,29 +119,33 @@
     }
 
     template <typename _Value> 
-    class NodeMap : public Parent1::template NodeMap<_Value>, 
-		    public Parent2::template NodeMap<_Value> { 
-      typedef typename Parent1::template NodeMap<_Value> ParentMap1;
-      typedef typename Parent2::template NodeMap<_Value> ParentMap2;
+    class NodeMap { 
+    protected:
+      typedef typename _Graph1::template NodeMap<_Value> ParentMap1;
+      typedef typename _Graph2::template NodeMap<_Value> ParentMap2;
+      ParentMap1 forward_map;
+      ParentMap2 backward_map;
     public:
       typedef _Value Value;
       typedef Node Key;
       NodeMap(const MergeNodeGraphWrapperBase<_Graph1, _Graph2>& gw) : 
-	ParentMap1(gw), ParentMap2(gw) { }
+	forward_map(*(gw.Parent1::graph)), 
+	backward_map(*(gw.Parent2::graph)) { }
       NodeMap(const MergeNodeGraphWrapperBase<_Graph1, _Graph2>& gw, 
 	      const _Value& value) : 
-	ParentMap1(gw, value), ParentMap2(gw, value) { }
+	forward_map(*(gw.Parent1::graph), value), 
+	backward_map(*(gw.Parent2::graph), value) { }
       _Value operator[](const Node& n) const {
 	if (!n.backward) 
-	  return ParentMap1::operator[](n);
+	  return forward_map[n];
 	else 
-	  return ParentMap2::operator[](n);
+	  return backward_map[n];
       }
       void set(const Node& n, const _Value& value) {
 	if (!n.backward) 
-	  ParentMap1::set(n, value);
+	  forward_map.set(n, value);
 	else 
-	  ParentMap2::set(n, value);
+	  backward_map.set(n, value);
       }
 //       using ParentMap1::operator[];
 //       using ParentMap2::operator[];
@@ -148,14 +153,19 @@
 
   };
 
-  //not yet working
+
+  /*! A graph wrapper base class 
+    for merging the node-set of two node-disjoint graphs 
+    into the node-set of one graph. 
+    Specialization for the case when _Graph1::Node are the same _Graph2::Node.
+   */
   template <typename _Graph1, typename _Graph2>
   class MergeNodeGraphWrapperBase<
     _Graph1, _Graph2, typename boost::enable_if<
     boost::is_same<typename _Graph1::Node, typename _Graph2::Node> >::type> : 
     public P1<_Graph1>, public P2<_Graph2> {
-  public :
-    void printNode() const { std::cout << "same" << std::endl; }
+  public:
+    static void printNode() { std::cout << "node: same" << std::endl; }
     typedef _Graph1 Graph1;
     typedef _Graph2 Graph2;
     typedef P1<_Graph1> Parent1;
@@ -165,20 +175,111 @@
   protected:
     MergeNodeGraphWrapperBase() { }
   public:
-    class Node { };
+    template <typename _Value> class NodeMap;
+
+    class Node : public Graph1Node {
+      friend class MergeNodeGraphWrapperBase<_Graph1, _Graph2>;
+      template <typename _Value> friend class NodeMap;
+    protected:
+      bool backward; //true, iff backward
+    public:
+      Node() { }
+      /// \todo =false is needed, or causes problems?
+      /// If \c _backward is false, then we get an edge corresponding to the 
+      /// original one, otherwise its oppositely directed pair is obtained.
+      Node(const Graph1Node& n1, 
+	   const Graph2Node& n2, bool _backward) : 
+	Graph1Node(!backward ? n1 : n2), backward(_backward) { }
+      Node(Invalid i) : Graph1Node(i), backward(true) { }
+      bool operator==(const Node& v) const { 
+	return (backward==v.backward && 
+		static_cast<Graph1Node>(*this)==static_cast<Graph1Node>(v));
+      } 
+      bool operator!=(const Node& v) const { 
+	return !(*this==v);
+      }
+    };
+
+    //typedef void Edge;
     class Edge { };
-    void first() const;
-    void next() const;
+    
+    void first(Node& i) const {
+      Parent1::graph->first(*static_cast<Graph1Node*>(&i));
+      i.backward=false;
+      if (*static_cast<Graph1Node*>(&i)==INVALID) {
+	Parent2::graph->first(*static_cast<Graph1Node*>(&i));
+	i.backward=true;
+      }
+    }
+    void next(Node& i) const {
+      if (!(i.backward)) {
+	Parent1::graph->next(*static_cast<Graph1Node*>(&i));
+	if (*static_cast<Graph1Node*>(&i)==INVALID) {
+	  Parent2::graph->first(*static_cast<Graph1Node*>(&i));
+	  i.backward=true;
+	}
+      } else {
+	Parent2::graph->next(*static_cast<Graph1Node*>(&i));
+      }
+    }
+
+    int id(const Node& n) const { 
+      if (!n.backward) 
+	return this->Parent1::graph->id(n);
+      else
+	return this->Parent2::graph->id(n);
+    }
+
+    template <typename _Value> 
+    class NodeMap { 
+    protected:
+      typedef typename _Graph1::template NodeMap<_Value> ParentMap1;
+      typedef typename _Graph2::template NodeMap<_Value> ParentMap2;
+      ParentMap1 forward_map;
+      ParentMap2 backward_map;
+    public:
+      typedef _Value Value;
+      typedef Node Key;
+      NodeMap(const MergeNodeGraphWrapperBase<_Graph1, _Graph2>& gw) : 
+	forward_map(*(gw.Parent1::graph)), 
+	backward_map(*(gw.Parent2::graph)) { }
+      NodeMap(const MergeNodeGraphWrapperBase<_Graph1, _Graph2>& gw, 
+	      const _Value& value) : 
+	forward_map(*(gw.Parent1::graph), value), 
+	backward_map(*(gw.Parent2::graph), value) { }
+      _Value operator[](const Node& n) const {
+	if (!n.backward) 
+	  return forward_map[n];
+	else 
+	  return backward_map[n];
+      }
+      void set(const Node& n, const _Value& value) {
+	if (!n.backward) 
+	  forward_map.set(n, value);
+	else 
+	  backward_map.set(n, value);
+      }
+//       using ParentMap1::operator[];
+//       using ParentMap2::operator[];
+    };
+
   };
 
-  //not yet working
+
+  /*! A graph wrapper base class 
+    for merging the node-set of two node-disjoint graphs 
+    into the node-set of one graph. 
+    Specialization for the case when 
+    _Graph1::Node are base and derived _Graph2::Node.
+    NOT YET IMPLEMENTED
+   */
   template <typename _Graph1, typename _Graph2>
   class MergeNodeGraphWrapperBase<
     _Graph1, _Graph2, typename boost::enable_if<
     boost::is_base_and_derived<typename _Graph1::Node, typename _Graph2::Node> >::type> : 
     public P1<_Graph1>, public P2<_Graph2> {
   public :
-    void printNode() const { std::cout << "2. nagyobb" << std::endl; }
+    static void printNode() { std::cout << "node: 2nd is derived" << std::endl; }
     typedef _Graph1 Graph1;
     typedef _Graph2 Graph2;
     typedef P1<_Graph1> Parent1;
@@ -201,7 +302,7 @@
     boost::is_base_and_derived<typename _Graph2::Node, typename _Graph1::Node> >::type> : 
     public P1<_Graph1>, public P2<_Graph2> {
   public :
-    void printNode() const { std::cout << "1. nagyobb" << std::endl; }
+    static void printNode() { std::cout << "node: 1st is derived" << std::endl; }
     typedef _Graph1 Graph1;
     typedef _Graph2 Graph2;
     typedef P1<_Graph1> Parent1;
@@ -218,6 +319,12 @@
   };
 
 
+  /*! A graph wrapper class 
+    fors merging the node-set of two node-disjoint graphs 
+    into one node-set. It does not satisfy 
+    StaticGraph concept as it has no edge-set which 
+    works together with the node-set.
+   */
   template <typename _Graph1, typename _Graph2>
   class MergeNodeGraphWrapper : public 
   IterableGraphExtender<MergeNodeGraphWrapperBase<_Graph1, _Graph2> > {
@@ -236,15 +343,17 @@
   };
 
 
-  /*! A base class for merging the node-sets and edge-sets of 
+  /*! A grah wrapper base class 
+    for merging the node-sets and edge-sets of 
     two node-disjoint graphs 
     into one graph.
+    Generic implementation for unrelated _Graph1::Edge and _Graph2::Edge.
    */
   template <typename _Graph1, typename _Graph2, typename Enable=void>
   class MergeEdgeGraphWrapperBase : 
     public MergeNodeGraphWrapperBase<_Graph1, _Graph2> {
   public:
-    void printEdge() const { std::cout << "generic" << std::endl; }
+    static void printEdge() { std::cout << "edge: generic" << std::endl; }
     typedef _Graph1 Graph1;
     typedef _Graph2 Graph2;
     typedef MergeNodeGraphWrapperBase<_Graph1, _Graph2> Parent;
@@ -263,7 +372,7 @@
 
     class Edge : public Graph1Edge, public Graph2Edge {
       friend class MergeEdgeGraphWrapperBase<_Graph1, _Graph2>;
-      template <typename Value> friend class EdgeMap;
+      template <typename _Value> friend class EdgeMap;
     protected:
       bool backward; //true, iff backward
     public:
@@ -276,18 +385,15 @@
 	Graph1Edge(n1), Graph2Edge(n2), backward(_backward) { }
       Edge(Invalid i) : Graph1Edge(i), Graph2Edge(i), backward(true) { }
       bool operator==(const Edge& v) const { 
-	return (this->backward==v.backward && 
-		static_cast<Graph1Edge>(*this)==
-		static_cast<Graph1Edge>(v) && 
-		static_cast<Graph2Edge>(*this)==
-		static_cast<Graph2Edge>(v));
+	if (backward) 
+	  return (v.backward && 
+		  static_cast<Graph2Edge>(*this)==static_cast<Graph2Edge>(v)); 
+	else 
+	  return (!v.backward && 
+		  static_cast<Graph1Edge>(*this)==static_cast<Graph1Edge>(v)); 
       } 
       bool operator!=(const Edge& v) const { 
-	return (this->backward!=v.backward || 
-		static_cast<Graph1Edge>(*this)!=
-		static_cast<Graph1Edge>(v) || 
-		static_cast<Graph2Edge>(*this)!=
-		static_cast<Graph2Edge>(v));
+	return !(*this==v);
       }
     };
 
@@ -381,29 +487,33 @@
     }
 
     template <typename _Value> 
-    class EdgeMap : public Parent1::template EdgeMap<_Value>, 
-		    public Parent2::template EdgeMap<_Value> { 
-      typedef typename Parent1::template EdgeMap<_Value> ParentMap1;
-      typedef typename Parent2::template EdgeMap<_Value> ParentMap2;
+    class EdgeMap { 
+    protected:
+      typedef typename Parent::Graph1::template EdgeMap<_Value> ParentMap1;
+      typedef typename Parent::Graph2::template EdgeMap<_Value> ParentMap2;
+      ParentMap1 forward_map;
+      ParentMap2 backward_map;
     public:
       typedef _Value Value;
       typedef Edge Key;
       EdgeMap(const MergeEdgeGraphWrapperBase<_Graph1, _Graph2>& gw) : 
-	ParentMap1(gw), ParentMap2(gw) { }
+	forward_map(*(gw.Parent1::graph)), 
+	backward_map(*(gw.Parent2::graph)) { }
       EdgeMap(const MergeEdgeGraphWrapperBase<_Graph1, _Graph2>& gw, 
 	      const _Value& value) : 
-	ParentMap1(gw, value), ParentMap2(gw, value) { }
+	forward_map(*(gw.Parent1::graph), value), 
+	backward_map(*(gw.Parent2::graph), value) { }
       _Value operator[](const Edge& n) const {
 	if (!n.backward) 
-	  return ParentMap1::operator[](n);
+	  return forward_map[n];
 	else 
-	  return ParentMap2::operator[](n);
+	  return backward_map[n];
       }
       void set(const Edge& n, const _Value& value) {
 	if (!n.backward) 
-	  ParentMap1::set(n, value);
+	  forward_map.set(n, value);
 	else 
-	  ParentMap2::set(n, value);
+	  backward_map.set(n, value);
       }
 //       using ParentMap1::operator[];
 //       using ParentMap2::operator[];
@@ -412,6 +522,189 @@
   };
 
 
+  /*! A graph wrapper base class 
+    for merging the node-sets and edge-sets of 
+    two node-disjoint graphs 
+    into one graph.
+    Specialization for the case when _Graph1::Edge and _Graph2::Edge
+    are the same.
+   */
+  template <typename _Graph1, typename _Graph2>
+  class MergeEdgeGraphWrapperBase<
+    _Graph1, _Graph2, typename boost::enable_if<
+    boost::is_same<typename _Graph1::Node, typename _Graph2::Node> >::type> : 
+    public MergeNodeGraphWrapperBase<_Graph1, _Graph2> {
+  public:
+    static void printEdge() { std::cout << "edge: same" << std::endl; }
+    typedef _Graph1 Graph1;
+    typedef _Graph2 Graph2;
+    typedef MergeNodeGraphWrapperBase<_Graph1, _Graph2> Parent;
+    typedef typename Parent::Parent1 Parent1;
+    typedef typename Parent::Parent2 Parent2;
+//     typedef P1<_Graph1> Parent1;
+//     typedef P2<_Graph2> Parent2;
+    typedef typename Parent1::Edge Graph1Edge;
+    typedef typename Parent2::Edge Graph2Edge;
+  protected:
+    MergeEdgeGraphWrapperBase() { }
+  public:
+    template <typename _Value> class EdgeMap;
+
+    typedef typename Parent::Node Node;
+
+    class Edge : public Graph1Edge {
+      friend class MergeEdgeGraphWrapperBase<_Graph1, _Graph2>;
+      template <typename _Value> friend class EdgeMap;
+    protected:
+      bool backward; //true, iff backward
+    public:
+      Edge() { }
+      /// \todo =false is needed, or causes problems?
+      /// If \c _backward is false, then we get an edge corresponding to the 
+      /// original one, otherwise its oppositely directed pair is obtained.
+      Edge(const Graph1Edge& n1, 
+	   const Graph2Edge& n2, bool _backward) : 
+	Graph1Edge(!backward ? n1 : n2), backward(_backward) { }
+      Edge(Invalid i) : Graph1Edge(i), backward(true) { }
+      bool operator==(const Edge& v) const { 
+	return (backward==v.backward && 
+		static_cast<Graph1Edge>(*this)==static_cast<Graph1Edge>(v)); 
+      }
+      bool operator!=(const Edge& v) const { 
+	return !(*this==v);
+      }
+    };
+
+    using Parent::first;
+    void first(Edge& i) const {
+      Parent1::graph->first(*static_cast<Graph1Edge*>(&i));
+      i.backward=false;
+      if (*static_cast<Graph1Edge*>(&i)==INVALID) {
+	Parent2::graph->first(*static_cast<Graph1Edge*>(&i));
+	i.backward=true;
+      }
+    }
+    void firstIn(Edge& i, const Node& n) const {
+      Parent1::graph->firstIn(*static_cast<Graph1Edge*>(&i), n);
+      i.backward=false;
+      if (*static_cast<Graph1Edge*>(&i)==INVALID) {
+	Parent2::graph->firstIn(*static_cast<Graph1Edge*>(&i), n);
+	i.backward=true;
+      }
+    }
+    void firstOut(Edge& i, const Node& n) const {
+      Parent1::graph->firstOut(*static_cast<Graph1Edge*>(&i), n);
+      i.backward=false;
+      if (*static_cast<Graph1Edge*>(&i)==INVALID) {
+	Parent2::graph->firstOut(*static_cast<Graph1Edge*>(&i), n);
+	i.backward=true;
+      }
+    }
+
+    using Parent::next;
+    void next(Edge& i) const {
+      if (!(i.backward)) {
+	Parent1::graph->next(*static_cast<Graph1Edge*>(&i));
+	if (*static_cast<Graph1Edge*>(&i)==INVALID) {
+	  Parent2::graph->first(*static_cast<Graph1Edge*>(&i));
+	  i.backward=true;
+	}
+      } else {
+	Parent2::graph->next(*static_cast<Graph1Edge*>(&i));
+      }
+    }
+    void nextIn(Edge& i) const {
+      if (!(i.backward)) {
+	Parent1::graph->nextIn(*static_cast<Graph1Edge*>(&i));
+	if (*static_cast<Graph1Edge*>(&i)==INVALID) {
+	  Parent2::graph->first(*static_cast<Graph1Edge*>(&i));
+	  i.backward=true;
+	}
+      } else {
+	Parent2::graph->nextIn(*static_cast<Graph1Edge*>(&i));
+      }
+    }
+    void nextOut(Edge& i) const {
+      if (!(i.backward)) {
+	Parent1::graph->nextOut(*static_cast<Graph1Edge*>(&i));
+	if (*static_cast<Graph1Edge*>(&i)==INVALID) {
+	  Parent2::graph->first(*static_cast<Graph1Edge*>(&i));
+	  i.backward=true;
+	}
+      } else {
+	Parent2::graph->nextOut(*static_cast<Graph1Edge*>(&i));
+      }
+    }
+
+    Node source(const Edge& i) const {
+      if (!(i.backward)) {
+	return 
+	  Node(Parent1::graph->source(i), INVALID, false);
+      } else {
+	return 
+	  Node(INVALID, Parent2::graph->source(i), true);
+      }
+    }
+
+    Node target(const Edge& i) const {
+      if (!(i.backward)) {
+	return 
+	  Node(Parent1::graph->target(i), INVALID, false);
+      } else {
+	return 
+	  Node(INVALID, Parent2::graph->target(i), true);
+      }
+    }
+
+    using Parent::id;
+    int id(const Edge& n) const { 
+      if (!n.backward) 
+	return this->Parent1::graph->id(n);
+      else
+	return this->Parent2::graph->id(n);
+    }
+
+    template <typename _Value> 
+    class EdgeMap { 
+    protected:
+      typedef typename Parent::Graph1::template EdgeMap<_Value> ParentMap1;
+      typedef typename Parent::Graph2::template EdgeMap<_Value> ParentMap2;
+      ParentMap1 forward_map;
+      ParentMap2 backward_map;
+    public:
+      typedef _Value Value;
+      typedef Edge Key;
+      EdgeMap(const MergeEdgeGraphWrapperBase<_Graph1, _Graph2>& gw) : 
+	forward_map(*(gw.Parent1::graph)), 
+	backward_map(*(gw.Parent2::graph)) { }
+      EdgeMap(const MergeEdgeGraphWrapperBase<_Graph1, _Graph2>& gw, 
+	      const _Value& value) : 
+	forward_map(*(gw.Parent1::graph), value), 
+	backward_map(*(gw.Parent2::graph), value) { }
+      _Value operator[](const Edge& n) const {
+	if (!n.backward) 
+	  return forward_map[n];
+	else 
+	  return backward_map[n];
+      }
+      void set(const Edge& n, const _Value& value) {
+	if (!n.backward) 
+	  forward_map.set(n, value);
+	else 
+	  backward_map.set(n, value);
+      }
+//       using ParentMap1::operator[];
+//       using ParentMap2::operator[];
+    };
+
+  };
+
+
+  /*! A graph wrapper class 
+    for merging the node-sets and edge-sets of 
+    two node-disjoint graphs 
+    into one graph.
+   */
   template <typename _Graph1, typename _Graph2>
   class MergeEdgeGraphWrapper : public 
   IterableGraphExtender<MergeEdgeGraphWrapperBase<_Graph1, _Graph2> > {
@@ -430,6 +723,11 @@
   };
 
   
+  /*! A graph wrapper base class for the following functionality.
+    If a bijection is given between the node-sets of two graphs, 
+    then the second one can be considered as a new edge-set 
+    over th first node-set. 
+   */
   template <typename _Graph, typename _EdgeSetGraph>
   class NewEdgeSetGraphWrapperBase : public GraphWrapperBase<_Graph> {
   public:
@@ -507,7 +805,7 @@
     bool forward(const Edge& e) const { return edge_set_graph->forward(e); }
     bool backward(const Edge& e) const { return edge_set_graph->backward(e); }
 
-    using Parent::id;
+    int id(const Node& e) const { return Parent::id(e); }
     int id(const Edge& e) const { return edge_set_graph->id(e); }
     
     Edge opposite(const Edge& e) const { return edge_set_graph->opposite(e); }
@@ -526,6 +824,12 @@
 
   };
 
+
+  /*! A graph wrapper class for the following functionality.
+    If a bijection is given between the node-sets of two graphs, 
+    then the second one can be considered as a new edge-set 
+    over th first node-set. 
+   */
   template <typename _Graph, typename _EdgeSetGraph>
   class NewEdgeSetGraphWrapper : 
     public IterableGraphExtender<
@@ -551,6 +855,212 @@
     }
   };
 
+
+  /*! A graph wrapper base class 
+    for merging graphs of type _Graph1 and _Graph2 
+    which are given on the same node-set 
+    (specially on the node-set of Graph1) 
+    into one graph.
+    In an other point of view, _Graph1 is extended with 
+    the edge-set of _Graph2.
+   */
+  template <typename _Graph1, typename _Graph2, typename Enable=void>
+  class AugmentingGraphWrapperBase : 
+    public P1<_Graph1> {
+  public:
+    void printAugment() const { std::cout << "generic" << std::endl; }
+    typedef _Graph1 Graph1;
+    typedef _Graph2 Graph2;
+    typedef P1<_Graph1> Parent1;
+    typedef P2<_Graph2> Parent2;
+    typedef typename Parent1::Edge Graph1Edge;
+    typedef typename Parent2::Edge Graph2Edge;
+  protected:
+    AugmentingGraphWrapperBase() { }
+    _Graph2* graph2;
+    void setGraph2(_Graph2& _graph2) { graph2=&_graph2; }
+  public:
+    
+    template <typename _Value> class EdgeMap;
+
+    typedef typename Parent1::Node Node;
+
+    class Edge : public Graph1Edge, public Graph2Edge {
+      friend class AugmentingGraphWrapperBase<_Graph1, _Graph2>;
+      template <typename _Value> friend class EdgeMap;
+    protected:
+      bool backward; //true, iff backward
+    public:
+      Edge() { }
+      /// \todo =false is needed, or causes problems?
+      /// If \c _backward is false, then we get an edge corresponding to the 
+      /// original one, otherwise its oppositely directed pair is obtained.
+      Edge(const Graph1Edge& n1, 
+	   const Graph2Edge& n2, bool _backward) : 
+	Graph1Edge(n1), Graph2Edge(n2), backward(_backward) { }
+      Edge(Invalid i) : Graph1Edge(i), Graph2Edge(i), backward(true) { }
+      bool operator==(const Edge& v) const { 
+	if (backward) 
+	  return (v.backward && 
+		  static_cast<Graph2Edge>(*this)==static_cast<Graph2Edge>(v)); 
+	else 
+	  return (!v.backward && 
+		  static_cast<Graph1Edge>(*this)==static_cast<Graph1Edge>(v)); 
+      } 
+      bool operator!=(const Edge& v) const { 
+	return !(*this==v);
+      }
+    };
+
+    using Parent1::first;
+    void first(Edge& i) const {
+      Parent1::graph->first(*static_cast<Graph1Edge*>(&i));
+      i.backward=false;
+      if (*static_cast<Graph1Edge*>(&i)==INVALID) {
+	graph2->first(*static_cast<Graph2Edge*>(&i));
+	i.backward=true;
+      }
+    }
+    void firstIn(Edge& i, const Node& n) const {
+      Parent1::graph->firstIn(*static_cast<Graph1Edge*>(&i), n);
+      i.backward=false;
+      if (*static_cast<Graph1Edge*>(&i)==INVALID) {
+	graph2->firstIn(*static_cast<Graph2Edge*>(&i), n);
+	i.backward=true;
+      }
+    }
+    void firstOut(Edge& i, const Node& n) const {
+      Parent1::graph->firstOut(*static_cast<Graph1Edge*>(&i), n);
+      i.backward=false;
+      if (*static_cast<Graph1Edge*>(&i)==INVALID) {
+	graph2->firstOut(*static_cast<Graph2Edge*>(&i), n);
+	i.backward=true;
+      }
+    }
+
+    using Parent1::next;
+    void next(Edge& i) const {
+      if (!(i.backward)) {
+	Parent1::graph->next(*static_cast<Graph1Edge*>(&i));
+	if (*static_cast<Graph1Edge*>(&i)==INVALID) {
+	  graph2->first(*static_cast<Graph2Edge*>(&i));
+	  i.backward=true;
+	}
+      } else {
+	graph2->next(*static_cast<Graph2Edge*>(&i));
+      }
+    }
+    void nextIn(Edge& i) const {
+      if (!(i.backward)) {
+	Parent1::graph->nextIn(*static_cast<Graph1Edge*>(&i));
+	if (*static_cast<Graph1Edge*>(&i)==INVALID) {
+	  graph2->first(*static_cast<Graph2Edge*>(&i));
+	  i.backward=true;
+	}
+      } else {
+	graph2->nextIn(*static_cast<Graph2Edge*>(&i));
+      }
+    }
+    void nextOut(Edge& i) const {
+      if (!(i.backward)) {
+	Parent1::graph->nextOut(*static_cast<Graph1Edge*>(&i));
+	if (*static_cast<Graph1Edge*>(&i)==INVALID) {
+	  graph2->first(*static_cast<Graph2Edge*>(&i));
+	  i.backward=true;
+	}
+      } else {
+	graph2->nextOut(*static_cast<Graph2Edge*>(&i));
+      }
+    }
+
+    Node source(const Edge& i) const {
+      if (!(i.backward)) {
+	return Parent1::graph->source(i);
+      } else {
+	return graph2->source(i);
+      }
+    }
+
+    Node target(const Edge& i) const {
+      if (!(i.backward)) {
+	return Parent1::graph->target(i);
+      } else {
+	return graph2->target(i);
+      }
+    }
+
+    int id(const Node& n) const {
+      return Parent1::id(n);
+    };
+    int id(const Edge& n) const { 
+      if (!n.backward) 
+	return this->Parent1::graph->id(n);
+      else
+	return this->graph2->id(n);
+    }
+
+    template <typename _Value> 
+    class EdgeMap { 
+    protected:
+      typedef typename _Graph1::template EdgeMap<_Value> ParentMap1;
+      typedef typename _Graph2::template EdgeMap<_Value> ParentMap2;
+      ParentMap1 forward_map;
+      ParentMap2 backward_map;
+    public:
+      typedef _Value Value;
+      typedef Edge Key;
+      EdgeMap(const AugmentingGraphWrapperBase<_Graph1, _Graph2>& gw) : 
+	forward_map(*(gw.Parent1::graph)), 
+	backward_map(*(gw.graph2)) { }
+      EdgeMap(const AugmentingGraphWrapperBase<_Graph1, _Graph2>& gw, 
+	      const _Value& value) : 
+	forward_map(*(gw.Parent1::graph), value), 
+	backward_map(*(gw.graph2), value) { }
+      _Value operator[](const Edge& n) const {
+	if (!n.backward) 
+	  return forward_map[n];
+	else 
+	  return backward_map[n];
+      }
+      void set(const Edge& n, const _Value& value) {
+	if (!n.backward) 
+	  forward_map.set(n, value);
+	else 
+	  backward_map.set(n, value);
+      }
+//       using ParentMap1::operator[];
+//       using ParentMap2::operator[];
+    };
+
+  };
+
+
+  /*! A graph wrapper class 
+    for merging two graphs (of type _Graph1 and _Graph2)
+    with the same node-set 
+    (specially on the node-set of Graph1) 
+    into one graph. 
+    In an other point of view, _Graph1 is extended with 
+    the edge-set of _Graph2.
+   */  
+  template <typename _Graph1, typename _Graph2>
+  class AugmentingGraphWrapper : public 
+  IterableGraphExtender<AugmentingGraphWrapperBase<_Graph1, _Graph2> > {
+  public:
+    typedef 
+    IterableGraphExtender<AugmentingGraphWrapperBase<_Graph1, _Graph2> >
+    Parent;
+    typedef _Graph1 Graph1;
+    typedef _Graph2 Graph2;
+  protected:
+    AugmentingGraphWrapper() { }
+  public:
+    AugmentingGraphWrapper(_Graph1& _graph1, _Graph2& _graph2) { 
+      setGraph(_graph1); 
+      setGraph2(_graph2);
+    }
+  };
+
 } //namespace lemon
 
 #endif //LEMON_MERGE_NODE_GRAPH_WRAPPER_H

Modified: hugo/trunk/src/work/marci/merge_node_graph_wrapper_test.cc
==============================================================================
--- hugo/trunk/src/work/marci/merge_node_graph_wrapper_test.cc	(original)
+++ hugo/trunk/src/work/marci/merge_node_graph_wrapper_test.cc	Sat Nov 20 15:09:27 2004
@@ -4,6 +4,7 @@
 #include <lemon/list_graph.h>
 #include <lemon/smart_graph.h>
 #include <lemon/dimacs.h>
+#include <lemon/full_graph.h>
 #include <merge_node_graph_wrapper.h>
 
 #include<lemon/concept_check.h>
@@ -21,165 +22,141 @@
   class Edge { };
 };
 
-int main() {
-  typedef SmartGraph Graph1;
-  typedef ListGraph Graph2;
-  
-  {
-    checkConcept<StaticGraph, NewEdgeSetGraphWrapper<Graph1, Graph2> >(); 
-  }
-  {
-    checkConcept<StaticGraph, MergeEdgeGraphWrapper<Graph1, Graph2> >(); 
-  }
-  
-  Graph1 g;
-  Graph2 h;
-  typedef MergeEdgeGraphWrapper<Graph1, Graph2> GW;
-  GW gw(g, h);
-
-  std::ifstream f1("graph1.dim");
-  std::ifstream f2("graph2.dim");
-  readDimacs(f1, g);
-  readDimacs(f2, h);
-  {
-
-//   Graph1::Node n1=g.addNode();
-//   Graph1::Node n2=g.addNode();
-//   Graph1::Node n3=g.addNode();
-//   Graph2::Node n4=h.addNode();
-//   Graph2::Node n5=h.addNode();
-//   Graph2::Node n6=h.addNode();
-//   Graph1::Edge e1=g.addEdge(n1, n2);
-//   Graph1::Edge e2=g.addEdge(n1, n3);
-//   Graph2::Edge e3=h.addEdge(n4, n5);
-//   Graph2::Edge e4=h.addEdge(n4, n5);
-  //GW::NodeIt n(gw)
-  cout << "1st graph" << endl;
+template <typename Graph>
+void printGraph(const Graph& g) {
   cout << " nodes:" << endl;
-  for (Graph1::NodeIt n(g); n!=INVALID; ++n) { 
+  for (typename Graph::NodeIt n(g); n!=INVALID; ++n) { 
     cout << "  " << g.id(n) << endl;
   }
   cout << " edges:" << endl;
-  for (Graph1::EdgeIt n(g); n!=INVALID; ++n) { 
+  for (typename Graph::EdgeIt n(g); n!=INVALID; ++n) { 
     cout << "  " << g.id(n) << ": " 
 	 << g.id(g.source(n)) << "->" << g.id(g.target(n)) << endl;
-  }
-  cout << "2nd graph" << endl;
-  cout << " nodes:" << endl;
-  for (Graph2::NodeIt n(h); n!=INVALID; ++n) { 
-    cout << "  " << h.id(n) << endl;
-  }
-  cout << " edges:" << endl;
-  for (Graph2::EdgeIt n(h); n!=INVALID; ++n) { 
-    cout << "  " << h.id(n) << ": " 
-	 << h.id(h.source(n)) << "->" << h.id(h.target(n)) << endl;
-  }
-  cout << "merged graph" << endl;
-  cout << " nodes:" << endl;
-  for (GW::NodeIt n(gw); n!=INVALID; ++n) { 
-    cout << "  "<< gw.id(n) << endl;
-  }
-  cout << " edges:" << endl;
-  for (GW::EdgeIt n(gw); n!=INVALID; ++n) { 
-    cout << "  " << gw.id(n) << ": " 
-	 << gw.id(gw.source(n)) << "->" << gw.id(gw.target(n)) << endl;
-  }
-
-  GW::NodeMap<int> nm(gw);
-  int i=0;
-  for (GW::NodeIt n(gw); n!=INVALID; ++n) { 
-    ++i;
-    nm.set(n, i);
-  }
-  for (Graph1::NodeIt n(g); n!=INVALID; ++n) { 
-    cout << nm[GW::Node(n,INVALID,false)] << endl;
-  }
-  for (Graph2::NodeIt n(h); n!=INVALID; ++n) { 
-    cout << nm[GW::Node(INVALID,n,true)] << endl;
-  }
-
-  gw.printNode();
+  }  
+}
 
+int main() {
   {
-//    typedef SmartGraph Graph1;
-    typedef ListGraph Graph1;
-    typedef ListGraph Graph2;
-    Graph1 g;
-    Graph2 h;
-    typedef MergeNodeGraphWrapper<Graph1, Graph2> GW;
-    GW gw(g, h);    
-    gw.printNode();
-  }
-  {
-//    typedef SmartGraph Graph1;
-    typedef Graph3 Graph1;
+    cout << "FIRST TEST" << endl;
+    typedef SmartGraph Graph1;
     typedef ListGraph Graph2;
-    Graph1 g;
-    Graph2 h;
-    typedef MergeNodeGraphWrapper<Graph1, Graph2> GW;
-    GW gw(g, h);    
-    gw.printNode();
-  }
-  {
-//    typedef SmartGraph Graph1;
-    typedef ListGraph Graph1;
-    typedef Graph3 Graph2;
-    Graph1 g;
-    Graph2 h;
-    typedef MergeNodeGraphWrapper<Graph1, Graph2> GW;
-    GW gw(g, h);    
-    gw.printNode();
-  }
+    
+    {
+      checkConcept<StaticGraph, MergeEdgeGraphWrapper<Graph1, Graph2> >();   
+      MergeEdgeGraphWrapper<Graph1, Graph2>::printNode(); 
+      MergeEdgeGraphWrapper<Graph1, Graph2>::printEdge(); 
+      checkConcept<StaticGraph, MergeEdgeGraphWrapper<Graph1, Graph1> >();   
+      MergeEdgeGraphWrapper<Graph1, Graph1>::printNode(); 
+      MergeEdgeGraphWrapper<Graph1, Graph1>::printEdge(); 
+    }
+  
+    Graph1 g1;
+    Graph2 g2;
+    typedef MergeEdgeGraphWrapper<Graph1, Graph2> GW;
+    GW gw(g1, g2);
+
+    std::ifstream f1("graph1.dim");
+    std::ifstream f2("graph2.dim");
+    readDimacs(f1, g1);
+    readDimacs(f2, g2);
+    
+    cout << "1st graph" << endl;
+    printGraph(g1);
+
+    cout << "2nd graph" << endl;
+    printGraph(g2);
+
+    cout << "merged graph" << endl;
+    printGraph(gw);
+
   }
+
+
   {
-    Graph1 g;
-    Graph2 h;
-    typedef Graph1::Node Node1;
-    typedef Graph2::Node Node2;
-    typedef NewEdgeSetGraphWrapper<Graph1, Graph2> GW;
-    Graph1::NodeMap<Graph2::Node> e_node(g);
-    Graph2::NodeMap<Graph1::Node> n_node(h);
-    GW gw(g, h, e_node, n_node);
-    for (int i=0; i<4; ++i) { 
-      Node1 n=g.addNode();
-      e_node.set(n, INVALID);
-    }
-    for (int i=0; i<4; ++i) {
-      Graph1::Node n1=g.addNode();
-      Graph2::Node n2=h.addNode();
-      e_node.set(n1, n2);
-      n_node.set(n2, n1);
-    }
-    for (Graph2::NodeIt n(h); n!=INVALID; ++n)
-      for (Graph2::NodeIt m(h); m!=INVALID; ++m)
-	if ((h.id(n)+h.id(m))%3==0) h.addEdge(n, m);
-//     Graph1::NodeIt n(g);
-//     Node1 n1=n;
-//     Node1 n2=++n;
-//     Node1 n3=++n;
-//     Node1 n4=n;
-//     gw.addEdge(n1, n2);
-//     gw.addEdge(n1, n2);
-//     for (EdgeIt(e))
-//   Graph1::Node n1=g.addNode();
-//   Graph1::Node n2=g.addNode();
-//   Graph1::Node n3=g.addNode();
-//   Graph2::Node n4=h.addNode();
-//   Graph2::Node n5=h.addNode();
-    for (GW::EdgeIt e(gw); e!=INVALID; ++e) 
-      cout << gw.id(e) << endl;
+    cout << "SECOND TEST" << endl;
+    typedef SmartGraph Graph1;
+    {
+      checkConcept<StaticGraph, Graph1>();
+    }
+
+    Graph1 g1;
+
+    FullGraph pre_g2(2);
+    ConstMap<FullGraph::Edge, bool> const_false_map(false);
+    typedef EdgeSubGraphWrapper<FullGraph, ConstMap<FullGraph::Edge, bool> >
+      Graph2;
+    {
+      checkConcept<StaticGraph, Graph2>();
+    }
+
+    Graph2 g2(pre_g2, const_false_map);
+
+    typedef MergeEdgeGraphWrapper<Graph1, Graph2> GW;
+    {
+      checkConcept<StaticGraph, GW>();   
+    }
+    GW gw(g1, g2);
+    GW::Node sw;
+    GW::Node tw;
+    {
+      Graph2::NodeIt k(g2);
+      sw=GW::Node(INVALID, k, true);
+      ++k;
+      tw=GW::Node(INVALID, k, true);
+    }
+
+    std::ifstream f1("graph2.dim");
+    readDimacs(f1, g1);
+
+    cout << "1st graph" << endl;
+    printGraph(g1);
+
+    cout << "2nd graph" << endl;
+    printGraph(g2);
+
+    cout << "merged graph" << endl;
+    printGraph(gw);
+
+    typedef ListGraph Graph3;
+    Graph3 g3;
+    GW::NodeMap<Graph3::Node> gwn(gw);
+    Graph3::NodeMap<GW::Node> g3n(g3);
     for (GW::NodeIt n(gw); n!=INVALID; ++n) {
-      if (e_node[n]==INVALID) {
- 	cout<<gw.id(n)<<" INVALID"<<endl;
-      } else {
-	cout <<gw.id(n)<<" "<<h.id(e_node[n])<<" out_edges: ";
-	//	cout << &e_node << endl;
-	//cout << &n_node << endl;
-	for (GW::OutEdgeIt e(gw, n); e!=INVALID; ++e) {
-	  cout<<gw.id(e)<<" ";
-	}
-	cout<< endl;
-      }
+      Graph3::Node m=g3.addNode();
+      gwn.set(n, m);
+      g3n.set(m, n);
+    }
+
+    typedef NewEdgeSetGraphWrapper<GW, Graph3> GWW;
+    {
+      checkConcept<StaticGraph, GWW>();   
     }
+
+    GWW gww(gw, g3, gwn, g3n);
+
+    for (Graph1::NodeIt n(g1); n!=INVALID; ++n) {
+      g3.addEdge(gwn[sw], gwn[GW::Node(n,INVALID,false)]);
+    }
+
+//     for (Graph1::NodeIt n(g1); n!=INVALID; ++n) {
+//       gww.addEdge(sw, GW::Node(n,INVALID,false));
+//     }
+
+    cout << "new edges" << endl;
+    printGraph(g3);
+
+    cout << "new edges in the new graph" << endl;
+    printGraph(gww);
+
+    typedef AugmentingGraphWrapper<GW, GWW> GWWW;
+    {
+      checkConcept<StaticGraph, GWWW>();   
+    }
+    GWWW gwww(gw, gww);
+
+    cout << "new edges merged into the original graph" << endl;
+    printGraph(gwww);
+
   }
+
 }



More information about the Lemon-commits mailing list