bug fix in SubBidirGraphWrapper, roadmap to MergeGraphWrapper
authormarci
Mon, 22 Nov 2004 09:09:18 +0000
changeset 101618d009b23e42
parent 1015 e3bb0e118bb4
child 1017 f588efc6d607
bug fix in SubBidirGraphWrapper, roadmap to MergeGraphWrapper
src/lemon/graph_wrapper.h
src/work/marci/makefile
src/work/marci/merge_node_graph_wrapper.h
src/work/marci/merge_node_graph_wrapper_test.cc
     1.1 --- a/src/lemon/graph_wrapper.h	Sat Nov 20 16:12:47 2004 +0000
     1.2 +++ b/src/lemon/graph_wrapper.h	Mon Nov 22 09:09:18 2004 +0000
     1.3 @@ -1192,7 +1192,7 @@
     1.4  //       }
     1.5  
     1.6  //      typename _Graph::template EdgeMap<T>::Reference 
     1.7 -      T operator[](Edge e) { 
     1.8 +      T operator[](Edge e) const { 
     1.9  	if (!e.backward) 
    1.10  	  return forward_map[e]; 
    1.11  	else 
     2.1 --- a/src/work/marci/makefile	Sat Nov 20 16:12:47 2004 +0000
     2.2 +++ b/src/work/marci/makefile	Mon Nov 22 09:09:18 2004 +0000
     2.3 @@ -1,7 +1,7 @@
     2.4  CXX2 = g++-2.95
     2.5  CXX3=$(CXX)
     2.6  BOOSTROOT ?= /home/marci/boost
     2.7 -INCLUDEDIRS ?= -I../{jacint,marci,alpar,klao,akos,athos} -I../.. -I.. -I$(BOOSTROOT)
     2.8 +INCLUDEDIRS ?= -ftemplate-depth-50 -I../{jacint,marci,alpar,klao,akos,athos} -I../.. -I.. -I$(BOOSTROOT)
     2.9  
    2.10  LEDABINARIES = leda_graph_demo leda_bfs_dfs max_bipartite_matching_demo
    2.11  BINARIES = merge_node_graph_wrapper_test# bfsit_vs_byhand max_flow_demo bfs_mm_test# sub_graph_wrapper_demo.cc graph_wrapper_time iterator_bfs_demo macro_test lg_vs_sg_vs_sg bipartite_graph_wrapper_test bipartite_matching_demo top_sort_test max_flow_1 proba7 proba10 
     3.1 --- a/src/work/marci/merge_node_graph_wrapper.h	Sat Nov 20 16:12:47 2004 +0000
     3.2 +++ b/src/work/marci/merge_node_graph_wrapper.h	Mon Nov 22 09:09:18 2004 +0000
     3.3 @@ -270,8 +270,7 @@
     3.4      for merging the node-set of two node-disjoint graphs 
     3.5      into the node-set of one graph. 
     3.6      Specialization for the case when 
     3.7 -    _Graph1::Node are base and derived _Graph2::Node.
     3.8 -    NOT YET IMPLEMENTED
     3.9 +    _Graph1::Node is a base class and _Graph2::Node is derived from it.
    3.10     */
    3.11    template <typename _Graph1, typename _Graph2>
    3.12    class MergeNodeGraphWrapperBase<
    3.13 @@ -289,13 +288,109 @@
    3.14    protected:
    3.15      MergeNodeGraphWrapperBase() { }
    3.16    public:
    3.17 -    class Node { };
    3.18 +    template <typename _Value> class NodeMap;
    3.19 +
    3.20 +    class Node : public Graph2Node {
    3.21 +      friend class MergeNodeGraphWrapperBase<_Graph1, _Graph2>;
    3.22 +      template <typename _Value> friend class NodeMap;
    3.23 +    protected:
    3.24 +      bool backward; //true, iff backward
    3.25 +    public:
    3.26 +      Node() { }
    3.27 +      /// \todo =false is needed, or causes problems?
    3.28 +      /// If \c _backward is false, then we get an edge corresponding to the 
    3.29 +      /// original one, otherwise its oppositely directed pair is obtained.
    3.30 +      Node(const Graph1Node& n1, 
    3.31 +	   const Graph2Node& n2, bool _backward) : 
    3.32 +	Graph2Node(n2), backward(_backward) { 
    3.33 +	if (!backward) *this=n1;
    3.34 +      }
    3.35 +      Node(Invalid i) : Graph2Node(i), backward(true) { }
    3.36 +      bool operator==(const Node& v) const { 
    3.37 +	if (backward) 
    3.38 +	  return (v.backward && 
    3.39 +		  static_cast<Graph2Node>(*this)==static_cast<Graph2Node>(v)); 
    3.40 +	else 
    3.41 +	  return (!v.backward && 
    3.42 +		  static_cast<Graph1Node>(*this)==static_cast<Graph1Node>(v)); 
    3.43 +      } 
    3.44 +      bool operator!=(const Node& v) const { 
    3.45 +	return !(*this==v);
    3.46 +      }
    3.47 +    };
    3.48 +
    3.49 +    //typedef void Edge;
    3.50      class Edge { };
    3.51 -    void first() const;
    3.52 -    void next() const;
    3.53 +    
    3.54 +    void first(Node& i) const {
    3.55 +      Parent1::graph->first(*static_cast<Graph1Node*>(&i));
    3.56 +      i.backward=false;
    3.57 +      if (*static_cast<Graph1Node*>(&i)==INVALID) {
    3.58 +	Parent2::graph->first(*static_cast<Graph2Node*>(&i));
    3.59 +	i.backward=true;
    3.60 +      }
    3.61 +    }
    3.62 +    void next(Node& i) const {
    3.63 +      if (!(i.backward)) {
    3.64 +	Parent1::graph->next(*static_cast<Graph1Node*>(&i));
    3.65 +	if (*static_cast<Graph1Node*>(&i)==INVALID) {
    3.66 +	  Parent2::graph->first(*static_cast<Graph2Node*>(&i));
    3.67 +	  i.backward=true;
    3.68 +	}
    3.69 +      } else {
    3.70 +	Parent2::graph->next(*static_cast<Graph2Node*>(&i));
    3.71 +      }
    3.72 +    }
    3.73 +
    3.74 +    int id(const Node& n) const { 
    3.75 +      if (!n.backward) 
    3.76 +	return this->Parent1::graph->id(n);
    3.77 +      else
    3.78 +	return this->Parent2::graph->id(n);
    3.79 +    }
    3.80 +
    3.81 +    template <typename _Value> 
    3.82 +    class NodeMap { 
    3.83 +    protected:
    3.84 +      typedef typename _Graph1::template NodeMap<_Value> ParentMap1;
    3.85 +      typedef typename _Graph2::template NodeMap<_Value> ParentMap2;
    3.86 +      ParentMap1 forward_map;
    3.87 +      ParentMap2 backward_map;
    3.88 +    public:
    3.89 +      typedef _Value Value;
    3.90 +      typedef Node Key;
    3.91 +      NodeMap(const MergeNodeGraphWrapperBase<_Graph1, _Graph2>& gw) : 
    3.92 +	forward_map(*(gw.Parent1::graph)), 
    3.93 +	backward_map(*(gw.Parent2::graph)) { }
    3.94 +      NodeMap(const MergeNodeGraphWrapperBase<_Graph1, _Graph2>& gw, 
    3.95 +	      const _Value& value) : 
    3.96 +	forward_map(*(gw.Parent1::graph), value), 
    3.97 +	backward_map(*(gw.Parent2::graph), value) { }
    3.98 +      _Value operator[](const Node& n) const {
    3.99 +	if (!n.backward) 
   3.100 +	  return forward_map[n];
   3.101 +	else 
   3.102 +	  return backward_map[n];
   3.103 +      }
   3.104 +      void set(const Node& n, const _Value& value) {
   3.105 +	if (!n.backward) 
   3.106 +	  forward_map.set(n, value);
   3.107 +	else 
   3.108 +	  backward_map.set(n, value);
   3.109 +      }
   3.110 +//       using ParentMap1::operator[];
   3.111 +//       using ParentMap2::operator[];
   3.112 +    };
   3.113 +
   3.114    };
   3.115  
   3.116 -  //not yet working
   3.117 +
   3.118 +  /*! A graph wrapper base class 
   3.119 +    for merging the node-set of two node-disjoint graphs 
   3.120 +    into the node-set of one graph. 
   3.121 +    Specialized implementaton for the case when _Graph1::Node is derived 
   3.122 +    from _Graph2::Node.
   3.123 +   */
   3.124    template <typename _Graph1, typename _Graph2>
   3.125    class MergeNodeGraphWrapperBase<
   3.126      _Graph1, _Graph2, typename boost::enable_if<
   3.127 @@ -312,10 +407,100 @@
   3.128    protected:
   3.129      MergeNodeGraphWrapperBase() { }
   3.130    public:
   3.131 -    class Node { };
   3.132 +    template <typename _Value> class NodeMap;
   3.133 +
   3.134 +    class Node : public Graph1Node {
   3.135 +      friend class MergeNodeGraphWrapperBase<_Graph1, _Graph2>;
   3.136 +      template <typename _Value> friend class NodeMap;
   3.137 +    protected:
   3.138 +      bool backward; //true, iff backward
   3.139 +    public:
   3.140 +      Node() { }
   3.141 +      /// \todo =false is needed, or causes problems?
   3.142 +      /// If \c _backward is false, then we get an edge corresponding to the 
   3.143 +      /// original one, otherwise its oppositely directed pair is obtained.
   3.144 +      Node(const Graph1Node& n1, 
   3.145 +	   const Graph2Node& n2, bool _backward) : 
   3.146 +	Graph1Node(n1), backward(_backward) { 
   3.147 +	if (backward) *this=n2;
   3.148 +      }
   3.149 +      Node(Invalid i) : Graph1Node(i), backward(true) { }
   3.150 +      bool operator==(const Node& v) const { 
   3.151 +	if (backward) 
   3.152 +	  return (v.backward && 
   3.153 +		  static_cast<Graph2Node>(*this)==static_cast<Graph2Node>(v)); 
   3.154 +	else 
   3.155 +	  return (!v.backward && 
   3.156 +		  static_cast<Graph1Node>(*this)==static_cast<Graph1Node>(v)); 
   3.157 +      } 
   3.158 +      bool operator!=(const Node& v) const { 
   3.159 +	return !(*this==v);
   3.160 +      }
   3.161 +    };
   3.162 +
   3.163 +    //typedef void Edge;
   3.164      class Edge { };
   3.165 -    void first() const;
   3.166 -    void next() const;
   3.167 +    
   3.168 +    void first(Node& i) const {
   3.169 +      Parent1::graph->first(*static_cast<Graph1Node*>(&i));
   3.170 +      i.backward=false;
   3.171 +      if (*static_cast<Graph1Node*>(&i)==INVALID) {
   3.172 +	Parent2::graph->first(*static_cast<Graph2Node*>(&i));
   3.173 +	i.backward=true;
   3.174 +      }
   3.175 +    }
   3.176 +    void next(Node& i) const {
   3.177 +      if (!(i.backward)) {
   3.178 +	Parent1::graph->next(*static_cast<Graph1Node*>(&i));
   3.179 +	if (*static_cast<Graph1Node*>(&i)==INVALID) {
   3.180 +	  Parent2::graph->first(*static_cast<Graph2Node*>(&i));
   3.181 +	  i.backward=true;
   3.182 +	}
   3.183 +      } else {
   3.184 +	Parent2::graph->next(*static_cast<Graph2Node*>(&i));
   3.185 +      }
   3.186 +    }
   3.187 +
   3.188 +    int id(const Node& n) const { 
   3.189 +      if (!n.backward) 
   3.190 +	return this->Parent1::graph->id(n);
   3.191 +      else
   3.192 +	return this->Parent2::graph->id(n);
   3.193 +    }
   3.194 +
   3.195 +    template <typename _Value> 
   3.196 +    class NodeMap { 
   3.197 +    protected:
   3.198 +      typedef typename _Graph1::template NodeMap<_Value> ParentMap1;
   3.199 +      typedef typename _Graph2::template NodeMap<_Value> ParentMap2;
   3.200 +      ParentMap1 forward_map;
   3.201 +      ParentMap2 backward_map;
   3.202 +    public:
   3.203 +      typedef _Value Value;
   3.204 +      typedef Node Key;
   3.205 +      NodeMap(const MergeNodeGraphWrapperBase<_Graph1, _Graph2>& gw) : 
   3.206 +	forward_map(*(gw.Parent1::graph)), 
   3.207 +	backward_map(*(gw.Parent2::graph)) { }
   3.208 +      NodeMap(const MergeNodeGraphWrapperBase<_Graph1, _Graph2>& gw, 
   3.209 +	      const _Value& value) : 
   3.210 +	forward_map(*(gw.Parent1::graph), value), 
   3.211 +	backward_map(*(gw.Parent2::graph), value) { }
   3.212 +      _Value operator[](const Node& n) const {
   3.213 +	if (!n.backward) 
   3.214 +	  return forward_map[n];
   3.215 +	else 
   3.216 +	  return backward_map[n];
   3.217 +      }
   3.218 +      void set(const Node& n, const _Value& value) {
   3.219 +	if (!n.backward) 
   3.220 +	  forward_map.set(n, value);
   3.221 +	else 
   3.222 +	  backward_map.set(n, value);
   3.223 +      }
   3.224 +//       using ParentMap1::operator[];
   3.225 +//       using ParentMap2::operator[];
   3.226 +    };
   3.227 +
   3.228    };
   3.229  
   3.230  
   3.231 @@ -532,7 +717,7 @@
   3.232    template <typename _Graph1, typename _Graph2>
   3.233    class MergeEdgeGraphWrapperBase<
   3.234      _Graph1, _Graph2, typename boost::enable_if<
   3.235 -    boost::is_same<typename _Graph1::Node, typename _Graph2::Node> >::type> : 
   3.236 +    boost::is_same<typename _Graph1::Edge, typename _Graph2::Edge> >::type> : 
   3.237      public MergeNodeGraphWrapperBase<_Graph1, _Graph2> {
   3.238    public:
   3.239      static void printEdge() { std::cout << "edge: same" << std::endl; }
   3.240 @@ -700,6 +885,375 @@
   3.241    };
   3.242  
   3.243  
   3.244 +  /*! A grah wrapper base class 
   3.245 +    for merging the node-sets and edge-sets of 
   3.246 +    two node-disjoint graphs 
   3.247 +    into one graph. 
   3.248 +    Specialized implementation for the case 
   3.249 +    when _Graph1::Edge is a base class and _Graph2::Edge
   3.250 +    is derived from it.
   3.251 +   */
   3.252 +  template <typename _Graph1, typename _Graph2>
   3.253 +  class MergeEdgeGraphWrapperBase<
   3.254 +    _Graph1, _Graph2, typename boost::enable_if<
   3.255 +    boost::is_base_and_derived<typename _Graph1::Edge, typename _Graph2::Edge> >::type> : 
   3.256 +    public MergeNodeGraphWrapperBase<_Graph1, _Graph2> {
   3.257 +  public:
   3.258 +    static void printEdge() { std::cout << "edge: 2nd is derived" << std::endl; }
   3.259 +    typedef _Graph1 Graph1;
   3.260 +    typedef _Graph2 Graph2;
   3.261 +    typedef MergeNodeGraphWrapperBase<_Graph1, _Graph2> Parent;
   3.262 +    typedef typename Parent::Parent1 Parent1;
   3.263 +    typedef typename Parent::Parent2 Parent2;
   3.264 +//     typedef P1<_Graph1> Parent1;
   3.265 +//     typedef P2<_Graph2> Parent2;
   3.266 +    typedef typename Parent1::Edge Graph1Edge;
   3.267 +    typedef typename Parent2::Edge Graph2Edge;
   3.268 +  protected:
   3.269 +    MergeEdgeGraphWrapperBase() { }
   3.270 +  public:
   3.271 +    template <typename _Value> class EdgeMap;
   3.272 +
   3.273 +    typedef typename Parent::Node Node;
   3.274 +
   3.275 +    class Edge : public Graph2Edge {
   3.276 +      friend class MergeEdgeGraphWrapperBase<_Graph1, _Graph2>;
   3.277 +      template <typename _Value> friend class EdgeMap;
   3.278 +    protected:
   3.279 +      bool backward; //true, iff backward
   3.280 +    public:
   3.281 +      Edge() { }
   3.282 +      /// \todo =false is needed, or causes problems?
   3.283 +      /// If \c _backward is false, then we get an edge corresponding to the 
   3.284 +      /// original one, otherwise its oppositely directed pair is obtained.
   3.285 +      Edge(const Graph1Edge& n1, 
   3.286 +	   const Graph2Edge& n2, bool _backward) : 
   3.287 +	Graph2Edge(n2), backward(_backward) { 
   3.288 +	if (!backward) *this=n1;
   3.289 +      }
   3.290 +      Edge(Invalid i) : Graph2Edge(i), backward(true) { }
   3.291 +      bool operator==(const Edge& v) const { 
   3.292 +	if (backward) 
   3.293 +	  return (v.backward && 
   3.294 +		  static_cast<Graph2Edge>(*this)==static_cast<Graph2Edge>(v)); 
   3.295 +	else 
   3.296 +	  return (!v.backward && 
   3.297 +		  static_cast<Graph1Edge>(*this)==static_cast<Graph1Edge>(v)); 
   3.298 +      } 
   3.299 +      bool operator!=(const Edge& v) const { 
   3.300 +	return !(*this==v);
   3.301 +      }
   3.302 +    };
   3.303 +
   3.304 +    using Parent::first;
   3.305 +    void first(Edge& i) const {
   3.306 +      Parent1::graph->first(*static_cast<Graph1Edge*>(&i));
   3.307 +      i.backward=false;
   3.308 +      if (*static_cast<Graph1Edge*>(&i)==INVALID) {
   3.309 +	Parent2::graph->first(*static_cast<Graph2Edge*>(&i));
   3.310 +	i.backward=true;
   3.311 +      }
   3.312 +    }
   3.313 +    void firstIn(Edge& i, const Node& n) const {
   3.314 +      Parent1::graph->firstIn(*static_cast<Graph1Edge*>(&i), n);
   3.315 +      i.backward=false;
   3.316 +      if (*static_cast<Graph1Edge*>(&i)==INVALID) {
   3.317 +	Parent2::graph->firstIn(*static_cast<Graph2Edge*>(&i), n);
   3.318 +	i.backward=true;
   3.319 +      }
   3.320 +    }
   3.321 +    void firstOut(Edge& i, const Node& n) const {
   3.322 +      Parent1::graph->firstOut(*static_cast<Graph1Edge*>(&i), n);
   3.323 +      i.backward=false;
   3.324 +      if (*static_cast<Graph1Edge*>(&i)==INVALID) {
   3.325 +	Parent2::graph->firstOut(*static_cast<Graph2Edge*>(&i), n);
   3.326 +	i.backward=true;
   3.327 +      }
   3.328 +    }
   3.329 +
   3.330 +    using Parent::next;
   3.331 +    void next(Edge& i) const {
   3.332 +      if (!(i.backward)) {
   3.333 +	Parent1::graph->next(*static_cast<Graph1Edge*>(&i));
   3.334 +	if (*static_cast<Graph1Edge*>(&i)==INVALID) {
   3.335 +	  Parent2::graph->first(*static_cast<Graph2Edge*>(&i));
   3.336 +	  i.backward=true;
   3.337 +	}
   3.338 +      } else {
   3.339 +	Parent2::graph->next(*static_cast<Graph2Edge*>(&i));
   3.340 +      }
   3.341 +    }
   3.342 +    void nextIn(Edge& i) const {
   3.343 +      if (!(i.backward)) {
   3.344 +	Parent1::graph->nextIn(*static_cast<Graph1Edge*>(&i));
   3.345 +	if (*static_cast<Graph1Edge*>(&i)==INVALID) {
   3.346 +	  Parent2::graph->first(*static_cast<Graph2Edge*>(&i));
   3.347 +	  i.backward=true;
   3.348 +	}
   3.349 +      } else {
   3.350 +	Parent2::graph->nextIn(*static_cast<Graph2Edge*>(&i));
   3.351 +      }
   3.352 +    }
   3.353 +    void nextOut(Edge& i) const {
   3.354 +      if (!(i.backward)) {
   3.355 +	Parent1::graph->nextOut(*static_cast<Graph1Edge*>(&i));
   3.356 +	if (*static_cast<Graph1Edge*>(&i)==INVALID) {
   3.357 +	  Parent2::graph->first(*static_cast<Graph2Edge*>(&i));
   3.358 +	  i.backward=true;
   3.359 +	}
   3.360 +      } else {
   3.361 +	Parent2::graph->nextOut(*static_cast<Graph2Edge*>(&i));
   3.362 +      }
   3.363 +    }
   3.364 +
   3.365 +    Node source(const Edge& i) const {
   3.366 +      if (!(i.backward)) {
   3.367 +	return 
   3.368 +	  Node(Parent1::graph->source(i), INVALID, false);
   3.369 +      } else {
   3.370 +	return 
   3.371 +	  Node(INVALID, Parent2::graph->source(i), true);
   3.372 +      }
   3.373 +    }
   3.374 +
   3.375 +    Node target(const Edge& i) const {
   3.376 +      if (!(i.backward)) {
   3.377 +	return 
   3.378 +	  Node(Parent1::graph->target(i), INVALID, false);
   3.379 +      } else {
   3.380 +	return 
   3.381 +	  Node(INVALID, Parent2::graph->target(i), true);
   3.382 +      }
   3.383 +    }
   3.384 +
   3.385 +    using Parent::id;
   3.386 +    int id(const Edge& n) const { 
   3.387 +      if (!n.backward) 
   3.388 +	return this->Parent1::graph->id(n);
   3.389 +      else
   3.390 +	return this->Parent2::graph->id(n);
   3.391 +    }
   3.392 +
   3.393 +    template <typename _Value> 
   3.394 +    class EdgeMap { 
   3.395 +    protected:
   3.396 +      typedef typename Parent::Graph1::template EdgeMap<_Value> ParentMap1;
   3.397 +      typedef typename Parent::Graph2::template EdgeMap<_Value> ParentMap2;
   3.398 +      ParentMap1 forward_map;
   3.399 +      ParentMap2 backward_map;
   3.400 +    public:
   3.401 +      typedef _Value Value;
   3.402 +      typedef Edge Key;
   3.403 +      EdgeMap(const MergeEdgeGraphWrapperBase<_Graph1, _Graph2>& gw) : 
   3.404 +	forward_map(*(gw.Parent1::graph)), 
   3.405 +	backward_map(*(gw.Parent2::graph)) { }
   3.406 +      EdgeMap(const MergeEdgeGraphWrapperBase<_Graph1, _Graph2>& gw, 
   3.407 +	      const _Value& value) : 
   3.408 +	forward_map(*(gw.Parent1::graph), value), 
   3.409 +	backward_map(*(gw.Parent2::graph), value) { }
   3.410 +      _Value operator[](const Edge& n) const {
   3.411 +	if (!n.backward) 
   3.412 +	  return forward_map[n];
   3.413 +	else 
   3.414 +	  return backward_map[n];
   3.415 +      }
   3.416 +      void set(const Edge& n, const _Value& value) {
   3.417 +	if (!n.backward) 
   3.418 +	  forward_map.set(n, value);
   3.419 +	else 
   3.420 +	  backward_map.set(n, value);
   3.421 +      }
   3.422 +//       using ParentMap1::operator[];
   3.423 +//       using ParentMap2::operator[];
   3.424 +    };
   3.425 +
   3.426 +  };
   3.427 +
   3.428 +
   3.429 +  /*! A grah wrapper base class 
   3.430 +    for merging the node-sets and edge-sets of 
   3.431 +    two node-disjoint graphs 
   3.432 +    into one graph. 
   3.433 +    Specialized implementation for the case 
   3.434 +    when _Graph1::Edge is derived from _Graph2::Edge.
   3.435 +   */
   3.436 +  template <typename _Graph1, typename _Graph2>
   3.437 +  class MergeEdgeGraphWrapperBase<
   3.438 +    _Graph1, _Graph2, typename boost::enable_if<
   3.439 +    boost::is_base_and_derived<typename _Graph2::Edge, typename _Graph1::Edge> >::type> : 
   3.440 +    public MergeNodeGraphWrapperBase<_Graph1, _Graph2> {
   3.441 +  public:
   3.442 +    static void printEdge() { std::cout << "edge: 1st is derived" << std::endl; }
   3.443 +    typedef _Graph1 Graph1;
   3.444 +    typedef _Graph2 Graph2;
   3.445 +    typedef MergeNodeGraphWrapperBase<_Graph1, _Graph2> Parent;
   3.446 +    typedef typename Parent::Parent1 Parent1;
   3.447 +    typedef typename Parent::Parent2 Parent2;
   3.448 +//     typedef P1<_Graph1> Parent1;
   3.449 +//     typedef P2<_Graph2> Parent2;
   3.450 +    typedef typename Parent1::Edge Graph1Edge;
   3.451 +    typedef typename Parent2::Edge Graph2Edge;
   3.452 +  protected:
   3.453 +    MergeEdgeGraphWrapperBase() { }
   3.454 +  public:
   3.455 +    template <typename _Value> class EdgeMap;
   3.456 +
   3.457 +    typedef typename Parent::Node Node;
   3.458 +
   3.459 +    class Edge : public Graph1Edge {
   3.460 +      friend class MergeEdgeGraphWrapperBase<_Graph1, _Graph2>;
   3.461 +      template <typename _Value> friend class EdgeMap;
   3.462 +    protected:
   3.463 +      bool backward; //true, iff backward
   3.464 +    public:
   3.465 +      Edge() { }
   3.466 +      /// \todo =false is needed, or causes problems?
   3.467 +      /// If \c _backward is false, then we get an edge corresponding to the 
   3.468 +      /// original one, otherwise its oppositely directed pair is obtained.
   3.469 +      Edge(const Graph1Edge& n1, 
   3.470 +	   const Graph2Edge& n2, bool _backward) : 
   3.471 +	Graph1Edge(n1), backward(_backward) { 
   3.472 +	if (backward) *this=n2;
   3.473 +      }
   3.474 +      Edge(Invalid i) : Graph1Edge(i), backward(true) { }
   3.475 +      bool operator==(const Edge& v) const { 
   3.476 +	if (backward) 
   3.477 +	  return (v.backward && 
   3.478 +		  static_cast<Graph2Edge>(*this)==static_cast<Graph2Edge>(v)); 
   3.479 +	else 
   3.480 +	  return (!v.backward && 
   3.481 +		  static_cast<Graph1Edge>(*this)==static_cast<Graph1Edge>(v)); 
   3.482 +      } 
   3.483 +      bool operator!=(const Edge& v) const { 
   3.484 +	return !(*this==v);
   3.485 +      }
   3.486 +    };
   3.487 +
   3.488 +    using Parent::first;
   3.489 +    void first(Edge& i) const {
   3.490 +      Parent1::graph->first(*static_cast<Graph1Edge*>(&i));
   3.491 +      i.backward=false;
   3.492 +      if (*static_cast<Graph1Edge*>(&i)==INVALID) {
   3.493 +	Parent2::graph->first(*static_cast<Graph2Edge*>(&i));
   3.494 +	i.backward=true;
   3.495 +      }
   3.496 +    }
   3.497 +    void firstIn(Edge& i, const Node& n) const {
   3.498 +      Parent1::graph->firstIn(*static_cast<Graph1Edge*>(&i), n);
   3.499 +      i.backward=false;
   3.500 +      if (*static_cast<Graph1Edge*>(&i)==INVALID) {
   3.501 +	Parent2::graph->firstIn(*static_cast<Graph2Edge*>(&i), n);
   3.502 +	i.backward=true;
   3.503 +      }
   3.504 +    }
   3.505 +    void firstOut(Edge& i, const Node& n) const {
   3.506 +      Parent1::graph->firstOut(*static_cast<Graph1Edge*>(&i), n);
   3.507 +      i.backward=false;
   3.508 +      if (*static_cast<Graph1Edge*>(&i)==INVALID) {
   3.509 +	Parent2::graph->firstOut(*static_cast<Graph2Edge*>(&i), n);
   3.510 +	i.backward=true;
   3.511 +      }
   3.512 +    }
   3.513 +
   3.514 +    using Parent::next;
   3.515 +    void next(Edge& i) const {
   3.516 +      if (!(i.backward)) {
   3.517 +	Parent1::graph->next(*static_cast<Graph1Edge*>(&i));
   3.518 +	if (*static_cast<Graph1Edge*>(&i)==INVALID) {
   3.519 +	  Parent2::graph->first(*static_cast<Graph2Edge*>(&i));
   3.520 +	  i.backward=true;
   3.521 +	}
   3.522 +      } else {
   3.523 +	Parent2::graph->next(*static_cast<Graph2Edge*>(&i));
   3.524 +      }
   3.525 +    }
   3.526 +    void nextIn(Edge& i) const {
   3.527 +      if (!(i.backward)) {
   3.528 +	Parent1::graph->nextIn(*static_cast<Graph1Edge*>(&i));
   3.529 +	if (*static_cast<Graph1Edge*>(&i)==INVALID) {
   3.530 +	  Parent2::graph->first(*static_cast<Graph2Edge*>(&i));
   3.531 +	  i.backward=true;
   3.532 +	}
   3.533 +      } else {
   3.534 +	Parent2::graph->nextIn(*static_cast<Graph2Edge*>(&i));
   3.535 +      }
   3.536 +    }
   3.537 +    void nextOut(Edge& i) const {
   3.538 +      if (!(i.backward)) {
   3.539 +	Parent1::graph->nextOut(*static_cast<Graph1Edge*>(&i));
   3.540 +	if (*static_cast<Graph1Edge*>(&i)==INVALID) {
   3.541 +	  Parent2::graph->first(*static_cast<Graph2Edge*>(&i));
   3.542 +	  i.backward=true;
   3.543 +	}
   3.544 +      } else {
   3.545 +	Parent2::graph->nextOut(*static_cast<Graph2Edge*>(&i));
   3.546 +      }
   3.547 +    }
   3.548 +
   3.549 +    Node source(const Edge& i) const {
   3.550 +      if (!(i.backward)) {
   3.551 +	return 
   3.552 +	  Node(Parent1::graph->source(i), INVALID, false);
   3.553 +      } else {
   3.554 +	return 
   3.555 +	  Node(INVALID, Parent2::graph->source(i), true);
   3.556 +      }
   3.557 +    }
   3.558 +
   3.559 +    Node target(const Edge& i) const {
   3.560 +      if (!(i.backward)) {
   3.561 +	return 
   3.562 +	  Node(Parent1::graph->target(i), INVALID, false);
   3.563 +      } else {
   3.564 +	return 
   3.565 +	  Node(INVALID, Parent2::graph->target(i), true);
   3.566 +      }
   3.567 +    }
   3.568 +
   3.569 +    using Parent::id;
   3.570 +    int id(const Edge& n) const { 
   3.571 +      if (!n.backward) 
   3.572 +	return this->Parent1::graph->id(n);
   3.573 +      else
   3.574 +	return this->Parent2::graph->id(n);
   3.575 +    }
   3.576 +
   3.577 +    template <typename _Value> 
   3.578 +    class EdgeMap { 
   3.579 +    protected:
   3.580 +      typedef typename Parent::Graph1::template EdgeMap<_Value> ParentMap1;
   3.581 +      typedef typename Parent::Graph2::template EdgeMap<_Value> ParentMap2;
   3.582 +      ParentMap1 forward_map;
   3.583 +      ParentMap2 backward_map;
   3.584 +    public:
   3.585 +      typedef _Value Value;
   3.586 +      typedef Edge Key;
   3.587 +      EdgeMap(const MergeEdgeGraphWrapperBase<_Graph1, _Graph2>& gw) : 
   3.588 +	forward_map(*(gw.Parent1::graph)), 
   3.589 +	backward_map(*(gw.Parent2::graph)) { }
   3.590 +      EdgeMap(const MergeEdgeGraphWrapperBase<_Graph1, _Graph2>& gw, 
   3.591 +	      const _Value& value) : 
   3.592 +	forward_map(*(gw.Parent1::graph), value), 
   3.593 +	backward_map(*(gw.Parent2::graph), value) { }
   3.594 +      _Value operator[](const Edge& n) const {
   3.595 +	if (!n.backward) 
   3.596 +	  return forward_map[n];
   3.597 +	else 
   3.598 +	  return backward_map[n];
   3.599 +      }
   3.600 +      void set(const Edge& n, const _Value& value) {
   3.601 +	if (!n.backward) 
   3.602 +	  forward_map.set(n, value);
   3.603 +	else 
   3.604 +	  backward_map.set(n, value);
   3.605 +      }
   3.606 +//       using ParentMap1::operator[];
   3.607 +//       using ParentMap2::operator[];
   3.608 +    };
   3.609 +
   3.610 +  };
   3.611 +
   3.612 +
   3.613    /*! A graph wrapper class 
   3.614      for merging the node-sets and edge-sets of 
   3.615      two node-disjoint graphs 
     4.1 --- a/src/work/marci/merge_node_graph_wrapper_test.cc	Sat Nov 20 16:12:47 2004 +0000
     4.2 +++ b/src/work/marci/merge_node_graph_wrapper_test.cc	Mon Nov 22 09:09:18 2004 +0000
     4.3 @@ -48,6 +48,14 @@
     4.4        checkConcept<StaticGraph, MergeEdgeGraphWrapper<Graph1, Graph1> >();   
     4.5        MergeEdgeGraphWrapper<Graph1, Graph1>::printNode(); 
     4.6        MergeEdgeGraphWrapper<Graph1, Graph1>::printEdge(); 
     4.7 +      typedef ResGraphWrapper<Graph1, int, 
     4.8 +	ConstMap<Graph1, int>, ConstMap<Graph1, int> > Graph4;
     4.9 +      checkConcept<StaticGraph, MergeEdgeGraphWrapper<Graph1, Graph4> >();   
    4.10 +      MergeEdgeGraphWrapper<Graph1, Graph4>::printNode(); 
    4.11 +      MergeEdgeGraphWrapper<Graph1, Graph4>::printEdge();
    4.12 +      checkConcept<StaticGraph, MergeEdgeGraphWrapper<Graph4, Graph1> >();   
    4.13 +      MergeEdgeGraphWrapper<Graph4, Graph1>::printNode(); 
    4.14 +      MergeEdgeGraphWrapper<Graph4, Graph1>::printEdge();  
    4.15      }
    4.16    
    4.17      Graph1 g1;
    4.18 @@ -118,6 +126,7 @@
    4.19      printGraph(gw);
    4.20  
    4.21      typedef ListGraph Graph3;
    4.22 +    //typedef SmartGraph Graph3;
    4.23      Graph3 g3;
    4.24      GW::NodeMap<Graph3::Node> gwn(gw);
    4.25      Graph3::NodeMap<GW::Node> g3n(g3);