marci@915: /* -*- C++ -*-
alpar@921:  * src/lemon/merge_node_graph_wrapper.h - Part of LEMON, a generic C++ optimization library
marci@915:  *
marci@915:  * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
marci@915:  * (Egervary Combinatorial Optimization Research Group, EGRES).
marci@915:  *
marci@915:  * Permission to use, modify and distribute this software is granted
marci@915:  * provided that this copyright notice appears in all copies. For
marci@915:  * precise terms see the accompanying LICENSE file.
marci@915:  *
marci@915:  * This software is provided "AS IS" with no warranty of any kind,
marci@915:  * express or implied, and with no claim as to its suitability for any
marci@915:  * purpose.
marci@915:  *
marci@915:  */
marci@915: 
alpar@921: #ifndef LEMON_MERGE_NODE_GRAPH_WRAPPER_H
alpar@921: #define LEMON_MERGE_NODE_GRAPH_WRAPPER_H
marci@917: 
alpar@921: #include <lemon/invalid.h>
alpar@921: #include <lemon/maps.h>
alpar@921: #include <lemon/map_defines.h>
alpar@921: #include <lemon/graph_wrapper.h>
marci@915: #include <iostream>
marci@915: 
alpar@921: namespace lemon {
marci@915: 
marci@917:   template <typename Graph1, typename Graph2, typename Enable=void> 
marci@915:   class MergeNodeGraphWrapper : 
marci@915:     public GraphWrapper<Graph1>, public GraphWrapper<Graph2> {
marci@915:     typedef GraphWrapper<Graph1> Parent1;
marci@915:     typedef GraphWrapper<Graph2> Parent2;
marci@915:     typedef typename GraphWrapper<Graph1>::Node Graph1Node;
marci@915:     typedef typename GraphWrapper<Graph2>::Node Graph2Node;
marci@915:   public:
marci@915:     class Node;
marci@915:     class NodeIt;
marci@915:     friend class Node;
marci@915:     friend class NodeIt;
marci@917:     template<typename Value> class NodeMap;
marci@915: 
marci@915:     MergeNodeGraphWrapper(Graph1& _graph1, Graph2& _graph2) : 
marci@915:       Parent1(_graph1), Parent2(_graph2) { }
marci@915: 
marci@915:     class Node : public Graph1Node, public Graph2Node {
marci@915:       friend class MergeNodeGraphWrapper<Graph1, Graph2>;
marci@917:       template<typename Value> friend class NodeMap;
marci@915:     protected:
marci@915:       bool backward; //true, iff backward
marci@915:     public:
marci@915:       Node() { }
marci@915:       /// \todo =false is needed, or causes problems?
marci@915:       /// If \c _backward is false, then we get an edge corresponding to the 
marci@915:       /// original one, otherwise its oppositely directed pair is obtained.
marci@915:       Node(const Graph1Node& n1, 
marci@915: 	   const Graph2Node& n2, bool _backward) : 
marci@915: 	Graph1Node(n1), Graph2Node(n2), backward(_backward) { }
marci@915:       Node(Invalid i) : Graph1Node(i), Graph2Node(i), backward(true) { }
marci@915:       bool operator==(const Node& v) const { 
marci@915: 	return (this->backward==v.backward && 
marci@915: 		static_cast<Graph1Node>(*this)==
marci@915: 		static_cast<Graph1Node>(v) && 
marci@915: 		static_cast<Graph2Node>(*this)==
marci@915: 		static_cast<Graph2Node>(v));
marci@915:       } 
marci@915:       bool operator!=(const Node& v) const { 
marci@915: 	return (this->backward!=v.backward || 
marci@915: 		static_cast<Graph1Node>(*this)!=
marci@915: 		static_cast<Graph1Node>(v) || 
marci@915: 		static_cast<Graph2Node>(*this)!=
marci@915: 		static_cast<Graph2Node>(v));
marci@915:       }
marci@915:     };
marci@915: 
marci@915:     class NodeIt : public Node {
marci@915:       friend class MergeNodeGraphWrapper<Graph1, Graph2>;
marci@915:     protected:
marci@915:       const MergeNodeGraphWrapper<Graph1, Graph2>* gw;
marci@915:     public:
marci@915:       NodeIt() { }
marci@915:       NodeIt(Invalid i) : Node(i) { }
marci@915:       NodeIt(const MergeNodeGraphWrapper<Graph1, Graph2>& _gw) : 
marci@915: 	Node(typename Graph1::NodeIt(*_gw.Parent1::graph), 
marci@917: 	     typename Graph2::Node(),
marci@915: 	     false), gw(&_gw) { 
marci@915: 	if (*static_cast<Graph1Node*>(this)==INVALID) {
marci@917: // 	  *static_cast<Node*>(this)=
marci@917: // 	    Node(Graph1Node(INVALID), 
marci@917: // 		 typename Graph2::NodeIt(*_gw.Parent2::graph), 
marci@917: // 		 true);
marci@917: 	  *static_cast<Graph2Node*>(this)=
marci@917: 	    typename Graph2::NodeIt(*_gw.Parent2::graph);
marci@917: 	  backward=true;
marci@915: 	}
marci@915:       }
marci@915:       NodeIt(const MergeNodeGraphWrapper<Graph1, Graph2>& _gw, 
marci@915: 	     const Node& n) : 
marci@915: 	Node(n), gw(&_gw) { }
marci@915:       NodeIt& operator++() { 
marci@915: 	if (!this->backward) {
marci@915: 	  *(static_cast<Graph1Node*>(this))=
marci@915: 	    ++(typename Graph1::NodeIt(*gw->Parent1::graph, *this));
marci@915: 	  if (*static_cast<Graph1Node*>(this)==INVALID) {
marci@917: // 	    *static_cast<Node*>(this)=
marci@917: // 	      Node(typename Graph1::Node(INVALID), 
marci@917: // 		   typename Graph2::NodeIt(*gw->Parent2::graph), true);
marci@917: 	    *static_cast<Graph2Node*>(this)=
marci@917: 	      typename Graph2::NodeIt(*gw->Parent2::graph);
marci@917: 	    backward=true;
marci@915: 	  }
marci@915: 	} else {
marci@915: 	  *(static_cast<Graph2Node*>(this))=
marci@915: 	    ++(typename Graph2::NodeIt(*gw->Parent2::graph, *this));
marci@915: 	}
marci@915: 	return *this;
marci@915:       }
marci@915:     };
marci@915: 
marci@915:     int id(const Node& n) const { 
marci@915:       if (!n.backward) 
marci@915: 	return this->Parent1::graph->id(n);
marci@915:       else
marci@915: 	return this->Parent2::graph->id(n);
marci@915:     }
marci@915: 
marci@917:     template <typename Value> 
marci@917:     class NodeMap : public Parent1::template NodeMap<Value>, 
marci@917: 		    public Parent2::template NodeMap<Value> { 
marci@917:       typedef typename Parent1::template NodeMap<Value> ParentMap1;
marci@917:       typedef typename Parent2::template NodeMap<Value> ParentMap2;
marci@917:     public:
marci@917:       NodeMap(const MergeNodeGraphWrapper<Graph1, Graph2>& gw) : 
marci@917: 	ParentMap1(gw), 
marci@917: 	ParentMap2(gw) { }
marci@917:       NodeMap(const MergeNodeGraphWrapper<Graph1, Graph2>& gw, 
marci@917: 	      const Value& value)
marci@917: 	: ParentMap1(gw, value), 
marci@917: 	  ParentMap2(gw, value) { }
marci@917:       NodeMap(const NodeMap& copy)
marci@917: 	: ParentMap1(copy), 
marci@917: 	  ParentMap2(copy) { }
marci@917:       template <typename TT>
marci@917:       NodeMap(const NodeMap<TT>& copy)
marci@917: 	: ParentMap1(copy),
marci@917: 	  ParentMap2(copy) { }
marci@917:       NodeMap& operator=(const NodeMap& copy) {
marci@917: 	ParentMap1::operator=(copy);
marci@917: 	ParentMap2::operator=(copy);
marci@917: 	return *this;
marci@917:       }
marci@917:       template <typename TT>
marci@917:       NodeMap& operator=(const NodeMap<TT>& copy) {
marci@917: 	ParentMap1::operator=(copy);
marci@917: 	ParentMap2::operator=(copy);
marci@917: 	return *this;
marci@917:       }
marci@917:       Value operator[](const Node& n) const {
marci@917: 	if (!n.backward) 
marci@917: 	  return ParentMap1::operator[](n);
marci@917: 	else 
marci@917: 	  return ParentMap2::operator[](n);
marci@917:       }
marci@917:       void set(const Node& n, const Value& value) {
marci@917: 	if (!n.backward) 
marci@917: 	  ParentMap1::set(n, value);
marci@917: 	else 
marci@917: 	  ParentMap2::set(n, value);
marci@917:       }
marci@917:       using ParentMap1::operator[];
marci@917:       using ParentMap2::operator[];
marci@917:     };
marci@917:     
marci@915:   };
marci@915: 
alpar@921: } //namespace lemon
marci@915: 
alpar@921: #endif //LEMON_MERGE_NODE_GRAPH_WRAPPER_H