2 * src/lemon/merge_node_graph_wrapper.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Combinatorial Optimization Research Group, EGRES).
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
17 #ifndef LEMON_MERGE_NODE_GRAPH_WRAPPER_H
18 #define LEMON_MERGE_NODE_GRAPH_WRAPPER_H
20 #include <lemon/invalid.h>
21 #include <lemon/maps.h>
22 #include <lemon/map_defines.h>
23 #include <lemon/graph_wrapper.h>
29 #include <boost/type_traits.hpp>
30 #include <boost/utility/enable_if.hpp>
34 template <class _Graph1>
35 class P1 : public GraphWrapperBase<_Graph1> {
38 template <class _Graph2>
39 class P2 : public GraphWrapperBase<_Graph2> {
43 template <typename _Graph1, typename _Graph2, typename Enable=void>
44 class MergeNodeGraphWrapperBaseBase :
45 public P1<_Graph1>, public P2<_Graph2> {
47 static void printNode() { std::cout << "node: generic" << std::endl; }
48 typedef _Graph1 Graph1;
49 typedef _Graph2 Graph2;
50 typedef P1<_Graph1> Parent1;
51 typedef P2<_Graph2> Parent2;
52 typedef typename Parent1::Node Graph1Node;
53 typedef typename Parent2::Node Graph2Node;
55 MergeNodeGraphWrapperBaseBase() { }
58 class Node : public Graph1Node, public Graph2Node {
59 friend class MergeNodeGraphWrapperBaseBase<_Graph1, _Graph2>;
61 bool backward; //true, iff backward
64 /// \todo =false is needed, or causes problems?
65 /// If \c _backward is false, then we get an edge corresponding to the
66 /// original one, otherwise its oppositely directed pair is obtained.
67 Node(const Graph1Node& n1,
68 const Graph2Node& n2, bool _backward) :
69 Graph1Node(n1), Graph2Node(n2), backward(_backward) { }
70 Node(Invalid i) : Graph1Node(i), Graph2Node(i), backward(true) { }
71 bool operator==(const Node& v) const {
74 static_cast<Graph2Node>(*this)==static_cast<Graph2Node>(v));
76 return (!v.backward &&
77 static_cast<Graph1Node>(*this)==static_cast<Graph1Node>(v));
79 bool operator!=(const Node& v) const {
84 static bool forward(const Node& n) { return !n.backward; }
85 static bool backward(const Node& n) { return n.backward; }
86 static void setForward(Node& n) { n.backward=false; }
87 static void setBackward(Node& n) { n.backward=true; }
91 template <typename _Graph1, typename _Graph2>
92 class MergeNodeGraphWrapperBaseBase<
93 _Graph1, _Graph2, typename boost::enable_if<
94 boost::is_same<typename _Graph1::Node, typename _Graph2::Node> >::type> :
95 public P1<_Graph1>, public P2<_Graph2> {
97 static void printNode() { std::cout << "node: same" << std::endl; }
98 typedef _Graph1 Graph1;
99 typedef _Graph2 Graph2;
100 typedef P1<_Graph1> Parent1;
101 typedef P2<_Graph2> Parent2;
102 typedef typename Parent1::Node Graph1Node;
103 typedef typename Parent2::Node Graph2Node;
105 MergeNodeGraphWrapperBaseBase() { }
108 class Node : public Graph1Node {
109 friend class MergeNodeGraphWrapperBaseBase<_Graph1, _Graph2>;
111 bool backward; //true, iff backward
114 /// \todo =false is needed, or causes problems?
115 /// If \c _backward is false, then we get an edge corresponding to the
116 /// original one, otherwise its oppositely directed pair is obtained.
117 Node(const Graph1Node& n1,
118 const Graph2Node& n2, bool _backward) :
119 Graph1Node(!_backward ? n1 : n2), backward(_backward) { }
120 Node(Invalid i) : Graph1Node(i), backward(true) { }
121 bool operator==(const Node& v) const {
122 return (backward==v.backward &&
123 static_cast<Graph1Node>(*this)==static_cast<Graph1Node>(v));
125 bool operator!=(const Node& v) const {
130 static bool forward(const Node& n) { return !n.backward; }
131 static bool backward(const Node& n) { return n.backward; }
132 static void setForward(Node& n) { n.backward=false; }
133 static void setBackward(Node& n) { n.backward=true; }
137 template <typename _Graph1, typename _Graph2>
138 class MergeNodeGraphWrapperBaseBase<
139 _Graph1, _Graph2, typename boost::enable_if<
140 boost::is_base_and_derived<typename _Graph1::Node, typename _Graph2::Node> >::type> :
141 public P1<_Graph1>, public P2<_Graph2> {
143 static void printNode() { std::cout << "node: 2nd is derived" << std::endl; }
144 typedef _Graph1 Graph1;
145 typedef _Graph2 Graph2;
146 typedef P1<_Graph1> Parent1;
147 typedef P2<_Graph2> Parent2;
148 typedef typename Parent1::Node Graph1Node;
149 typedef typename Parent2::Node Graph2Node;
151 MergeNodeGraphWrapperBaseBase() { }
154 class Node : public Graph2Node {
155 friend class MergeNodeGraphWrapperBaseBase<_Graph1, _Graph2>;
157 bool backward; //true, iff backward
160 /// \todo =false is needed, or causes problems?
161 /// If \c _backward is false, then we get an edge corresponding to the
162 /// original one, otherwise its oppositely directed pair is obtained.
163 Node(const Graph1Node& n1,
164 const Graph2Node& n2, bool _backward) :
165 Graph2Node(n2), backward(_backward) {
166 if (!backward) *this=n1;
168 Node(Invalid i) : Graph2Node(i), backward(true) { }
169 bool operator==(const Node& v) const {
171 return (v.backward &&
172 static_cast<Graph2Node>(*this)==static_cast<Graph2Node>(v));
174 return (!v.backward &&
175 static_cast<Graph1Node>(*this)==static_cast<Graph1Node>(v));
177 bool operator!=(const Node& v) const {
182 static bool forward(const Node& n) { return !n.backward; }
183 static bool backward(const Node& n) { return n.backward; }
184 static void setForward(Node& n) { n.backward=false; }
185 static void setBackward(Node& n) { n.backward=true; }
189 template <typename _Graph1, typename _Graph2>
190 class MergeNodeGraphWrapperBaseBase<
191 _Graph1, _Graph2, typename boost::enable_if<
192 boost::is_base_and_derived<typename _Graph2::Node, typename _Graph1::Node> >::type> :
193 public P1<_Graph1>, public P2<_Graph2> {
195 static void printNode() { std::cout << "node: 1st is derived" << std::endl; }
196 typedef _Graph1 Graph1;
197 typedef _Graph2 Graph2;
198 typedef P1<_Graph1> Parent1;
199 typedef P2<_Graph2> Parent2;
200 typedef typename Parent1::Node Graph1Node;
201 typedef typename Parent2::Node Graph2Node;
203 MergeNodeGraphWrapperBaseBase() { }
206 class Node : public Graph1Node {
207 friend class MergeNodeGraphWrapperBaseBase<_Graph1, _Graph2>;
209 bool backward; //true, iff backward
212 /// \todo =false is needed, or causes problems?
213 /// If \c _backward is false, then we get an edge corresponding to the
214 /// original one, otherwise its oppositely directed pair is obtained.
215 Node(const Graph1Node& n1,
216 const Graph2Node& n2, bool _backward) :
217 Graph1Node(n1), backward(_backward) {
218 if (backward) *this=n2;
220 Node(Invalid i) : Graph1Node(i), backward(true) { }
221 bool operator==(const Node& v) const {
223 return (v.backward &&
224 static_cast<Graph2Node>(*this)==static_cast<Graph2Node>(v));
226 return (!v.backward &&
227 static_cast<Graph1Node>(*this)==static_cast<Graph1Node>(v));
229 bool operator!=(const Node& v) const {
234 static bool forward(const Node& n) { return !n.backward; }
235 static bool backward(const Node& n) { return n.backward; }
236 static void setForward(Node& n) { n.backward=false; }
237 static void setBackward(Node& n) { n.backward=true; }
241 template <typename _Graph1, typename _Graph2>
242 class MergeNodeGraphWrapperBase :
243 public MergeNodeGraphWrapperBaseBase<_Graph1, _Graph2> {
245 typedef MergeNodeGraphWrapperBaseBase<_Graph1, _Graph2> Parent;
246 typedef _Graph1 Graph1;
247 typedef _Graph2 Graph2;
248 typedef P1<_Graph1> Parent1;
249 typedef P2<_Graph2> Parent2;
250 typedef typename Parent1::Node Graph1Node;
251 typedef typename Parent2::Node Graph2Node;
253 typedef typename Parent::Node Node;
256 void first(Node& i) const {
257 Parent1::graph->first(*static_cast<Graph1Node*>(&i));
259 if (*static_cast<Graph1Node*>(&i)==INVALID) {
260 Parent2::graph->first(*static_cast<Graph2Node*>(&i));
261 this->setBackward(i);
264 void next(Node& i) const {
265 if (this->forward(i)) {
266 Parent1::graph->next(*static_cast<Graph1Node*>(&i));
267 if (*static_cast<Graph1Node*>(&i)==INVALID) {
268 Parent2::graph->first(*static_cast<Graph2Node*>(&i));
269 this->setBackward(i);
272 Parent2::graph->next(*static_cast<Graph2Node*>(&i));
276 int id(const Node& n) const {
277 if (this->forward(n))
278 return this->Parent1::graph->id(n);
280 return this->Parent2::graph->id(n);
283 template <typename _Value>
286 typedef typename _Graph1::template NodeMap<_Value> ParentMap1;
287 typedef typename _Graph2::template NodeMap<_Value> ParentMap2;
288 ParentMap1 forward_map;
289 ParentMap2 backward_map;
291 typedef _Value Value;
293 NodeMap(const MergeNodeGraphWrapperBase<_Graph1, _Graph2>& gw) :
294 forward_map(*(gw.Parent1::graph)),
295 backward_map(*(gw.Parent2::graph)) { }
296 NodeMap(const MergeNodeGraphWrapperBase<_Graph1, _Graph2>& gw,
297 const _Value& value) :
298 forward_map(*(gw.Parent1::graph), value),
299 backward_map(*(gw.Parent2::graph), value) { }
300 _Value operator[](const Node& n) const {
301 if (Parent::forward(n))
302 return forward_map[n];
304 return backward_map[n];
306 void set(const Node& n, const _Value& value) {
307 if (Parent::forward(n))
308 forward_map.set(n, value);
310 backward_map.set(n, value);
312 // using ParentMap1::operator[];
313 // using ParentMap2::operator[];
319 /*! A graph wrapper class
320 for merging the node-set of two node-disjoint graphs
321 into the node-set of one graph.
322 Different implementations are according to the relation of
323 _Graph1::Node and _Graph2::Node.
324 If _Graph1::Node and _Graph2::Node are unrelated, then
325 MergeNodeGraphWrapper<_Graph1, _Graph2>::Node
326 is derived from both.
327 If _Graph1::Node and _Graph2::Node are the same type, then
328 MergeNodeGraphWrapper<_Graph1, _Graph2>::Node
329 is derived from _Graph1::Node.
330 If one of _Graph1::Node and _Graph2::Node
331 is derived from the other one, then
332 MergeNodeGraphWrapper<_Graph1, _Graph2>::Node
333 is derived from the derived type.
335 StaticGraph concept as it has no edge-set which
336 works together with the node-set.
338 template <typename _Graph1, typename _Graph2>
339 class MergeNodeGraphWrapper : public
340 IterableGraphExtender<MergeNodeGraphWrapperBase<_Graph1, _Graph2> > {
342 typedef _Graph1 Graph1;
343 typedef _Graph2 Graph2;
344 typedef IterableGraphExtender<
345 MergeNodeGraphWrapperBase<_Graph1, _Graph2> > Parent;
347 MergeNodeGraphWrapper() { }
349 MergeNodeGraphWrapper(_Graph1& _graph1, _Graph2& _graph2) {
350 Parent::Parent1::setGraph(_graph1);
351 Parent::Parent2::setGraph(_graph2);
356 /*! A grah wrapper base class
357 for merging the node-sets and edge-sets of
358 two node-disjoint graphs
360 Generic implementation for unrelated _Graph1::Edge and _Graph2::Edge.
362 template <typename _Graph1, typename _Graph2, typename Enable=void>
363 class MergeEdgeGraphWrapperBase :
364 public MergeNodeGraphWrapperBase<_Graph1, _Graph2> {
366 static void printEdge() { std::cout << "edge: generic" << std::endl; }
367 typedef _Graph1 Graph1;
368 typedef _Graph2 Graph2;
369 typedef MergeNodeGraphWrapperBase<_Graph1, _Graph2> Parent;
370 typedef typename Parent::Parent1 Parent1;
371 typedef typename Parent::Parent2 Parent2;
372 // typedef P1<_Graph1> Parent1;
373 // typedef P2<_Graph2> Parent2;
374 typedef typename Parent1::Edge Graph1Edge;
375 typedef typename Parent2::Edge Graph2Edge;
377 MergeEdgeGraphWrapperBase() { }
379 template <typename _Value> class EdgeMap;
381 typedef typename Parent::Node Node;
383 class Edge : public Graph1Edge, public Graph2Edge {
384 friend class MergeEdgeGraphWrapperBase<_Graph1, _Graph2>;
385 template <typename _Value> friend class EdgeMap;
387 bool backward; //true, iff backward
390 /// \todo =false is needed, or causes problems?
391 /// If \c _backward is false, then we get an edge corresponding to the
392 /// original one, otherwise its oppositely directed pair is obtained.
393 Edge(const Graph1Edge& n1,
394 const Graph2Edge& n2, bool _backward) :
395 Graph1Edge(n1), Graph2Edge(n2), backward(_backward) { }
396 Edge(Invalid i) : Graph1Edge(i), Graph2Edge(i), backward(true) { }
397 bool operator==(const Edge& v) const {
399 return (v.backward &&
400 static_cast<Graph2Edge>(*this)==static_cast<Graph2Edge>(v));
402 return (!v.backward &&
403 static_cast<Graph1Edge>(*this)==static_cast<Graph1Edge>(v));
405 bool operator!=(const Edge& v) const {
410 using Parent::forward;
411 using Parent::backward;
412 bool forward(const Edge& e) const { return !e.backward; }
413 bool backward(const Edge& e) const { return e.backward; }
416 void first(Edge& i) const {
417 Parent1::graph->first(*static_cast<Graph1Edge*>(&i));
419 if (*static_cast<Graph1Edge*>(&i)==INVALID) {
420 Parent2::graph->first(*static_cast<Graph2Edge*>(&i));
424 void firstIn(Edge& i, const Node& n) const {
426 Parent1::graph->firstIn(*static_cast<Graph1Edge*>(&i), n);
427 if (*static_cast<Graph1Edge*>(&i)==INVALID)
432 Parent2::graph->firstIn(*static_cast<Graph2Edge*>(&i), n);
436 void firstOut(Edge& i, const Node& n) const {
438 Parent1::graph->firstOut(*static_cast<Graph1Edge*>(&i), n);
439 if (*static_cast<Graph1Edge*>(&i)==INVALID)
444 Parent2::graph->firstOut(*static_cast<Graph2Edge*>(&i), n);
450 void next(Edge& i) const {
452 Parent1::graph->next(*static_cast<Graph1Edge*>(&i));
453 if (*static_cast<Graph1Edge*>(&i)==INVALID) {
454 Parent2::graph->first(*static_cast<Graph2Edge*>(&i));
458 Parent2::graph->next(*static_cast<Graph2Edge*>(&i));
461 void nextIn(Edge& i) const {
463 Parent1::graph->nextIn(*static_cast<Graph1Edge*>(&i));
464 if (*static_cast<Graph1Edge*>(&i)==INVALID) i=INVALID;
466 Parent2::graph->nextIn(*static_cast<Graph2Edge*>(&i));
469 void nextOut(Edge& i) const {
471 Parent1::graph->nextOut(*static_cast<Graph1Edge*>(&i));
472 if (*static_cast<Graph1Edge*>(&i)==INVALID) i=INVALID;
474 Parent2::graph->nextOut(*static_cast<Graph2Edge*>(&i));
478 Node source(const Edge& i) const {
481 Node(Parent1::graph->source(i), INVALID, false);
484 Node(INVALID, Parent2::graph->source(i), true);
488 Node target(const Edge& i) const {
491 Node(Parent1::graph->target(i), INVALID, false);
494 Node(INVALID, Parent2::graph->target(i), true);
499 int id(const Edge& n) const {
501 return this->Parent1::graph->id(n);
503 return this->Parent2::graph->id(n);
506 template <typename _Value>
509 typedef typename Parent::Graph1::template EdgeMap<_Value> ParentMap1;
510 typedef typename Parent::Graph2::template EdgeMap<_Value> ParentMap2;
511 ParentMap1 forward_map;
512 ParentMap2 backward_map;
514 typedef _Value Value;
516 EdgeMap(const MergeEdgeGraphWrapperBase<_Graph1, _Graph2>& gw) :
517 forward_map(*(gw.Parent1::graph)),
518 backward_map(*(gw.Parent2::graph)) { }
519 EdgeMap(const MergeEdgeGraphWrapperBase<_Graph1, _Graph2>& gw,
520 const _Value& value) :
521 forward_map(*(gw.Parent1::graph), value),
522 backward_map(*(gw.Parent2::graph), value) { }
523 _Value operator[](const Edge& n) const {
525 return forward_map[n];
527 return backward_map[n];
529 void set(const Edge& n, const _Value& value) {
531 forward_map.set(n, value);
533 backward_map.set(n, value);
535 // using ParentMap1::operator[];
536 // using ParentMap2::operator[];
542 /*! A graph wrapper base class
543 for merging the node-sets and edge-sets of
544 two node-disjoint graphs
546 Specialization for the case when _Graph1::Edge and _Graph2::Edge
549 template <typename _Graph1, typename _Graph2>
550 class MergeEdgeGraphWrapperBase<
551 _Graph1, _Graph2, typename boost::enable_if<
552 boost::is_same<typename _Graph1::Edge, typename _Graph2::Edge> >::type> :
553 public MergeNodeGraphWrapperBase<_Graph1, _Graph2> {
555 static void printEdge() { std::cout << "edge: same" << std::endl; }
556 typedef _Graph1 Graph1;
557 typedef _Graph2 Graph2;
558 typedef MergeNodeGraphWrapperBase<_Graph1, _Graph2> Parent;
559 typedef typename Parent::Parent1 Parent1;
560 typedef typename Parent::Parent2 Parent2;
561 // typedef P1<_Graph1> Parent1;
562 // typedef P2<_Graph2> Parent2;
563 typedef typename Parent1::Edge Graph1Edge;
564 typedef typename Parent2::Edge Graph2Edge;
566 MergeEdgeGraphWrapperBase() { }
568 template <typename _Value> class EdgeMap;
570 typedef typename Parent::Node Node;
572 class Edge : public Graph1Edge {
573 friend class MergeEdgeGraphWrapperBase<_Graph1, _Graph2>;
574 template <typename _Value> friend class EdgeMap;
576 bool backward; //true, iff backward
579 /// \todo =false is needed, or causes problems?
580 /// If \c _backward is false, then we get an edge corresponding to the
581 /// original one, otherwise its oppositely directed pair is obtained.
582 Edge(const Graph1Edge& n1,
583 const Graph2Edge& n2, bool _backward) :
584 Graph1Edge(!_backward ? n1 : n2), backward(_backward) { }
585 Edge(Invalid i) : Graph1Edge(i), backward(true) { }
586 bool operator==(const Edge& v) const {
587 return (backward==v.backward &&
588 static_cast<Graph1Edge>(*this)==static_cast<Graph1Edge>(v));
590 bool operator!=(const Edge& v) const {
595 using Parent::forward;
596 using Parent::backward;
597 bool forward(const Edge& e) const { return !e.backward; }
598 bool backward(const Edge& e) const { return e.backward; }
601 void first(Edge& i) const {
602 Parent1::graph->first(*static_cast<Graph1Edge*>(&i));
604 if (*static_cast<Graph1Edge*>(&i)==INVALID) {
605 Parent2::graph->first(*static_cast<Graph1Edge*>(&i));
609 void firstIn(Edge& i, const Node& n) const {
611 Parent1::graph->firstIn(*static_cast<Graph1Edge*>(&i), n);
612 if (*static_cast<Graph1Edge*>(&i)==INVALID)
617 Parent2::graph->firstIn(*static_cast<Graph1Edge*>(&i), n);
621 void firstOut(Edge& i, const Node& n) const {
623 Parent1::graph->firstOut(*static_cast<Graph1Edge*>(&i), n);
624 if (*static_cast<Graph1Edge*>(&i)==INVALID)
629 Parent2::graph->firstOut(*static_cast<Graph1Edge*>(&i), n);
635 void next(Edge& i) const {
637 Parent1::graph->next(*static_cast<Graph1Edge*>(&i));
638 if (*static_cast<Graph1Edge*>(&i)==INVALID) {
639 Parent2::graph->first(*static_cast<Graph1Edge*>(&i));
643 Parent2::graph->next(*static_cast<Graph1Edge*>(&i));
646 void nextIn(Edge& i) const {
648 Parent1::graph->nextIn(*static_cast<Graph1Edge*>(&i));
649 if (*static_cast<Graph1Edge*>(&i)==INVALID) i=INVALID;
651 Parent2::graph->nextIn(*static_cast<Graph1Edge*>(&i));
654 void nextOut(Edge& i) const {
656 Parent1::graph->nextOut(*static_cast<Graph1Edge*>(&i));
657 if (*static_cast<Graph1Edge*>(&i)==INVALID) i=INVALID;
659 Parent2::graph->nextOut(*static_cast<Graph1Edge*>(&i));
663 Node source(const Edge& i) const {
666 Node(Parent1::graph->source(i), INVALID, false);
669 Node(INVALID, Parent2::graph->source(i), true);
673 Node target(const Edge& i) const {
676 Node(Parent1::graph->target(i), INVALID, false);
679 Node(INVALID, Parent2::graph->target(i), true);
684 int id(const Edge& n) const {
686 return this->Parent1::graph->id(n);
688 return this->Parent2::graph->id(n);
691 template <typename _Value>
694 typedef typename Parent::Graph1::template EdgeMap<_Value> ParentMap1;
695 typedef typename Parent::Graph2::template EdgeMap<_Value> ParentMap2;
696 ParentMap1 forward_map;
697 ParentMap2 backward_map;
699 typedef _Value Value;
701 EdgeMap(const MergeEdgeGraphWrapperBase<_Graph1, _Graph2>& gw) :
702 forward_map(*(gw.Parent1::graph)),
703 backward_map(*(gw.Parent2::graph)) { }
704 EdgeMap(const MergeEdgeGraphWrapperBase<_Graph1, _Graph2>& gw,
705 const _Value& value) :
706 forward_map(*(gw.Parent1::graph), value),
707 backward_map(*(gw.Parent2::graph), value) { }
708 _Value operator[](const Edge& n) const {
710 return forward_map[n];
712 return backward_map[n];
714 void set(const Edge& n, const _Value& value) {
716 forward_map.set(n, value);
718 backward_map.set(n, value);
720 // using ParentMap1::operator[];
721 // using ParentMap2::operator[];
727 /*! A grah wrapper base class
728 for merging the node-sets and edge-sets of
729 two node-disjoint graphs
731 Specialized implementation for the case
732 when _Graph1::Edge is a base class and _Graph2::Edge
735 template <typename _Graph1, typename _Graph2>
736 class MergeEdgeGraphWrapperBase<
737 _Graph1, _Graph2, typename boost::enable_if<
738 boost::is_base_and_derived<typename _Graph1::Edge, typename _Graph2::Edge> >::type> :
739 public MergeNodeGraphWrapperBase<_Graph1, _Graph2> {
741 static void printEdge() { std::cout << "edge: 2nd is derived" << std::endl; }
742 typedef _Graph1 Graph1;
743 typedef _Graph2 Graph2;
744 typedef MergeNodeGraphWrapperBase<_Graph1, _Graph2> Parent;
745 typedef typename Parent::Parent1 Parent1;
746 typedef typename Parent::Parent2 Parent2;
747 // typedef P1<_Graph1> Parent1;
748 // typedef P2<_Graph2> Parent2;
749 typedef typename Parent1::Edge Graph1Edge;
750 typedef typename Parent2::Edge Graph2Edge;
752 MergeEdgeGraphWrapperBase() { }
754 template <typename _Value> class EdgeMap;
756 typedef typename Parent::Node Node;
758 class Edge : public Graph2Edge {
759 friend class MergeEdgeGraphWrapperBase<_Graph1, _Graph2>;
760 template <typename _Value> friend class EdgeMap;
762 bool backward; //true, iff backward
765 /// \todo =false is needed, or causes problems?
766 /// If \c _backward is false, then we get an edge corresponding to the
767 /// original one, otherwise its oppositely directed pair is obtained.
768 Edge(const Graph1Edge& n1,
769 const Graph2Edge& n2, bool _backward) :
770 Graph2Edge(n2), backward(_backward) {
771 if (!backward) *this=n1;
773 Edge(Invalid i) : Graph2Edge(i), backward(true) { }
774 bool operator==(const Edge& v) const {
776 return (v.backward &&
777 static_cast<Graph2Edge>(*this)==static_cast<Graph2Edge>(v));
779 return (!v.backward &&
780 static_cast<Graph1Edge>(*this)==static_cast<Graph1Edge>(v));
782 bool operator!=(const Edge& v) const {
787 using Parent::forward;
788 using Parent::backward;
789 bool forward(const Edge& e) const { return !e.backward; }
790 bool backward(const Edge& e) const { return e.backward; }
793 void first(Edge& i) const {
794 Parent1::graph->first(*static_cast<Graph1Edge*>(&i));
796 if (*static_cast<Graph1Edge*>(&i)==INVALID) {
797 Parent2::graph->first(*static_cast<Graph2Edge*>(&i));
801 void firstIn(Edge& i, const Node& n) const {
803 Parent1::graph->firstIn(*static_cast<Graph1Edge*>(&i), n);
804 if (*static_cast<Graph1Edge*>(&i)==INVALID)
809 Parent2::graph->firstIn(*static_cast<Graph2Edge*>(&i), n);
813 void firstOut(Edge& i, const Node& n) const {
815 Parent1::graph->firstOut(*static_cast<Graph1Edge*>(&i), n);
816 if (*static_cast<Graph1Edge*>(&i)==INVALID)
821 Parent2::graph->firstOut(*static_cast<Graph2Edge*>(&i), n);
827 void next(Edge& i) const {
829 Parent1::graph->next(*static_cast<Graph1Edge*>(&i));
830 if (*static_cast<Graph1Edge*>(&i)==INVALID) {
831 Parent2::graph->first(*static_cast<Graph2Edge*>(&i));
835 Parent2::graph->next(*static_cast<Graph2Edge*>(&i));
838 void nextIn(Edge& i) const {
840 Parent1::graph->nextIn(*static_cast<Graph1Edge*>(&i));
841 if (*static_cast<Graph1Edge*>(&i)==INVALID) i=INVALID;
843 Parent2::graph->nextIn(*static_cast<Graph2Edge*>(&i));
846 void nextOut(Edge& i) const {
848 Parent1::graph->nextOut(*static_cast<Graph1Edge*>(&i));
849 if (*static_cast<Graph1Edge*>(&i)==INVALID) i=INVALID;
851 Parent2::graph->nextOut(*static_cast<Graph2Edge*>(&i));
855 Node source(const Edge& i) const {
858 Node(Parent1::graph->source(i), INVALID, false);
861 Node(INVALID, Parent2::graph->source(i), true);
865 Node target(const Edge& i) const {
868 Node(Parent1::graph->target(i), INVALID, false);
871 Node(INVALID, Parent2::graph->target(i), true);
876 int id(const Edge& n) const {
878 return this->Parent1::graph->id(n);
880 return this->Parent2::graph->id(n);
883 template <typename _Value>
886 typedef typename Parent::Graph1::template EdgeMap<_Value> ParentMap1;
887 typedef typename Parent::Graph2::template EdgeMap<_Value> ParentMap2;
888 ParentMap1 forward_map;
889 ParentMap2 backward_map;
891 typedef _Value Value;
893 EdgeMap(const MergeEdgeGraphWrapperBase<_Graph1, _Graph2>& gw) :
894 forward_map(*(gw.Parent1::graph)),
895 backward_map(*(gw.Parent2::graph)) { }
896 EdgeMap(const MergeEdgeGraphWrapperBase<_Graph1, _Graph2>& gw,
897 const _Value& value) :
898 forward_map(*(gw.Parent1::graph), value),
899 backward_map(*(gw.Parent2::graph), value) { }
900 _Value operator[](const Edge& n) const {
902 return forward_map[n];
904 return backward_map[n];
906 void set(const Edge& n, const _Value& value) {
908 forward_map.set(n, value);
910 backward_map.set(n, value);
912 // using ParentMap1::operator[];
913 // using ParentMap2::operator[];
919 /*! A grah wrapper base class
920 for merging the node-sets and edge-sets of
921 two node-disjoint graphs
923 Specialized implementation for the case
924 when _Graph1::Edge is derived from _Graph2::Edge.
926 template <typename _Graph1, typename _Graph2>
927 class MergeEdgeGraphWrapperBase<
928 _Graph1, _Graph2, typename boost::enable_if<
929 boost::is_base_and_derived<typename _Graph2::Edge, typename _Graph1::Edge> >::type> :
930 public MergeNodeGraphWrapperBase<_Graph1, _Graph2> {
932 static void printEdge() { std::cout << "edge: 1st is derived" << std::endl; }
933 typedef _Graph1 Graph1;
934 typedef _Graph2 Graph2;
935 typedef MergeNodeGraphWrapperBase<_Graph1, _Graph2> Parent;
936 typedef typename Parent::Parent1 Parent1;
937 typedef typename Parent::Parent2 Parent2;
938 // typedef P1<_Graph1> Parent1;
939 // typedef P2<_Graph2> Parent2;
940 typedef typename Parent1::Edge Graph1Edge;
941 typedef typename Parent2::Edge Graph2Edge;
943 MergeEdgeGraphWrapperBase() { }
945 template <typename _Value> class EdgeMap;
947 typedef typename Parent::Node Node;
949 class Edge : public Graph1Edge {
950 friend class MergeEdgeGraphWrapperBase<_Graph1, _Graph2>;
951 template <typename _Value> friend class EdgeMap;
953 bool backward; //true, iff backward
956 /// \todo =false is needed, or causes problems?
957 /// If \c _backward is false, then we get an edge corresponding to the
958 /// original one, otherwise its oppositely directed pair is obtained.
959 Edge(const Graph1Edge& n1,
960 const Graph2Edge& n2, bool _backward) :
961 Graph1Edge(n1), backward(_backward) {
962 if (backward) *this=n2;
964 Edge(Invalid i) : Graph1Edge(i), backward(true) { }
965 bool operator==(const Edge& v) const {
967 return (v.backward &&
968 static_cast<Graph2Edge>(*this)==static_cast<Graph2Edge>(v));
970 return (!v.backward &&
971 static_cast<Graph1Edge>(*this)==static_cast<Graph1Edge>(v));
973 bool operator!=(const Edge& v) const {
978 using Parent::forward;
979 using Parent::backward;
980 bool forward(const Edge& e) const { return !e.backward; }
981 bool backward(const Edge& e) const { return e.backward; }
984 void first(Edge& i) const {
985 Parent1::graph->first(*static_cast<Graph1Edge*>(&i));
987 if (*static_cast<Graph1Edge*>(&i)==INVALID) {
988 Parent2::graph->first(*static_cast<Graph2Edge*>(&i));
992 void firstIn(Edge& i, const Node& n) const {
994 Parent1::graph->firstIn(*static_cast<Graph1Edge*>(&i), n);
995 if (*static_cast<Graph1Edge*>(&i)==INVALID)
1000 Parent2::graph->firstIn(*static_cast<Graph2Edge*>(&i), n);
1004 void firstOut(Edge& i, const Node& n) const {
1006 Parent1::graph->firstOut(*static_cast<Graph1Edge*>(&i), n);
1007 if (*static_cast<Graph1Edge*>(&i)==INVALID)
1012 Parent2::graph->firstOut(*static_cast<Graph2Edge*>(&i), n);
1018 void next(Edge& i) const {
1019 if (!(i.backward)) {
1020 Parent1::graph->next(*static_cast<Graph1Edge*>(&i));
1021 if (*static_cast<Graph1Edge*>(&i)==INVALID) {
1022 Parent2::graph->first(*static_cast<Graph2Edge*>(&i));
1026 Parent2::graph->next(*static_cast<Graph2Edge*>(&i));
1029 void nextIn(Edge& i) const {
1030 if (!(i.backward)) {
1031 Parent1::graph->nextIn(*static_cast<Graph1Edge*>(&i));
1032 if (*static_cast<Graph1Edge*>(&i)==INVALID) i=INVALID;
1034 Parent2::graph->nextIn(*static_cast<Graph2Edge*>(&i));
1037 void nextOut(Edge& i) const {
1038 if (!(i.backward)) {
1039 Parent1::graph->nextOut(*static_cast<Graph1Edge*>(&i));
1040 if (*static_cast<Graph1Edge*>(&i)==INVALID) i=INVALID;
1042 Parent2::graph->nextOut(*static_cast<Graph2Edge*>(&i));
1046 Node source(const Edge& i) const {
1047 if (!(i.backward)) {
1049 Node(Parent1::graph->source(i), INVALID, false);
1052 Node(INVALID, Parent2::graph->source(i), true);
1056 Node target(const Edge& i) const {
1057 if (!(i.backward)) {
1059 Node(Parent1::graph->target(i), INVALID, false);
1062 Node(INVALID, Parent2::graph->target(i), true);
1067 int id(const Edge& n) const {
1069 return this->Parent1::graph->id(n);
1071 return this->Parent2::graph->id(n);
1074 template <typename _Value>
1077 typedef typename Parent::Graph1::template EdgeMap<_Value> ParentMap1;
1078 typedef typename Parent::Graph2::template EdgeMap<_Value> ParentMap2;
1079 ParentMap1 forward_map;
1080 ParentMap2 backward_map;
1082 typedef _Value Value;
1084 EdgeMap(const MergeEdgeGraphWrapperBase<_Graph1, _Graph2>& gw) :
1085 forward_map(*(gw.Parent1::graph)),
1086 backward_map(*(gw.Parent2::graph)) { }
1087 EdgeMap(const MergeEdgeGraphWrapperBase<_Graph1, _Graph2>& gw,
1088 const _Value& value) :
1089 forward_map(*(gw.Parent1::graph), value),
1090 backward_map(*(gw.Parent2::graph), value) { }
1091 _Value operator[](const Edge& n) const {
1093 return forward_map[n];
1095 return backward_map[n];
1097 void set(const Edge& n, const _Value& value) {
1099 forward_map.set(n, value);
1101 backward_map.set(n, value);
1103 // using ParentMap1::operator[];
1104 // using ParentMap2::operator[];
1110 /*! A graph wrapper class
1111 for merging the node-sets and edge-sets of
1112 two node-disjoint graphs
1115 template <typename _Graph1, typename _Graph2>
1116 class MergeEdgeGraphWrapper : public
1117 IterableGraphExtender<MergeEdgeGraphWrapperBase<_Graph1, _Graph2> > {
1119 typedef _Graph1 Graph1;
1120 typedef _Graph2 Graph2;
1121 typedef IterableGraphExtender<
1122 MergeEdgeGraphWrapperBase<_Graph1, _Graph2> > Parent;
1124 MergeEdgeGraphWrapper() { }
1126 MergeEdgeGraphWrapper(_Graph1& _graph1, _Graph2& _graph2) {
1127 Parent::Parent1::setGraph(_graph1);
1128 Parent::Parent2::setGraph(_graph2);
1133 /*! A graph wrapper base class for the following functionality.
1134 If a bijection is given between the node-sets of two graphs,
1135 then the second one can be considered as a new edge-set
1136 over th first node-set.
1138 template <typename _Graph, typename _EdgeSetGraph>
1139 class NewEdgeSetGraphWrapperBase : public GraphWrapperBase<_Graph> {
1141 typedef GraphWrapperBase<_Graph> Parent;
1142 typedef _Graph Graph;
1143 typedef _EdgeSetGraph EdgeSetGraph;
1144 typedef typename _Graph::Node Node;
1145 typedef typename _EdgeSetGraph::Node ENode;
1147 EdgeSetGraph* edge_set_graph;
1148 typename Graph::NodeMap<ENode>* e_node;
1149 typename EdgeSetGraph::NodeMap<Node>* n_node;
1150 void setEdgeSetGraph(EdgeSetGraph& _edge_set_graph) {
1151 edge_set_graph=&_edge_set_graph;
1153 /// For each node of \c Graph, this gives a node of \c EdgeSetGraph .
1154 void setNodeMap(typename EdgeSetGraph::NodeMap<Node>& _n_node) {
1157 /// For each node of \c EdgeSetGraph, this gives a node of \c Graph .
1158 void setENodeMap(typename Graph::NodeMap<ENode>& _e_node) {
1162 class Edge : public EdgeSetGraph::Edge {
1163 typedef typename EdgeSetGraph::Edge Parent;
1166 Edge(const Parent& e) : Parent(e) { }
1167 Edge(Invalid i) : Parent(i) { }
1170 using Parent::first;
1171 void first(Edge &e) const {
1172 edge_set_graph->first(e);
1174 void firstOut(Edge& e, const Node& n) const {
1175 // cout << e_node << endl;
1176 // cout << n_node << endl;
1177 edge_set_graph->firstOut(e, (*e_node)[n]);
1179 void firstIn(Edge& e, const Node& n) const {
1180 edge_set_graph->firstIn(e, (*e_node)[n]);
1184 void next(Edge &e) const {
1185 edge_set_graph->next(e);
1187 void nextOut(Edge& e) const {
1188 edge_set_graph->nextOut(e);
1190 void nextIn(Edge& e) const {
1191 edge_set_graph->nextIn(e);
1194 Node source(const Edge& e) const {
1195 return (*n_node)[edge_set_graph->source(e)];
1197 Node target(const Edge& e) const {
1198 return (*n_node)[edge_set_graph->target(e)];
1201 int edgeNum() const { return edge_set_graph->edgeNum(); }
1203 // NNode addOldNode() {
1204 // return Parent::addNode();
1207 // ENode addNewNode() {
1208 // return edge_set_graph->addNode();
1211 Edge addEdge(const Node& u, const Node& v) {
1212 return edge_set_graph->addEdge((*e_node)[u], (*e_node)[v]);
1215 using Parent::erase;
1216 void erase(const Edge& i) const { edge_set_graph->erase(i); }
1218 void clear() const { Parent::clear(); edge_set_graph->clear(); }
1220 bool forward(const Edge& e) const { return edge_set_graph->forward(e); }
1221 bool backward(const Edge& e) const { return edge_set_graph->backward(e); }
1223 int id(const Node& e) const { return Parent::id(e); }
1224 int id(const Edge& e) const { return edge_set_graph->id(e); }
1226 Edge opposite(const Edge& e) const { return edge_set_graph->opposite(e); }
1228 template <typename _Value>
1229 class EdgeMap : public EdgeSetGraph::EdgeMap<_Value> {
1231 typedef typename EdgeSetGraph::EdgeMap<_Value> Parent;
1232 typedef _Value Value;
1234 EdgeMap(const NewEdgeSetGraphWrapperBase& gw) :
1235 Parent(*(gw.edge_set_graph)) { }
1236 EdgeMap(const NewEdgeSetGraphWrapperBase& gw, const _Value& _value) :
1237 Parent(*(gw.edge_set_graph), _value) { }
1243 /*! A graph wrapper class for the following functionality.
1244 If a bijection is given between the node-sets of two graphs,
1245 then the second one can be considered as a new edge-set
1246 over th first node-set.
1248 template <typename _Graph, typename _EdgeSetGraph>
1249 class NewEdgeSetGraphWrapper :
1250 public IterableGraphExtender<
1251 NewEdgeSetGraphWrapperBase<_Graph, _EdgeSetGraph> > {
1253 typedef _Graph Graph;
1254 typedef _EdgeSetGraph EdgeSetGraph;
1255 typedef IterableGraphExtender<
1256 NewEdgeSetGraphWrapperBase<_Graph, _EdgeSetGraph> > Parent;
1258 NewEdgeSetGraphWrapper() { }
1260 NewEdgeSetGraphWrapper(_Graph& _graph,
1261 _EdgeSetGraph& _edge_set_graph,
1263 NodeMap<typename _EdgeSetGraph::Node>& _e_node,
1264 typename _EdgeSetGraph::
1265 NodeMap<typename _Graph::Node>& _n_node) {
1267 setEdgeSetGraph(_edge_set_graph);
1268 setNodeMap(_n_node);
1269 setENodeMap(_e_node);
1273 /*! A graph wrapper class for the following functionality.
1274 The same as NewEdgeSetGrapWrapper, but the bijection and the graph of
1275 new edges is andled inthe class.
1277 template <typename _Graph, typename _EdgeSetGraph>
1278 class NewEdgeSetGraphWrapper2 :
1279 public IterableGraphExtender<
1280 NewEdgeSetGraphWrapperBase<_Graph, _EdgeSetGraph> > {
1282 typedef _Graph Graph;
1283 typedef _EdgeSetGraph EdgeSetGraph;
1284 typedef IterableGraphExtender<
1285 NewEdgeSetGraphWrapperBase<_Graph, _EdgeSetGraph> > Parent;
1287 _EdgeSetGraph _edge_set_graph;
1288 typename Graph::template NodeMap<typename EdgeSetGraph::Node> _e_node;
1289 typename EdgeSetGraph::template NodeMap<typename Graph::Node> _n_node;
1290 NewEdgeSetGraphWrapper2() { }
1292 typedef typename Graph::Node Node;
1293 // typedef typename Parent::Edge Edge;
1295 NewEdgeSetGraphWrapper2(_Graph& _graph) :
1297 _e_node(_graph), _n_node(_edge_set_graph) {
1299 setEdgeSetGraph(_edge_set_graph);
1300 setNodeMap(_n_node); setENodeMap(_e_node);
1302 for (this->first(n); n!=INVALID; this->next(n)) {
1303 typename EdgeSetGraph::Node e=_edge_set_graph.addNode();
1310 // Node n=(*this).Parent::addNode();
1311 // typename EdgeSetGraph::Node e=_edge_set_graph.addNode();
1312 // _e_node.set(n, e);
1313 // _n_node.set(e, n);
1319 /*! A graph wrapper base class
1320 for merging graphs of type _Graph1 and _Graph2
1321 which are given on the same node-set
1322 (specially on the node-set of Graph1)
1324 In an other point of view, _Graph1 is extended with
1325 the edge-set of _Graph2.
1326 \warning we need specialize dimplementations
1327 \todo we need specialize dimplementations
1328 \bug we need specialize dimplementations
1330 template <typename _Graph1, typename _Graph2, typename Enable=void>
1331 class AugmentingGraphWrapperBase :
1332 public P1<_Graph1> {
1334 void printAugment() const { std::cout << "generic" << std::endl; }
1335 typedef _Graph1 Graph1;
1336 typedef _Graph2 Graph2;
1337 typedef P1<_Graph1> Parent1;
1338 typedef P2<_Graph2> Parent2;
1339 typedef typename Parent1::Edge Graph1Edge;
1340 typedef typename Parent2::Edge Graph2Edge;
1342 AugmentingGraphWrapperBase() { }
1344 void setGraph2(_Graph2& _graph2) { graph2=&_graph2; }
1347 template <typename _Value> class EdgeMap;
1349 typedef typename Parent1::Node Node;
1351 class Edge : public Graph1Edge, public Graph2Edge {
1352 friend class AugmentingGraphWrapperBase<_Graph1, _Graph2>;
1353 template <typename _Value> friend class EdgeMap;
1355 bool backward; //true, iff backward
1358 /// \todo =false is needed, or causes problems?
1359 /// If \c _backward is false, then we get an edge corresponding to the
1360 /// original one, otherwise its oppositely directed pair is obtained.
1361 Edge(const Graph1Edge& n1,
1362 const Graph2Edge& n2, bool _backward) :
1363 Graph1Edge(n1), Graph2Edge(n2), backward(_backward) { }
1364 Edge(Invalid i) : Graph1Edge(i), Graph2Edge(i), backward(true) { }
1365 bool operator==(const Edge& v) const {
1367 return (v.backward &&
1368 static_cast<Graph2Edge>(*this)==static_cast<Graph2Edge>(v));
1370 return (!v.backward &&
1371 static_cast<Graph1Edge>(*this)==static_cast<Graph1Edge>(v));
1373 bool operator!=(const Edge& v) const {
1378 using Parent1::first;
1379 void first(Edge& i) const {
1380 Parent1::graph->first(*static_cast<Graph1Edge*>(&i));
1382 if (*static_cast<Graph1Edge*>(&i)==INVALID) {
1383 graph2->first(*static_cast<Graph2Edge*>(&i));
1387 void firstIn(Edge& i, const Node& n) const {
1388 Parent1::graph->firstIn(*static_cast<Graph1Edge*>(&i), n);
1390 if (*static_cast<Graph1Edge*>(&i)==INVALID) {
1391 graph2->firstIn(*static_cast<Graph2Edge*>(&i), n);
1395 void firstOut(Edge& i, const Node& n) const {
1396 Parent1::graph->firstOut(*static_cast<Graph1Edge*>(&i), n);
1398 if (*static_cast<Graph1Edge*>(&i)==INVALID) {
1399 graph2->firstOut(*static_cast<Graph2Edge*>(&i), n);
1404 using Parent1::next;
1405 void next(Edge& i) const {
1406 if (!(i.backward)) {
1407 Parent1::graph->next(*static_cast<Graph1Edge*>(&i));
1408 if (*static_cast<Graph1Edge*>(&i)==INVALID) {
1409 graph2->first(*static_cast<Graph2Edge*>(&i));
1413 graph2->next(*static_cast<Graph2Edge*>(&i));
1416 void nextIn(Edge& i) const {
1417 if (!(i.backward)) {
1419 Parent1::graph->nextIn(*static_cast<Graph1Edge*>(&i));
1420 if (*static_cast<Graph1Edge*>(&i)==INVALID) {
1421 graph2->firstIn(*static_cast<Graph2Edge*>(&i), n);
1425 graph2->nextIn(*static_cast<Graph2Edge*>(&i));
1428 void nextOut(Edge& i) const {
1429 if (!(i.backward)) {
1431 Parent1::graph->nextOut(*static_cast<Graph1Edge*>(&i));
1432 if (*static_cast<Graph1Edge*>(&i)==INVALID) {
1433 graph2->firstOut(*static_cast<Graph2Edge*>(&i), n);
1437 graph2->nextOut(*static_cast<Graph2Edge*>(&i));
1441 Node source(const Edge& i) const {
1442 if (!(i.backward)) {
1443 return Parent1::graph->source(i);
1445 return graph2->source(i);
1449 Node target(const Edge& i) const {
1450 if (!(i.backward)) {
1451 return Parent1::graph->target(i);
1453 return graph2->target(i);
1457 int id(const Node& n) const {
1458 return Parent1::id(n);
1460 int id(const Edge& n) const {
1462 return this->Parent1::graph->id(n);
1464 return this->graph2->id(n);
1467 template <typename _Value>
1470 typedef typename _Graph1::template EdgeMap<_Value> ParentMap1;
1471 typedef typename _Graph2::template EdgeMap<_Value> ParentMap2;
1472 ParentMap1 forward_map;
1473 ParentMap2 backward_map;
1475 typedef _Value Value;
1477 EdgeMap(const AugmentingGraphWrapperBase<_Graph1, _Graph2>& gw) :
1478 forward_map(*(gw.Parent1::graph)),
1479 backward_map(*(gw.graph2)) { }
1480 EdgeMap(const AugmentingGraphWrapperBase<_Graph1, _Graph2>& gw,
1481 const _Value& value) :
1482 forward_map(*(gw.Parent1::graph), value),
1483 backward_map(*(gw.graph2), value) { }
1484 _Value operator[](const Edge& n) const {
1486 return forward_map[n];
1488 return backward_map[n];
1490 void set(const Edge& n, const _Value& value) {
1492 forward_map.set(n, value);
1494 backward_map.set(n, value);
1496 // using ParentMap1::operator[];
1497 // using ParentMap2::operator[];
1503 /*! A graph wrapper class
1504 for merging two graphs (of type _Graph1 and _Graph2)
1505 with the same node-set
1506 (specially on the node-set of Graph1)
1508 In an other point of view, _Graph1 is extended with
1509 the edge-set of _Graph2.
1511 template <typename _Graph1, typename _Graph2>
1512 class AugmentingGraphWrapper : public
1513 IterableGraphExtender<AugmentingGraphWrapperBase<_Graph1, _Graph2> > {
1516 IterableGraphExtender<AugmentingGraphWrapperBase<_Graph1, _Graph2> >
1518 typedef _Graph1 Graph1;
1519 typedef _Graph2 Graph2;
1521 AugmentingGraphWrapper() { }
1523 AugmentingGraphWrapper(_Graph1& _graph1, _Graph2& _graph2) {
1531 #endif //LEMON_MERGE_NODE_GRAPH_WRAPPER_H