diff -r ef2d00e46897 -r c2992fd74dad lemon/bits/graph_extender.h --- a/lemon/bits/graph_extender.h Wed Feb 22 12:45:59 2006 +0000 +++ b/lemon/bits/graph_extender.h Wed Feb 22 18:26:56 2006 +0000 @@ -22,15 +22,19 @@ #include #include +#include + namespace lemon { - template - class GraphExtender : public _Base { + template + class GraphExtender : public Base { public: - typedef _Base Parent; + typedef Base Parent; typedef GraphExtender Graph; + // Base extensions + typedef typename Parent::Node Node; typedef typename Parent::Edge Edge; @@ -59,24 +63,278 @@ return INVALID; } - }; + // Alterable extension - template - class UGraphExtender : public _Base { - typedef _Base Parent; - typedef UGraphExtender Graph; + typedef AlterationNotifier NodeNotifier; + typedef AlterationNotifier EdgeNotifier; + + + protected: + + mutable NodeNotifier node_notifier; + mutable EdgeNotifier edge_notifier; public: + NodeNotifier& getNotifier(Node) const { + return node_notifier; + } + + EdgeNotifier& getNotifier(Edge) const { + return edge_notifier; + } + + class NodeIt : public Node { + const Graph* graph; + public: + + NodeIt() {} + + NodeIt(Invalid i) : Node(i) { } + + explicit NodeIt(const Graph& _graph) : graph(&_graph) { + _graph.first(*static_cast(this)); + } + + NodeIt(const Graph& _graph, const Node& node) + : Node(node), graph(&_graph) {} + + NodeIt& operator++() { + graph->next(*this); + return *this; + } + + }; + + + class EdgeIt : public Edge { + const Graph* graph; + public: + + EdgeIt() { } + + EdgeIt(Invalid i) : Edge(i) { } + + explicit EdgeIt(const Graph& _graph) : graph(&_graph) { + _graph.first(*static_cast(this)); + } + + EdgeIt(const Graph& _graph, const Edge& e) : + Edge(e), graph(&_graph) { } + + EdgeIt& operator++() { + graph->next(*this); + return *this; + } + + }; + + + class OutEdgeIt : public Edge { + const Graph* graph; + public: + + OutEdgeIt() { } + + OutEdgeIt(Invalid i) : Edge(i) { } + + OutEdgeIt(const Graph& _graph, const Node& node) + : graph(&_graph) { + _graph.firstOut(*this, node); + } + + OutEdgeIt(const Graph& _graph, const Edge& edge) + : Edge(edge), graph(&_graph) {} + + OutEdgeIt& operator++() { + graph->nextOut(*this); + return *this; + } + + }; + + + class InEdgeIt : public Edge { + const Graph* graph; + public: + + InEdgeIt() { } + + InEdgeIt(Invalid i) : Edge(i) { } + + InEdgeIt(const Graph& _graph, const Node& node) + : graph(&_graph) { + _graph.firstIn(*this, node); + } + + InEdgeIt(const Graph& _graph, const Edge& edge) : + Edge(edge), graph(&_graph) {} + + InEdgeIt& operator++() { + graph->nextIn(*this); + return *this; + } + + }; + + /// \brief Base node of the iterator + /// + /// Returns the base node (ie. the source in this case) of the iterator + Node baseNode(const OutEdgeIt &e) const { + return Parent::source(e); + } + /// \brief Running node of the iterator + /// + /// Returns the running node (ie. the target in this case) of the + /// iterator + Node runningNode(const OutEdgeIt &e) const { + return Parent::target(e); + } + + /// \brief Base node of the iterator + /// + /// Returns the base node (ie. the target in this case) of the iterator + Node baseNode(const InEdgeIt &e) const { + return Parent::target(e); + } + /// \brief Running node of the iterator + /// + /// Returns the running node (ie. the source in this case) of the + /// iterator + Node runningNode(const InEdgeIt &e) const { + return Parent::source(e); + } + + + template + class NodeMap + : public IterableMapExtender > { + public: + typedef GraphExtender Graph; + typedef IterableMapExtender > Parent; + + NodeMap(const Graph& _g) + : Parent(_g) {} + NodeMap(const Graph& _g, const _Value& _v) + : Parent(_g, _v) {} + + NodeMap& operator=(const NodeMap& cmap) { + return operator=(cmap); + } + + + /// \brief Template assign operator. + /// + /// The given parameter should be conform to the ReadMap + /// concecpt and could be indiced by the current item set of + /// the NodeMap. In this case the value for each item + /// is assigned by the value of the given ReadMap. + template + NodeMap& operator=(const CMap& cmap) { + checkConcept, CMap>(); + const typename Parent::Graph* graph = Parent::getGraph(); + Node it; + for (graph->first(it); it != INVALID; graph->next(it)) { + Parent::set(it, cmap[it]); + } + return *this; + } + + }; + + template + class EdgeMap + : public IterableMapExtender > { + public: + typedef GraphExtender Graph; + typedef IterableMapExtender > Parent; + + EdgeMap(const Graph& _g) + : Parent(_g) {} + EdgeMap(const Graph& _g, const _Value& _v) + : Parent(_g, _v) {} + + EdgeMap& operator=(const EdgeMap& cmap) { + return operator=(cmap); + } + + template + EdgeMap& operator=(const CMap& cmap) { + checkConcept, CMap>(); + const typename Parent::Graph* graph = Parent::getGraph(); + Edge it; + for (graph->first(it); it != INVALID; graph->next(it)) { + Parent::set(it, cmap[it]); + } + return *this; + } + }; + + + Node addNode() { + Node node = Parent::addNode(); + getNotifier(Node()).add(node); + return node; + } + + Edge addEdge(const Node& from, const Node& to) { + Edge edge = Parent::addEdge(from, to); + getNotifier(Edge()).add(edge); + return edge; + } + + void clear() { + getNotifier(Edge()).clear(); + getNotifier(Node()).clear(); + Parent::clear(); + } + + + void erase(const Node& node) { + Edge edge; + Parent::firstOut(edge, node); + while (edge != INVALID ) { + erase(edge); + Parent::firstOut(edge, node); + } + + Parent::firstIn(edge, node); + while (edge != INVALID ) { + erase(edge); + Parent::firstIn(edge, node); + } + + getNotifier(Node()).erase(node); + Parent::erase(node); + } + + void erase(const Edge& edge) { + getNotifier(Edge()).erase(edge); + Parent::erase(edge); + } + + + ~GraphExtender() { + getNotifier(Edge()).clear(); + getNotifier(Node()).clear(); + } + }; + + template + class UGraphBaseExtender : public Base { + + public: + + typedef Base Parent; typedef typename Parent::Edge UEdge; typedef typename Parent::Node Node; + typedef True UndirectedTag; + class Edge : public UEdge { - friend class UGraphExtender; + friend class UGraphBaseExtender; protected: - // FIXME: Marci use opposite logic in his graph adaptors. It would - // be reasonable to syncronize... bool forward; Edge(const UEdge &ue, bool _forward) : @@ -101,16 +359,7 @@ }; - /// \brief Edge of opposite direction. - /// - /// Returns the Edge of opposite direction. - Edge oppositeEdge(const Edge &e) const { - return Edge(e,!e.forward); - } - public: - /// \todo Shouldn't the "source" of an undirected edge be called "aNode" - /// or something??? using Parent::source; /// Source of the given Edge. @@ -118,8 +367,6 @@ return e.forward ? Parent::source(e) : Parent::target(e); } - /// \todo Shouldn't the "target" of an undirected edge be called "bNode" - /// or something??? using Parent::target; /// Target of the given Edge. @@ -127,24 +374,6 @@ return e.forward ? Parent::target(e) : Parent::source(e); } - Node oppositeNode(const Node &n, const UEdge &e) const { - if( n == Parent::source(e)) - return Parent::target(e); - else if( n == Parent::target(e)) - return Parent::source(e); - else - return INVALID; - } - - /// \brief Directed edge from an undirected edge and a source node. - /// - /// Returns a (directed) Edge corresponding to the specified UEdge - /// and source Node. - /// - Edge direct(const UEdge &ue, const Node &s) const { - return Edge(ue, s == source(ue)); - } - /// \brief Directed edge from an undirected edge. /// /// Returns a directed edge corresponding to the specified UEdge. @@ -163,12 +392,13 @@ using Parent::first; + using Parent::next; + void first(Edge &e) const { Parent::first(e); e.forward=true; } - using Parent::next; void next(Edge &e) const { if( e.forward ) { e.forward = false; @@ -179,8 +409,6 @@ } } - public: - void firstOut(Edge &e, const Node &n) const { Parent::firstIn(e,n); if( UEdge(e) != INVALID ) { @@ -229,21 +457,6 @@ } } - void firstInc(UEdge &e, const Node &n) const { - Parent::firstOut(e, n); - if (e != INVALID) return; - Parent::firstIn(e, n); - } - void nextInc(UEdge &e, const Node &n) const { - if (Parent::source(e) == n) { - Parent::nextOut(e); - if (e != INVALID) return; - Parent::firstIn(e, n); - } else { - Parent::nextIn(e); - } - } - void firstInc(UEdge &e, bool &d, const Node &n) const { d = true; Parent::firstOut(e, n); @@ -251,6 +464,7 @@ d = false; Parent::firstIn(e, n); } + void nextInc(UEdge &e, bool &d) const { if (d) { Node s = Parent::source(e); @@ -263,14 +477,17 @@ } } - // Miscellaneous stuff: + Node nodeFromId(int id) const { + return Parent::nodeFromId(id); + } - /// \todo these methods (id, maxEdgeId) should be moved into separate - /// Extender + Edge edgeFromId(int id) const { + return direct(Parent::edgeFromId(id >> 1), bool(id & 1)); + } - // using Parent::id; - // Using "using" is not a good idea, cause it could be that there is - // no "id" in Parent... + UEdge uEdgeFromId(int id) const { + return Parent::edgeFromId(id >> 1); + } int id(const Node &n) const { return Parent::id(n); @@ -296,16 +513,6 @@ return Parent::maxEdgeId(); } - int maxId(Node) const { - return maxNodeId(); - } - - int maxId(Edge) const { - return maxEdgeId(); - } - int maxId(UEdge) const { - return maxUEdgeId(); - } int edgeNum() const { return 2 * Parent::edgeNum(); @@ -315,31 +522,6 @@ return Parent::edgeNum(); } - Node nodeFromId(int id) const { - return Parent::nodeFromId(id); - } - - Edge edgeFromId(int id) const { - return direct(Parent::edgeFromId(id >> 1), bool(id & 1)); - } - - UEdge uEdgeFromId(int id) const { - return Parent::edgeFromId(id >> 1); - } - - Node fromId(int id, Node) const { - return nodeFromId(id); - } - - Edge fromId(int id, Edge) const { - return edgeFromId(id); - } - - UEdge fromId(int id, UEdge) const { - return uEdgeFromId(id); - } - - Edge findEdge(Node source, Node target, Edge prev) const { if (prev == INVALID) { UEdge edge = Parent::findEdge(source, target); @@ -375,24 +557,486 @@ } return INVALID; } + }; + + + template + class UGraphExtender : public Base { + public: + + typedef Base Parent; + typedef UGraphExtender Graph; + + typedef typename Parent::Node Node; + typedef typename Parent::Edge Edge; + typedef typename Parent::UEdge UEdge; + + // UGraph extension + + int maxId(Node) const { + return Parent::maxNodeId(); + } + + int maxId(Edge) const { + return Parent::maxEdgeId(); + } + + int maxId(UEdge) const { + return Parent::maxUEdgeId(); + } + + Node fromId(int id, Node) const { + return Parent::nodeFromId(id); + } + + Edge fromId(int id, Edge) const { + return Parent::edgeFromId(id); + } + + UEdge fromId(int id, UEdge) const { + return Parent::uEdgeFromId(id); + } + + Node oppositeNode(const Node &n, const UEdge &e) const { + if( n == Parent::source(e)) + return Parent::target(e); + else if( n == Parent::target(e)) + return Parent::source(e); + else + return INVALID; + } + + Edge oppositeEdge(const Edge &e) const { + return Parent::direct(e, !Parent::direction(e)); + } + + using Parent::direct; + Edge direct(const UEdge &ue, const Node &s) const { + return Parent::direct(ue, Parent::source(ue) == s); + } + + // Alterable extension + + typedef AlterationNotifier NodeNotifier; + typedef AlterationNotifier EdgeNotifier; + typedef AlterationNotifier UEdgeNotifier; + + + protected: + + mutable NodeNotifier node_notifier; + mutable EdgeNotifier edge_notifier; + mutable UEdgeNotifier uedge_notifier; + + public: + + NodeNotifier& getNotifier(Node) const { + return node_notifier; + } + + EdgeNotifier& getNotifier(Edge) const { + return edge_notifier; + } + + UEdgeNotifier& getNotifier(UEdge) const { + return uedge_notifier; + } + + + + class NodeIt : public Node { + const Graph* graph; + public: + + NodeIt() {} + + NodeIt(Invalid i) : Node(i) { } + + explicit NodeIt(const Graph& _graph) : graph(&_graph) { + _graph.first(*static_cast(this)); + } + + NodeIt(const Graph& _graph, const Node& node) + : Node(node), graph(&_graph) {} + + NodeIt& operator++() { + graph->next(*this); + return *this; + } + + }; + + + class EdgeIt : public Edge { + const Graph* graph; + public: + + EdgeIt() { } + + EdgeIt(Invalid i) : Edge(i) { } + + explicit EdgeIt(const Graph& _graph) : graph(&_graph) { + _graph.first(*static_cast(this)); + } + + EdgeIt(const Graph& _graph, const Edge& e) : + Edge(e), graph(&_graph) { } + + EdgeIt& operator++() { + graph->next(*this); + return *this; + } + + }; + + + class OutEdgeIt : public Edge { + const Graph* graph; + public: + + OutEdgeIt() { } + + OutEdgeIt(Invalid i) : Edge(i) { } + + OutEdgeIt(const Graph& _graph, const Node& node) + : graph(&_graph) { + _graph.firstOut(*this, node); + } + + OutEdgeIt(const Graph& _graph, const Edge& edge) + : Edge(edge), graph(&_graph) {} + + OutEdgeIt& operator++() { + graph->nextOut(*this); + return *this; + } + + }; + + + class InEdgeIt : public Edge { + const Graph* graph; + public: + + InEdgeIt() { } + + InEdgeIt(Invalid i) : Edge(i) { } + + InEdgeIt(const Graph& _graph, const Node& node) + : graph(&_graph) { + _graph.firstIn(*this, node); + } + + InEdgeIt(const Graph& _graph, const Edge& edge) : + Edge(edge), graph(&_graph) {} + + InEdgeIt& operator++() { + graph->nextIn(*this); + return *this; + } + + }; + + + class UEdgeIt : public Parent::UEdge { + const Graph* graph; + public: + + UEdgeIt() { } + + UEdgeIt(Invalid i) : UEdge(i) { } + + explicit UEdgeIt(const Graph& _graph) : graph(&_graph) { + _graph.first(*static_cast(this)); + } + + UEdgeIt(const Graph& _graph, const UEdge& e) : + UEdge(e), graph(&_graph) { } + + UEdgeIt& operator++() { + graph->next(*this); + return *this; + } + + }; + + class IncEdgeIt : public Parent::UEdge { + friend class UGraphExtender; + const Graph* graph; + bool direction; + public: + + IncEdgeIt() { } + + IncEdgeIt(Invalid i) : UEdge(i), direction(false) { } + + IncEdgeIt(const Graph& _graph, const Node &n) : graph(&_graph) { + _graph.firstInc(*this, direction, n); + } + + IncEdgeIt(const Graph& _graph, const UEdge &ue, const Node &n) + : graph(&_graph), UEdge(ue) { + direction = (_graph.source(ue) == n); + } + + IncEdgeIt& operator++() { + graph->nextInc(*this, direction); + return *this; + } + }; + + /// \brief Base node of the iterator + /// + /// Returns the base node (ie. the source in this case) of the iterator + Node baseNode(const OutEdgeIt &e) const { + return Parent::source((Edge)e); + } + /// \brief Running node of the iterator + /// + /// Returns the running node (ie. the target in this case) of the + /// iterator + Node runningNode(const OutEdgeIt &e) const { + return Parent::target((Edge)e); + } + + /// \brief Base node of the iterator + /// + /// Returns the base node (ie. the target in this case) of the iterator + Node baseNode(const InEdgeIt &e) const { + return Parent::target((Edge)e); + } + /// \brief Running node of the iterator + /// + /// Returns the running node (ie. the source in this case) of the + /// iterator + Node runningNode(const InEdgeIt &e) const { + return Parent::source((Edge)e); + } + + /// Base node of the iterator + /// + /// Returns the base node of the iterator + Node baseNode(const IncEdgeIt &e) const { + return e.direction ? source(e) : target(e); + } + /// Running node of the iterator + /// + /// Returns the running node of the iterator + Node runningNode(const IncEdgeIt &e) const { + return e.direction ? target(e) : source(e); + } + + // Mappable extension + + template + class NodeMap + : public IterableMapExtender > { + public: + typedef UGraphExtender Graph; + typedef IterableMapExtender > Parent; + + NodeMap(const Graph& _g) + : Parent(_g) {} + NodeMap(const Graph& _g, const _Value& _v) + : Parent(_g, _v) {} + + NodeMap& operator=(const NodeMap& cmap) { + return operator=(cmap); + } + + + /// \brief Template assign operator. + /// + /// The given parameter should be conform to the ReadMap + /// concecpt and could be indiced by the current item set of + /// the NodeMap. In this case the value for each item + /// is assigned by the value of the given ReadMap. + template + NodeMap& operator=(const CMap& cmap) { + checkConcept, CMap>(); + const typename Parent::Graph* graph = Parent::getGraph(); + Node it; + for (graph->first(it); it != INVALID; graph->next(it)) { + Parent::set(it, cmap[it]); + } + return *this; + } + + }; + + template + class EdgeMap + : public IterableMapExtender > { + public: + typedef UGraphExtender Graph; + typedef IterableMapExtender > Parent; + + EdgeMap(const Graph& _g) + : Parent(_g) {} + EdgeMap(const Graph& _g, const _Value& _v) + : Parent(_g, _v) {} + + EdgeMap& operator=(const EdgeMap& cmap) { + return operator=(cmap); + } + + template + EdgeMap& operator=(const CMap& cmap) { + checkConcept, CMap>(); + const typename Parent::Graph* graph = Parent::getGraph(); + Edge it; + for (graph->first(it); it != INVALID; graph->next(it)) { + Parent::set(it, cmap[it]); + } + return *this; + } + }; + + + template + class UEdgeMap + : public IterableMapExtender > { + public: + typedef UGraphExtender Graph; + typedef IterableMapExtender > Parent; + + UEdgeMap(const Graph& _g) + : Parent(_g) {} + UEdgeMap(const Graph& _g, const _Value& _v) + : Parent(_g, _v) {} + + UEdgeMap& operator=(const UEdgeMap& cmap) { + return operator=(cmap); + } + + template + UEdgeMap& operator=(const CMap& cmap) { + checkConcept, CMap>(); + const typename Parent::Graph* graph = Parent::getGraph(); + UEdge it; + for (graph->first(it); it != INVALID; graph->next(it)) { + Parent::set(it, cmap[it]); + } + return *this; + } + }; + + // Alteration extension + + Node addNode() { + Node node = Parent::addNode(); + getNotifier(Node()).add(node); + return node; + } + + UEdge addEdge(const Node& from, const Node& to) { + UEdge uedge = Parent::addEdge(from, to); + getNotifier(UEdge()).add(uedge); + getNotifier(Edge()).add(Parent::direct(uedge, true)); + getNotifier(Edge()).add(Parent::direct(uedge, false)); + return uedge; + } + + void clear() { + getNotifier(Edge()).clear(); + getNotifier(UEdge()).clear(); + getNotifier(Node()).clear(); + Parent::clear(); + } + + void erase(const Node& node) { + Edge edge; + Parent::firstOut(edge, node); + while (edge != INVALID ) { + erase(edge); + Parent::firstOut(edge, node); + } + + Parent::firstIn(edge, node); + while (edge != INVALID ) { + erase(edge); + Parent::firstIn(edge, node); + } + + getNotifier(Node()).erase(node); + Parent::erase(node); + } + + void erase(const UEdge& uedge) { + getNotifier(Edge()).erase(Parent::direct(uedge, true)); + getNotifier(Edge()).erase(Parent::direct(uedge, false)); + getNotifier(UEdge()).erase(uedge); + Parent::erase(uedge); + } + + ~UGraphExtender() { + getNotifier(Edge()).clear(); + getNotifier(UEdge()).clear(); + getNotifier(Node()).clear(); + } }; - template - class BpUGraphExtender : public _Base { + template + class BpUGraphBaseExtender : public Base { public: - typedef _Base Parent; - typedef BpUGraphExtender Graph; + typedef Base Parent; + typedef BpUGraphBaseExtender Graph; typedef typename Parent::Node Node; typedef typename Parent::Edge UEdge; + using Parent::first; using Parent::next; using Parent::id; + class ANode : public Node { + friend class BpUGraphBaseExtender; + public: + ANode() {} + ANode(const Node& node) : Node(node) { + LEMON_ASSERT(Parent::aNode(node) || node == INVALID, + typename Parent::NodeSetError()); + } + ANode(Invalid) : Node(INVALID) {} + }; + + void first(ANode& node) const { + Parent::firstANode(static_cast(node)); + } + void next(ANode& node) const { + Parent::nextANode(static_cast(node)); + } + + int id(const ANode& node) const { + return Parent::aNodeId(node); + } + + class BNode : public Node { + friend class BpUGraphBaseExtender; + public: + BNode() {} + BNode(const Node& node) : Node(node) { + LEMON_ASSERT(Parent::bNode(node) || node == INVALID, + typename Parent::NodeSetError()); + } + BNode(Invalid) : Node(INVALID) {} + }; + + void first(BNode& node) const { + Parent::firstBNode(static_cast(node)); + } + void next(BNode& node) const { + Parent::nextBNode(static_cast(node)); + } + + int id(const BNode& node) const { + return Parent::aNodeId(node); + } + Node source(const UEdge& edge) const { return aNode(edge); } @@ -427,7 +1071,7 @@ } class Edge : public UEdge { - friend class BpUGraphExtender; + friend class BpUGraphBaseExtender; protected: bool forward; @@ -504,27 +1148,6 @@ return edge.forward ? Parent::bNode(edge) : Parent::aNode(edge); } - bool direction(const Edge& edge) const { - return edge.forward; - } - - Edge direct(const UEdge& edge, const Node& node) const { - return Edge(edge, node == Parent::source(edge)); - } - - Edge direct(const UEdge& edge, bool direction) const { - return Edge(edge, direction); - } - - Node oppositeNode(const UEdge& edge, const Node& node) const { - return source(edge) == node ? - target(edge) : source(edge); - } - - Edge oppositeEdge(const Edge& edge) const { - return Edge(edge, !edge.forward); - } - int id(const Edge& edge) const { return (Parent::id(edge) << 1) + (edge.forward ? 0 : 1); } @@ -535,50 +1158,40 @@ return (Parent::maxId(UEdge()) << 1) + 1; } - class ANode : public Node { - friend class BpUGraphExtender; - public: - ANode() {} - ANode(const Node& node) : Node(node) { - LEMON_ASSERT(Parent::aNode(node) || node == INVALID, - typename Parent::NodeSetError()); - } - ANode(Invalid) : Node(INVALID) {} - }; - - void first(ANode& node) const { - Parent::firstANode(static_cast(node)); - } - void next(ANode& node) const { - Parent::nextANode(static_cast(node)); + bool direction(const Edge& edge) const { + return edge.forward; } - int id(const ANode& node) const { - return Parent::aNodeId(node); + Edge direct(const UEdge& edge, bool direction) const { + return Edge(edge, direction); + } + }; + + template + class BpUGraphExtender : public Base { + public: + typedef Base Parent; + typedef BpUGraphExtender Graph; + + typedef typename Parent::Node Node; + typedef typename Parent::BNode BNode; + typedef typename Parent::ANode ANode; + typedef typename Parent::Edge Edge; + typedef typename Parent::UEdge UEdge; + + Node oppositeNode(const UEdge& edge, const Node& node) const { + return source(edge) == node ? + target(edge) : source(edge); } - class BNode : public Node { - friend class BpUGraphExtender; - public: - BNode() {} - BNode(const Node& node) : Node(node) { - LEMON_ASSERT(Parent::bNode(node) || node == INVALID, - typename Parent::NodeSetError()); - } - BNode(Invalid) : Node(INVALID) {} - }; - - void first(BNode& node) const { - Parent::firstBNode(static_cast(node)); - } - void next(BNode& node) const { - Parent::nextBNode(static_cast(node)); - } - - int id(const BNode& node) const { - return Parent::aNodeId(node); + using Parent::direct; + Edge direct(const UEdge& edge, const Node& node) const { + return Edge(edge, node == Parent::source(edge)); } + Edge oppositeEdge(const Edge& edge) const { + return Parent::direct(edge, !Parent::direction(edge)); + } int maxId(Node) const { @@ -591,10 +1204,10 @@ return Parent::maxANodeId(); } int maxId(Edge) const { - return maxEdgeId(); + return Parent::maxEdgeId(); } int maxId(UEdge) const { - return maxUEdgeId(); + return Parent::maxUEdgeId(); } @@ -608,12 +1221,605 @@ return Parent::fromBNodeId(id); } Edge fromId(int id, Edge) const { - return edgeFromId(id); + return Parent::edgeFromId(id); } UEdge fromId(int id, UEdge) const { - return uEdgeFromId(id); + return Parent::uEdgeFromId(id); + } + + typedef AlterationNotifier NodeNotifier; + typedef AlterationNotifier BNodeNotifier; + typedef AlterationNotifier ANodeNotifier; + typedef AlterationNotifier EdgeNotifier; + typedef AlterationNotifier UEdgeNotifier; + + protected: + + mutable NodeNotifier nodeNotifier; + mutable BNodeNotifier bNodeNotifier; + mutable ANodeNotifier aNodeNotifier; + mutable EdgeNotifier edgeNotifier; + mutable UEdgeNotifier uEdgeNotifier; + + public: + + NodeNotifier& getNotifier(Node) const { + return nodeNotifier; } + BNodeNotifier& getNotifier(BNode) const { + return bNodeNotifier; + } + + ANodeNotifier& getNotifier(ANode) const { + return aNodeNotifier; + } + + EdgeNotifier& getNotifier(Edge) const { + return edgeNotifier; + } + + UEdgeNotifier& getNotifier(UEdge) const { + return uEdgeNotifier; + } + + ~BpUGraphExtender() { + getNotifier(UEdge()).clear(); + getNotifier(Edge()).clear(); + getNotifier(ANode()).clear(); + getNotifier(BNode()).clear(); + getNotifier(Node()).clear(); + } + + + class NodeIt : public Node { + const Graph* graph; + public: + + NodeIt() { } + + NodeIt(Invalid i) : Node(INVALID) { } + + explicit NodeIt(const Graph& _graph) : graph(&_graph) { + graph->first(static_cast(*this)); + } + + NodeIt(const Graph& _graph, const Node& node) + : Node(node), graph(&_graph) { } + + NodeIt& operator++() { + graph->next(*this); + return *this; + } + + }; + + class ANodeIt : public Node { + friend class BpUGraphExtender; + const Graph* graph; + public: + + ANodeIt() { } + + ANodeIt(Invalid i) : Node(INVALID) { } + + explicit ANodeIt(const Graph& _graph) : graph(&_graph) { + graph->firstANode(static_cast(*this)); + } + + ANodeIt(const Graph& _graph, const Node& node) + : Node(node), graph(&_graph) {} + + ANodeIt& operator++() { + graph->nextANode(*this); + return *this; + } + }; + + class BNodeIt : public Node { + friend class BpUGraphExtender; + const Graph* graph; + public: + + BNodeIt() { } + + BNodeIt(Invalid i) : Node(INVALID) { } + + explicit BNodeIt(const Graph& _graph) : graph(&_graph) { + graph->firstBNode(static_cast(*this)); + } + + BNodeIt(const Graph& _graph, const Node& node) + : Node(node), graph(&_graph) {} + + BNodeIt& operator++() { + graph->nextBNode(*this); + return *this; + } + }; + + class EdgeIt : public Edge { + friend class BpUGraphExtender; + const Graph* graph; + public: + + EdgeIt() { } + + EdgeIt(Invalid i) : Edge(INVALID) { } + + explicit EdgeIt(const Graph& _graph) : graph(&_graph) { + graph->first(static_cast(*this)); + } + + EdgeIt(const Graph& _graph, const Edge& edge) + : Edge(edge), graph(&_graph) { } + + EdgeIt& operator++() { + graph->next(*this); + return *this; + } + + }; + + class UEdgeIt : public UEdge { + friend class BpUGraphExtender; + const Graph* graph; + public: + + UEdgeIt() { } + + UEdgeIt(Invalid i) : UEdge(INVALID) { } + + explicit UEdgeIt(const Graph& _graph) : graph(&_graph) { + graph->first(static_cast(*this)); + } + + UEdgeIt(const Graph& _graph, const UEdge& edge) + : UEdge(edge), graph(&_graph) { } + + UEdgeIt& operator++() { + graph->next(*this); + return *this; + } + }; + + class OutEdgeIt : public Edge { + friend class BpUGraphExtender; + const Graph* graph; + public: + + OutEdgeIt() { } + + OutEdgeIt(Invalid i) : Edge(i) { } + + OutEdgeIt(const Graph& _graph, const Node& node) + : graph(&_graph) { + graph->firstOut(*this, node); + } + + OutEdgeIt(const Graph& _graph, const Edge& edge) + : Edge(edge), graph(&_graph) {} + + OutEdgeIt& operator++() { + graph->nextOut(*this); + return *this; + } + + }; + + + class InEdgeIt : public Edge { + friend class BpUGraphExtender; + const Graph* graph; + public: + + InEdgeIt() { } + + InEdgeIt(Invalid i) : Edge(i) { } + + InEdgeIt(const Graph& _graph, const Node& node) + : graph(&_graph) { + graph->firstIn(*this, node); + } + + InEdgeIt(const Graph& _graph, const Edge& edge) : + Edge(edge), graph(&_graph) {} + + InEdgeIt& operator++() { + graph->nextIn(*this); + return *this; + } + + }; + + /// \brief Base node of the iterator + /// + /// Returns the base node (ie. the source in this case) of the iterator + Node baseNode(const OutEdgeIt &e) const { + return Parent::source((Edge&)e); + } + /// \brief Running node of the iterator + /// + /// Returns the running node (ie. the target in this case) of the + /// iterator + Node runningNode(const OutEdgeIt &e) const { + return Parent::target((Edge&)e); + } + + /// \brief Base node of the iterator + /// + /// Returns the base node (ie. the target in this case) of the iterator + Node baseNode(const InEdgeIt &e) const { + return Parent::target((Edge&)e); + } + /// \brief Running node of the iterator + /// + /// Returns the running node (ie. the source in this case) of the + /// iterator + Node runningNode(const InEdgeIt &e) const { + return Parent::source((Edge&)e); + } + + class IncEdgeIt : public Parent::UEdge { + friend class BpUGraphExtender; + const Graph* graph; + bool direction; + public: + + IncEdgeIt() { } + + IncEdgeIt(Invalid i) : UEdge(i), direction(true) { } + + IncEdgeIt(const Graph& _graph, const Node &n) : graph(&_graph) { + graph->firstInc(*this, direction, n); + } + + IncEdgeIt(const Graph& _graph, const UEdge &ue, const Node &n) + : graph(&_graph), UEdge(ue) { + direction = (graph->source(ue) == n); + } + + IncEdgeIt& operator++() { + graph->nextInc(*this, direction); + return *this; + } + }; + + + /// Base node of the iterator + /// + /// Returns the base node of the iterator + Node baseNode(const IncEdgeIt &e) const { + return e.direction ? source(e) : target(e); + } + + /// Running node of the iterator + /// + /// Returns the running node of the iterator + Node runningNode(const IncEdgeIt &e) const { + return e.direction ? target(e) : source(e); + } + + template + class ANodeMap + : public IterableMapExtender > { + public: + typedef BpUGraphExtender Graph; + typedef IterableMapExtender > + Parent; + + ANodeMap(const Graph& _g) + : Parent(_g) {} + ANodeMap(const Graph& _g, const _Value& _v) + : Parent(_g, _v) {} + + ANodeMap& operator=(const ANodeMap& cmap) { + return operator=(cmap); + } + + + /// \brief Template assign operator. + /// + /// The given parameter should be conform to the ReadMap + /// concept and could be indiced by the current item set of + /// the ANodeMap. In this case the value for each item + /// is assigned by the value of the given ReadMap. + template + ANodeMap& operator=(const CMap& cmap) { + checkConcept, CMap>(); + const typename Parent::Graph* graph = Parent::getGraph(); + ANode it; + for (graph->first(it); it != INVALID; graph->next(it)) { + Parent::set(it, cmap[it]); + } + return *this; + } + + }; + + template + class BNodeMap + : public IterableMapExtender > { + public: + typedef BpUGraphExtender Graph; + typedef IterableMapExtender > + Parent; + + BNodeMap(const Graph& _g) + : Parent(_g) {} + BNodeMap(const Graph& _g, const _Value& _v) + : Parent(_g, _v) {} + + BNodeMap& operator=(const BNodeMap& cmap) { + return operator=(cmap); + } + + + /// \brief Template assign operator. + /// + /// The given parameter should be conform to the ReadMap + /// concept and could be indiced by the current item set of + /// the BNodeMap. In this case the value for each item + /// is assigned by the value of the given ReadMap. + template + BNodeMap& operator=(const CMap& cmap) { + checkConcept, CMap>(); + const typename Parent::Graph* graph = Parent::getGraph(); + BNode it; + for (graph->first(it); it != INVALID; graph->next(it)) { + Parent::set(it, cmap[it]); + } + return *this; + } + + }; + + protected: + + template + class NodeMapBase : public NodeNotifier::ObserverBase { + public: + typedef BpUGraphExtender Graph; + + typedef Node Key; + typedef _Value Value; + + /// The reference type of the map; + typedef typename BNodeMap<_Value>::Reference Reference; + /// The pointer type of the map; + typedef typename BNodeMap<_Value>::Pointer Pointer; + + /// The const value type of the map. + typedef const Value ConstValue; + /// The const reference type of the map; + typedef typename BNodeMap<_Value>::ConstReference ConstReference; + /// The pointer type of the map; + typedef typename BNodeMap<_Value>::ConstPointer ConstPointer; + + typedef True ReferenceMapTag; + + NodeMapBase(const Graph& _g) + : graph(&_g), bNodeMap(_g), aNodeMap(_g) { + NodeNotifier::ObserverBase::attach(_g.getNotifier(Node())); + } + NodeMapBase(const Graph& _g, const _Value& _v) + : graph(&_g), bNodeMap(_g, _v), + aNodeMap(_g, _v) { + NodeNotifier::ObserverBase::attach(_g.getNotifier(Node())); + } + + virtual ~NodeMapBase() { + if (NodeNotifier::ObserverBase::attached()) { + NodeNotifier::ObserverBase::detach(); + } + } + + ConstReference operator[](const Key& node) const { + if (Parent::aNode(node)) { + return aNodeMap[node]; + } else { + return bNodeMap[node]; + } + } + + Reference operator[](const Key& node) { + if (Parent::aNode(node)) { + return aNodeMap[node]; + } else { + return bNodeMap[node]; + } + } + + void set(const Key& node, const Value& value) { + if (Parent::aNode(node)) { + aNodeMap.set(node, value); + } else { + bNodeMap.set(node, value); + } + } + + protected: + + virtual void add(const Node&) {} + virtual void add(const std::vector&) {} + virtual void erase(const Node&) {} + virtual void erase(const std::vector&) {} + virtual void clear() {} + virtual void build() {} + + const Graph* getGraph() const { return graph; } + + private: + const Graph* graph; + BNodeMap<_Value> bNodeMap; + ANodeMap<_Value> aNodeMap; + }; + + public: + + template + class NodeMap + : public IterableMapExtender > { + public: + typedef BpUGraphExtender Graph; + typedef IterableMapExtender< NodeMapBase<_Value> > Parent; + + NodeMap(const Graph& _g) + : Parent(_g) {} + NodeMap(const Graph& _g, const _Value& _v) + : Parent(_g, _v) {} + + NodeMap& operator=(const NodeMap& cmap) { + return operator=(cmap); + } + + + /// \brief Template assign operator. + /// + /// The given parameter should be conform to the ReadMap + /// concept and could be indiced by the current item set of + /// the NodeMap. In this case the value for each item + /// is assigned by the value of the given ReadMap. + template + NodeMap& operator=(const CMap& cmap) { + checkConcept, CMap>(); + const typename Parent::Graph* graph = Parent::getGraph(); + Node it; + for (graph->first(it); it != INVALID; graph->next(it)) { + Parent::set(it, cmap[it]); + } + return *this; + } + + }; + + + + template + class EdgeMap + : public IterableMapExtender > { + public: + typedef BpUGraphExtender Graph; + typedef IterableMapExtender > Parent; + + EdgeMap(const Graph& _g) + : Parent(_g) {} + EdgeMap(const Graph& _g, const _Value& _v) + : Parent(_g, _v) {} + + EdgeMap& operator=(const EdgeMap& cmap) { + return operator=(cmap); + } + + template + EdgeMap& operator=(const CMap& cmap) { + checkConcept, CMap>(); + const typename Parent::Graph* graph = Parent::getGraph(); + Edge it; + for (graph->first(it); it != INVALID; graph->next(it)) { + Parent::set(it, cmap[it]); + } + return *this; + } + }; + + template + class UEdgeMap + : public IterableMapExtender > { + public: + typedef BpUGraphExtender Graph; + typedef IterableMapExtender > + Parent; + + UEdgeMap(const Graph& _g) + : Parent(_g) {} + UEdgeMap(const Graph& _g, const _Value& _v) + : Parent(_g, _v) {} + + UEdgeMap& operator=(const UEdgeMap& cmap) { + return operator=(cmap); + } + + template + UEdgeMap& operator=(const CMap& cmap) { + checkConcept, CMap>(); + const typename Parent::Graph* graph = Parent::getGraph(); + UEdge it; + for (graph->first(it); it != INVALID; graph->next(it)) { + Parent::set(it, cmap[it]); + } + return *this; + } + }; + + + Node addANode() { + Node node = Parent::addANode(); + getNotifier(ANode()).add(node); + getNotifier(Node()).add(node); + return node; + } + + Node addBNode() { + Node node = Parent::addBNode(); + getNotifier(BNode()).add(node); + getNotifier(Node()).add(node); + return node; + } + + UEdge addEdge(const Node& source, const Node& target) { + UEdge uedge = Parent::addEdge(source, target); + getNotifier(UEdge()).add(uedge); + + std::vector edges; + edges.push_back(direct(uedge, true)); + edges.push_back(direct(uedge, false)); + getNotifier(Edge()).add(edges); + + return uedge; + } + + void clear() { + getNotifier(Edge()).clear(); + getNotifier(UEdge()).clear(); + getNotifier(Node()).clear(); + getNotifier(BNode()).clear(); + getNotifier(ANode()).clear(); + Parent::clear(); + } + + void erase(const Node& node) { + UEdge uedge; + bool dir; + Parent::firstInc(uedge, dir, node); + while (uedge != INVALID ) { + erase(uedge); + Parent::firstInc(uedge, dir, node); + } + + getNotifier(Node()).erase(node); + Parent::erase(node); + } + + void erase(const UEdge& uedge) { + std::vector edges; + edges.push_back(direct(uedge, true)); + edges.push_back(direct(uedge, false)); + getNotifier(Edge()).erase(edges); + getNotifier(UEdge()).erase(uedge); + Parent::erase(uedge); + } + + + ~BpUGraphExtender() { + getNotifier(Edge()).clear(); + getNotifier(UEdge()).clear(); + getNotifier(Node()).clear(); + getNotifier(BNode()).clear(); + getNotifier(ANode()).clear(); + } + + }; }