# HG changeset patch # User marci # Date 1101114558 0 # Node ID 18d009b23e42cdd5c0999f354a37e60440f4f165 # Parent e3bb0e118bb401baa5fd8c951b27cb782d247ca0 bug fix in SubBidirGraphWrapper, roadmap to MergeGraphWrapper diff -r e3bb0e118bb4 -r 18d009b23e42 src/lemon/graph_wrapper.h --- a/src/lemon/graph_wrapper.h Sat Nov 20 16:12:47 2004 +0000 +++ b/src/lemon/graph_wrapper.h Mon Nov 22 09:09:18 2004 +0000 @@ -1192,7 +1192,7 @@ // } // typename _Graph::template EdgeMap::Reference - T operator[](Edge e) { + T operator[](Edge e) const { if (!e.backward) return forward_map[e]; else diff -r e3bb0e118bb4 -r 18d009b23e42 src/work/marci/makefile --- a/src/work/marci/makefile Sat Nov 20 16:12:47 2004 +0000 +++ b/src/work/marci/makefile Mon Nov 22 09:09:18 2004 +0000 @@ -1,7 +1,7 @@ CXX2 = g++-2.95 CXX3=$(CXX) BOOSTROOT ?= /home/marci/boost -INCLUDEDIRS ?= -I../{jacint,marci,alpar,klao,akos,athos} -I../.. -I.. -I$(BOOSTROOT) +INCLUDEDIRS ?= -ftemplate-depth-50 -I../{jacint,marci,alpar,klao,akos,athos} -I../.. -I.. -I$(BOOSTROOT) LEDABINARIES = leda_graph_demo leda_bfs_dfs max_bipartite_matching_demo 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 diff -r e3bb0e118bb4 -r 18d009b23e42 src/work/marci/merge_node_graph_wrapper.h --- a/src/work/marci/merge_node_graph_wrapper.h Sat Nov 20 16:12:47 2004 +0000 +++ b/src/work/marci/merge_node_graph_wrapper.h Mon Nov 22 09:09:18 2004 +0000 @@ -270,8 +270,7 @@ 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 + _Graph1::Node is a base class and _Graph2::Node is derived from it. */ template class MergeNodeGraphWrapperBase< @@ -289,13 +288,109 @@ protected: MergeNodeGraphWrapperBase() { } public: - class Node { }; + template class NodeMap; + + class Node : 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) : + Graph2Node(n2), backward(_backward) { + if (!backward) *this=n1; + } + Node(Invalid 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() const; - void next() const; + + 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[]; + }; + }; - //not yet working + + /*! A graph wrapper base class + for merging the node-set of two node-disjoint graphs + into the node-set of one graph. + Specialized implementaton for the case when _Graph1::Node is derived + from _Graph2::Node. + */ template class MergeNodeGraphWrapperBase< _Graph1, _Graph2, typename boost::enable_if< @@ -312,10 +407,100 @@ protected: MergeNodeGraphWrapperBase() { } public: - class Node { }; + 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(n1), backward(_backward) { + if (backward) *this=n2; + } + Node(Invalid i) : Graph1Node(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() const; - void next() const; + + 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[]; + }; + }; @@ -532,7 +717,7 @@ template class MergeEdgeGraphWrapperBase< _Graph1, _Graph2, typename boost::enable_if< - boost::is_same >::type> : + boost::is_same >::type> : public MergeNodeGraphWrapperBase<_Graph1, _Graph2> { public: static void printEdge() { std::cout << "edge: same" << std::endl; } @@ -700,6 +885,375 @@ }; + /*! A grah wrapper base class + for merging the node-sets and edge-sets of + two node-disjoint graphs + into one graph. + Specialized implementation for the case + when _Graph1::Edge is a base class and _Graph2::Edge + is derived from it. + */ + template + class MergeEdgeGraphWrapperBase< + _Graph1, _Graph2, typename boost::enable_if< + boost::is_base_and_derived >::type> : + public MergeNodeGraphWrapperBase<_Graph1, _Graph2> { + public: + static void printEdge() { std::cout << "edge: 2nd is derived" << 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 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) : + Graph2Edge(n2), backward(_backward) { + if (!backward) *this=n1; + } + Edge(Invalid 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 grah wrapper base class + for merging the node-sets and edge-sets of + two node-disjoint graphs + into one graph. + Specialized implementation for the case + when _Graph1::Edge is derived from _Graph2::Edge. + */ + template + class MergeEdgeGraphWrapperBase< + _Graph1, _Graph2, typename boost::enable_if< + boost::is_base_and_derived >::type> : + public MergeNodeGraphWrapperBase<_Graph1, _Graph2> { + public: + static void printEdge() { std::cout << "edge: 1st is derived" << 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(n1), backward(_backward) { + if (backward) *this=n2; + } + Edge(Invalid i) : Graph1Edge(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 class for merging the node-sets and edge-sets of two node-disjoint graphs diff -r e3bb0e118bb4 -r 18d009b23e42 src/work/marci/merge_node_graph_wrapper_test.cc --- a/src/work/marci/merge_node_graph_wrapper_test.cc Sat Nov 20 16:12:47 2004 +0000 +++ b/src/work/marci/merge_node_graph_wrapper_test.cc Mon Nov 22 09:09:18 2004 +0000 @@ -48,6 +48,14 @@ checkConcept >(); MergeEdgeGraphWrapper::printNode(); MergeEdgeGraphWrapper::printEdge(); + typedef ResGraphWrapper, ConstMap > Graph4; + checkConcept >(); + MergeEdgeGraphWrapper::printNode(); + MergeEdgeGraphWrapper::printEdge(); + checkConcept >(); + MergeEdgeGraphWrapper::printNode(); + MergeEdgeGraphWrapper::printEdge(); } Graph1 g1; @@ -118,6 +126,7 @@ printGraph(gw); typedef ListGraph Graph3; + //typedef SmartGraph Graph3; Graph3 g3; GW::NodeMap gwn(gw); Graph3::NodeMap g3n(g3);