/* -*- C++ -*- * src/lemon/merge_node_graph_wrapper.h - Part of LEMON, 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 LEMON_MERGE_NODE_GRAPH_WRAPPER_H #define LEMON_MERGE_NODE_GRAPH_WRAPPER_H #include #include #include #include #include using std::cout; using std::endl; #include #include namespace lemon { template class P1 : public GraphWrapperBase<_Graph1> { }; template class P2 : public GraphWrapperBase<_Graph2> { }; /*! 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 class MergeNodeGraphWrapperBase : public P1<_Graph1>, public P2<_Graph2> { public: static void printNode() { std::cout << "node: generic" << std::endl; } typedef _Graph1 Graph1; typedef _Graph2 Graph2; typedef P1<_Graph1> Parent1; typedef P2<_Graph2> Parent2; typedef typename Parent1::Node Graph1Node; typedef typename Parent2::Node Graph2Node; protected: MergeNodeGraphWrapperBase() { } public: template class NodeMap; class Node : public Graph1Node, public Graph2Node { friend class MergeNodeGraphWrapperBase<_Graph1, _Graph2>; template 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(n1), Graph2Node(n2), backward(_backward) { } Node(Invalid i) : Graph1Node(i), Graph2Node(i), backward(true) { } bool operator==(const Node& v) const { if (backward) return (v.backward && static_cast(*this)==static_cast(v)); else return (!v.backward && static_cast(*this)==static_cast(v)); } bool operator!=(const Node& v) const { return !(*this==v); } }; //typedef void Edge; class Edge { }; void first(Node& i) const { Parent1::graph->first(*static_cast(&i)); i.backward=false; if (*static_cast(&i)==INVALID) { Parent2::graph->first(*static_cast(&i)); i.backward=true; } } void next(Node& i) const { if (!(i.backward)) { Parent1::graph->next(*static_cast(&i)); if (*static_cast(&i)==INVALID) { Parent2::graph->first(*static_cast(&i)); i.backward=true; } } else { Parent2::graph->next(*static_cast(&i)); } } int id(const Node& n) const { if (!n.backward) return this->Parent1::graph->id(n); else return this->Parent2::graph->id(n); } template 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[]; }; }; /*! 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 class MergeNodeGraphWrapperBase< _Graph1, _Graph2, typename boost::enable_if< boost::is_same >::type> : public P1<_Graph1>, public P2<_Graph2> { public: static void printNode() { std::cout << "node: same" << std::endl; } typedef _Graph1 Graph1; typedef _Graph2 Graph2; typedef P1<_Graph1> Parent1; typedef P2<_Graph2> Parent2; typedef typename Parent1::Node Graph1Node; typedef typename Parent2::Node Graph2Node; protected: MergeNodeGraphWrapperBase() { } public: template class NodeMap; class Node : public Graph1Node { friend class MergeNodeGraphWrapperBase<_Graph1, _Graph2>; template 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(*this)==static_cast(v)); } bool operator!=(const Node& v) const { return !(*this==v); } }; //typedef void Edge; class Edge { }; void first(Node& i) const { Parent1::graph->first(*static_cast(&i)); i.backward=false; if (*static_cast(&i)==INVALID) { Parent2::graph->first(*static_cast(&i)); i.backward=true; } } void next(Node& i) const { if (!(i.backward)) { Parent1::graph->next(*static_cast(&i)); if (*static_cast(&i)==INVALID) { Parent2::graph->first(*static_cast(&i)); i.backward=true; } } else { Parent2::graph->next(*static_cast(&i)); } } int id(const Node& n) const { if (!n.backward) return this->Parent1::graph->id(n); else return this->Parent2::graph->id(n); } template 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[]; }; }; /*! 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 class MergeNodeGraphWrapperBase< _Graph1, _Graph2, typename boost::enable_if< boost::is_base_and_derived >::type> : public P1<_Graph1>, public P2<_Graph2> { public : static void printNode() { std::cout << "node: 2nd is derived" << std::endl; } typedef _Graph1 Graph1; typedef _Graph2 Graph2; typedef P1<_Graph1> Parent1; typedef P2<_Graph2> Parent2; typedef typename Parent1::Node Graph1Node; typedef typename Parent2::Node Graph2Node; protected: MergeNodeGraphWrapperBase() { } public: class Node { }; class Edge { }; void first() const; void next() const; }; //not yet working template class MergeNodeGraphWrapperBase< _Graph1, _Graph2, typename boost::enable_if< boost::is_base_and_derived >::type> : public P1<_Graph1>, public P2<_Graph2> { public : static void printNode() { std::cout << "node: 1st is derived" << std::endl; } typedef _Graph1 Graph1; typedef _Graph2 Graph2; typedef P1<_Graph1> Parent1; typedef P2<_Graph2> Parent2; typedef typename Parent1::Node Graph1Node; typedef typename Parent2::Node Graph2Node; protected: MergeNodeGraphWrapperBase() { } public: class Node { }; class Edge { }; void first() const; void next() const; }; /*! 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 class MergeNodeGraphWrapper : public IterableGraphExtender > { public: typedef _Graph1 Graph1; typedef _Graph2 Graph2; typedef IterableGraphExtender< MergeNodeGraphWrapperBase<_Graph1, _Graph2> > Parent; protected: MergeNodeGraphWrapper() { } public: MergeNodeGraphWrapper(_Graph1& _graph1, _Graph2& _graph2) { Parent::Parent1::setGraph(_graph1); Parent::Parent2::setGraph(_graph2); } }; /*! 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 class MergeEdgeGraphWrapperBase : public MergeNodeGraphWrapperBase<_Graph1, _Graph2> { public: static void printEdge() { std::cout << "edge: generic" << 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 class EdgeMap; typedef typename Parent::Node Node; class Edge : public Graph1Edge, public Graph2Edge { friend class MergeEdgeGraphWrapperBase<_Graph1, _Graph2>; template 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(*this)==static_cast(v)); else return (!v.backward && static_cast(*this)==static_cast(v)); } bool operator!=(const Edge& v) const { return !(*this==v); } }; using Parent::first; void first(Edge& i) const { Parent1::graph->first(*static_cast(&i)); i.backward=false; if (*static_cast(&i)==INVALID) { Parent2::graph->first(*static_cast(&i)); i.backward=true; } } void firstIn(Edge& i, const Node& n) const { Parent1::graph->firstIn(*static_cast(&i), n); i.backward=false; if (*static_cast(&i)==INVALID) { Parent2::graph->firstIn(*static_cast(&i), n); i.backward=true; } } void firstOut(Edge& i, const Node& n) const { Parent1::graph->firstOut(*static_cast(&i), n); i.backward=false; if (*static_cast(&i)==INVALID) { Parent2::graph->firstOut(*static_cast(&i), n); i.backward=true; } } using Parent::next; void next(Edge& i) const { if (!(i.backward)) { Parent1::graph->next(*static_cast(&i)); if (*static_cast(&i)==INVALID) { Parent2::graph->first(*static_cast(&i)); i.backward=true; } } else { Parent2::graph->next(*static_cast(&i)); } } void nextIn(Edge& i) const { if (!(i.backward)) { Parent1::graph->nextIn(*static_cast(&i)); if (*static_cast(&i)==INVALID) { Parent2::graph->first(*static_cast(&i)); i.backward=true; } } else { Parent2::graph->nextIn(*static_cast(&i)); } } void nextOut(Edge& i) const { if (!(i.backward)) { Parent1::graph->nextOut(*static_cast(&i)); if (*static_cast(&i)==INVALID) { Parent2::graph->first(*static_cast(&i)); i.backward=true; } } else { Parent2::graph->nextOut(*static_cast(&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 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 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 class MergeEdgeGraphWrapperBase< _Graph1, _Graph2, typename boost::enable_if< boost::is_same >::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 class EdgeMap; typedef typename Parent::Node Node; class Edge : public Graph1Edge { friend class MergeEdgeGraphWrapperBase<_Graph1, _Graph2>; template 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(*this)==static_cast(v)); } bool operator!=(const Edge& v) const { return !(*this==v); } }; using Parent::first; void first(Edge& i) const { Parent1::graph->first(*static_cast(&i)); i.backward=false; if (*static_cast(&i)==INVALID) { Parent2::graph->first(*static_cast(&i)); i.backward=true; } } void firstIn(Edge& i, const Node& n) const { Parent1::graph->firstIn(*static_cast(&i), n); i.backward=false; if (*static_cast(&i)==INVALID) { Parent2::graph->firstIn(*static_cast(&i), n); i.backward=true; } } void firstOut(Edge& i, const Node& n) const { Parent1::graph->firstOut(*static_cast(&i), n); i.backward=false; if (*static_cast(&i)==INVALID) { Parent2::graph->firstOut(*static_cast(&i), n); i.backward=true; } } using Parent::next; void next(Edge& i) const { if (!(i.backward)) { Parent1::graph->next(*static_cast(&i)); if (*static_cast(&i)==INVALID) { Parent2::graph->first(*static_cast(&i)); i.backward=true; } } else { Parent2::graph->next(*static_cast(&i)); } } void nextIn(Edge& i) const { if (!(i.backward)) { Parent1::graph->nextIn(*static_cast(&i)); if (*static_cast(&i)==INVALID) { Parent2::graph->first(*static_cast(&i)); i.backward=true; } } else { Parent2::graph->nextIn(*static_cast(&i)); } } void nextOut(Edge& i) const { if (!(i.backward)) { Parent1::graph->nextOut(*static_cast(&i)); if (*static_cast(&i)==INVALID) { Parent2::graph->first(*static_cast(&i)); i.backward=true; } } else { Parent2::graph->nextOut(*static_cast(&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 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 class MergeEdgeGraphWrapper : public IterableGraphExtender > { public: typedef _Graph1 Graph1; typedef _Graph2 Graph2; typedef IterableGraphExtender< MergeEdgeGraphWrapperBase<_Graph1, _Graph2> > Parent; protected: MergeEdgeGraphWrapper() { } public: MergeEdgeGraphWrapper(_Graph1& _graph1, _Graph2& _graph2) { Parent::Parent1::setGraph(_graph1); Parent::Parent2::setGraph(_graph2); } }; /*! 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 class NewEdgeSetGraphWrapperBase : public GraphWrapperBase<_Graph> { public: typedef GraphWrapperBase<_Graph> Parent; typedef _Graph Graph; typedef _EdgeSetGraph EdgeSetGraph; typedef typename _Graph::Node Node; typedef typename _EdgeSetGraph::Node ENode; protected: EdgeSetGraph* edge_set_graph; typename Graph::NodeMap* e_node; typename EdgeSetGraph::NodeMap* n_node; void setEdgeSetGraph(EdgeSetGraph& _edge_set_graph) { edge_set_graph=&_edge_set_graph; } /// For each node of \c Graph, this gives a node of \c EdgeSetGraph . void setNodeMap(typename EdgeSetGraph::NodeMap& _n_node) { n_node=&_n_node; } /// For each node of \c EdgeSetGraph, this gives a node of \c Graph . void setENodeMap(typename Graph::NodeMap& _e_node) { e_node=&_e_node; } public: class Edge : public EdgeSetGraph::Edge { typedef typename EdgeSetGraph::Edge Parent; public: Edge() { } Edge(const Parent& e) : Parent(e) { } Edge(Invalid i) : Parent(i) { } }; using Parent::first; void first(Edge &e) const { edge_set_graph->first(e); } void firstOut(Edge& e, const Node& n) const { // cout << e_node << endl; // cout << n_node << endl; edge_set_graph->firstOut(e, (*e_node)[n]); } void firstIn(Edge& e, const Node& n) const { edge_set_graph->firstIn(e, (*e_node)[n]); } using Parent::next; void next(Edge &e) const { edge_set_graph->next(e); } void nextOut(Edge& e) const { edge_set_graph->nextOut(e); } void nextIn(Edge& e) const { edge_set_graph->nextIn(e); } Node source(const Edge& e) const { return (*n_node)[edge_set_graph->source(e)]; } Node target(const Edge& e) const { return (*n_node)[edge_set_graph->target(e)]; } int edgeNum() const { return edge_set_graph->edgeNum(); } Edge addEdge(const Node& u, const Node& v) { return edge_set_graph->addEdge((*e_node)[u], (*e_node)[v]); } using Parent::erase; void erase(const Edge& i) const { edge_set_graph->erase(i); } void clear() const { Parent::clear(); edge_set_graph->clear(); } bool forward(const Edge& e) const { return edge_set_graph->forward(e); } bool backward(const Edge& e) const { return edge_set_graph->backward(e); } 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); } template class EdgeMap : public EdgeSetGraph::EdgeMap<_Value> { public: typedef typename EdgeSetGraph::EdgeMap<_Value> Parent; typedef _Value Value; typedef Edge Key; EdgeMap(const NewEdgeSetGraphWrapperBase& gw) : Parent(*(gw.edge_set_graph)) { } EdgeMap(const NewEdgeSetGraphWrapperBase& gw, const _Value& _value) : Parent(*(gw.edge_set_graph), _value) { } }; }; /*! 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 class NewEdgeSetGraphWrapper : public IterableGraphExtender< NewEdgeSetGraphWrapperBase<_Graph, _EdgeSetGraph> > { public: typedef _Graph Graph; typedef _EdgeSetGraph EdgeSetGraph; typedef IterableGraphExtender< NewEdgeSetGraphWrapper<_Graph, _EdgeSetGraph> > Parent; protected: NewEdgeSetGraphWrapper() { } public: NewEdgeSetGraphWrapper(_Graph& _graph, _EdgeSetGraph& _edge_set_graph, typename _Graph:: NodeMap& _e_node, typename _EdgeSetGraph:: NodeMap& _n_node) { setGraph(_graph); setEdgeSetGraph(_edge_set_graph); setNodeMap(_n_node); setENodeMap(_e_node); } }; /*! 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 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 class EdgeMap; typedef typename Parent1::Node Node; class Edge : public Graph1Edge, public Graph2Edge { friend class AugmentingGraphWrapperBase<_Graph1, _Graph2>; template 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(*this)==static_cast(v)); else return (!v.backward && static_cast(*this)==static_cast(v)); } bool operator!=(const Edge& v) const { return !(*this==v); } }; using Parent1::first; void first(Edge& i) const { Parent1::graph->first(*static_cast(&i)); i.backward=false; if (*static_cast(&i)==INVALID) { graph2->first(*static_cast(&i)); i.backward=true; } } void firstIn(Edge& i, const Node& n) const { Parent1::graph->firstIn(*static_cast(&i), n); i.backward=false; if (*static_cast(&i)==INVALID) { graph2->firstIn(*static_cast(&i), n); i.backward=true; } } void firstOut(Edge& i, const Node& n) const { Parent1::graph->firstOut(*static_cast(&i), n); i.backward=false; if (*static_cast(&i)==INVALID) { graph2->firstOut(*static_cast(&i), n); i.backward=true; } } using Parent1::next; void next(Edge& i) const { if (!(i.backward)) { Parent1::graph->next(*static_cast(&i)); if (*static_cast(&i)==INVALID) { graph2->first(*static_cast(&i)); i.backward=true; } } else { graph2->next(*static_cast(&i)); } } void nextIn(Edge& i) const { if (!(i.backward)) { Parent1::graph->nextIn(*static_cast(&i)); if (*static_cast(&i)==INVALID) { graph2->first(*static_cast(&i)); i.backward=true; } } else { graph2->nextIn(*static_cast(&i)); } } void nextOut(Edge& i) const { if (!(i.backward)) { Parent1::graph->nextOut(*static_cast(&i)); if (*static_cast(&i)==INVALID) { graph2->first(*static_cast(&i)); i.backward=true; } } else { graph2->nextOut(*static_cast(&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 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 class AugmentingGraphWrapper : public IterableGraphExtender > { public: typedef IterableGraphExtender > 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