deba@1791: /* -*- C++ -*- deba@1791: * lemon/graph_extender.h - Part of LEMON, a generic C++ optimization library deba@1791: * alpar@1875: * Copyright (C) 2006 Egervary Jeno Kombinatorikus Optimalizalasi deba@1791: * Kutatocsoport (Egervary Research Group on Combinatorial Optimization, deba@1791: * EGRES). deba@1791: * deba@1791: * Permission to use, modify and distribute this software is granted deba@1791: * provided that this copyright notice appears in all copies. For deba@1791: * precise terms see the accompanying LICENSE file. deba@1791: * deba@1791: * This software is provided "AS IS" with no warranty of any kind, deba@1791: * express or implied, and with no claim as to its suitability for any deba@1791: * purpose. deba@1791: * deba@1791: */ deba@1791: deba@1791: #ifndef LEMON_GRAPH_EXTENDER_H deba@1791: #define LEMON_GRAPH_EXTENDER_H deba@1791: deba@1791: #include deba@1820: #include deba@1791: deba@1791: namespace lemon { deba@1791: deba@1791: template deba@1791: class GraphExtender : public _Base { deba@1791: public: deba@1791: deba@1791: typedef _Base Parent; deba@1791: typedef GraphExtender Graph; deba@1791: deba@1791: typedef typename Parent::Node Node; deba@1791: typedef typename Parent::Edge Edge; deba@1791: deba@1791: int maxId(Node) const { deba@1791: return Parent::maxNodeId(); deba@1791: } deba@1791: deba@1791: int maxId(Edge) const { deba@1791: return Parent::maxEdgeId(); deba@1791: } deba@1791: deba@1791: Node fromId(int id, Node) const { deba@1791: return Parent::nodeFromId(id); deba@1791: } deba@1791: deba@1791: Edge fromId(int id, Edge) const { deba@1791: return Parent::edgeFromId(id); deba@1791: } deba@1791: deba@1791: Node oppositeNode(const Node &n, const Edge &e) const { deba@1791: if (n == Parent::source(e)) deba@1791: return Parent::target(e); deba@1791: else if(n==Parent::target(e)) deba@1791: return Parent::source(e); deba@1791: else deba@1791: return INVALID; deba@1791: } deba@1791: deba@1791: }; deba@1791: deba@1791: template klao@1909: class UGraphExtender : public _Base { deba@1791: typedef _Base Parent; klao@1909: typedef UGraphExtender Graph; deba@1791: deba@1791: public: deba@1791: klao@1909: typedef typename Parent::Edge UEdge; deba@1791: typedef typename Parent::Node Node; deba@1791: klao@1909: class Edge : public UEdge { klao@1909: friend class UGraphExtender; deba@1791: deba@1791: protected: deba@1791: // FIXME: Marci use opposite logic in his graph adaptors. It would deba@1791: // be reasonable to syncronize... deba@1791: bool forward; deba@1791: klao@1909: Edge(const UEdge &ue, bool _forward) : klao@1909: UEdge(ue), forward(_forward) {} deba@1791: deba@1791: public: deba@1791: Edge() {} deba@1791: deba@1791: /// Invalid edge constructor klao@1909: Edge(Invalid i) : UEdge(i), forward(true) {} deba@1791: deba@1791: bool operator==(const Edge &that) const { klao@1909: return forward==that.forward && UEdge(*this)==UEdge(that); deba@1791: } deba@1791: bool operator!=(const Edge &that) const { klao@1909: return forward!=that.forward || UEdge(*this)!=UEdge(that); deba@1791: } deba@1791: bool operator<(const Edge &that) const { deba@1791: return forward> 1), bool(id & 1)); deba@1791: } deba@1791: klao@1909: UEdge uEdgeFromId(int id) const { deba@1791: return Parent::edgeFromId(id >> 1); deba@1791: } deba@1791: deba@1791: Node fromId(int id, Node) const { deba@1791: return nodeFromId(id); deba@1791: } deba@1791: deba@1791: Edge fromId(int id, Edge) const { deba@1791: return edgeFromId(id); deba@1791: } deba@1791: klao@1909: UEdge fromId(int id, UEdge) const { klao@1909: return uEdgeFromId(id); deba@1791: } deba@1791: deba@1791: deba@1791: Edge findEdge(Node source, Node target, Edge prev) const { deba@1791: if (prev == INVALID) { klao@1909: UEdge edge = Parent::findEdge(source, target); deba@1791: if (edge != INVALID) return direct(edge, true); deba@1791: edge = Parent::findEdge(target, source); deba@1791: if (edge != INVALID) return direct(edge, false); deba@1791: } else if (direction(prev)) { klao@1909: UEdge edge = Parent::findEdge(source, target, prev); deba@1791: if (edge != INVALID) return direct(edge, true); deba@1791: edge = Parent::findEdge(target, source); deba@1791: if (edge != INVALID) return direct(edge, false); deba@1791: } else { klao@1909: UEdge edge = Parent::findEdge(target, source, prev); deba@1791: if (edge != INVALID) return direct(edge, false); deba@1791: } deba@1791: return INVALID; deba@1791: } deba@1791: klao@1909: UEdge findUEdge(Node source, Node target, UEdge prev) const { deba@1791: if (prev == INVALID) { klao@1909: UEdge edge = Parent::findEdge(source, target); deba@1791: if (edge != INVALID) return edge; deba@1791: edge = Parent::findEdge(target, source); deba@1791: if (edge != INVALID) return edge; deba@1791: } else if (Parent::source(prev) == source) { klao@1909: UEdge edge = Parent::findEdge(source, target, prev); deba@1791: if (edge != INVALID) return edge; deba@1791: edge = Parent::findEdge(target, source); deba@1791: if (edge != INVALID) return edge; deba@1791: } else { klao@1909: UEdge edge = Parent::findEdge(target, source, prev); deba@1791: if (edge != INVALID) return edge; deba@1791: } deba@1791: return INVALID; deba@1791: } deba@1791: deba@1791: }; deba@1791: deba@1820: deba@1820: template klao@1909: class UBipartiteGraphExtender : public _Base { deba@1820: public: deba@1820: typedef _Base Parent; klao@1909: typedef UBipartiteGraphExtender Graph; deba@1820: deba@1820: typedef typename Parent::Node Node; klao@1909: typedef typename Parent::Edge UEdge; deba@1820: deba@1820: using Parent::first; deba@1820: using Parent::next; deba@1820: deba@1820: using Parent::id; deba@1820: klao@1909: Node source(const UEdge& edge) const { deba@1820: return upperNode(edge); deba@1820: } klao@1909: Node target(const UEdge& edge) const { deba@1820: return lowerNode(edge); deba@1820: } deba@1820: klao@1909: void firstInc(UEdge& edge, bool& direction, const Node& node) const { deba@1820: if (Parent::upper(node)) { deba@1820: Parent::firstDown(edge, node); deba@1820: direction = true; deba@1820: } else { deba@1820: Parent::firstUp(edge, node); klao@1909: direction = static_cast(edge) == INVALID; deba@1820: } deba@1820: } klao@1909: void nextInc(UEdge& edge, bool& direction) const { deba@1820: if (direction) { deba@1820: Parent::nextDown(edge); deba@1820: } else { deba@1820: Parent::nextUp(edge); deba@1820: if (edge == INVALID) direction = true; deba@1820: } deba@1820: } deba@1820: klao@1909: int maxUEdgeId() const { deba@1820: return Parent::maxEdgeId(); deba@1820: } deba@1820: klao@1909: UEdge uEdgeFromId(int id) const { deba@1820: return Parent::edgeFromId(id); deba@1820: } deba@1820: klao@1909: class Edge : public UEdge { klao@1909: friend class UBipartiteGraphExtender; deba@1820: protected: deba@1820: bool forward; deba@1820: klao@1909: Edge(const UEdge& edge, bool _forward) klao@1909: : UEdge(edge), forward(_forward) {} deba@1820: deba@1820: public: deba@1820: Edge() {} klao@1909: Edge (Invalid) : UEdge(INVALID), forward(true) {} deba@1820: bool operator==(const Edge& i) const { klao@1909: return UEdge::operator==(i) && forward == i.forward; deba@1820: } deba@1820: bool operator!=(const Edge& i) const { klao@1909: return UEdge::operator!=(i) || forward != i.forward; deba@1820: } deba@1820: bool operator<(const Edge& i) const { klao@1909: return UEdge::operator<(i) || klao@1909: (!(i.forward(edge)); deba@1820: edge.forward = true; deba@1820: } deba@1820: deba@1820: void next(Edge& edge) const { deba@1820: if (!edge.forward) { klao@1909: Parent::next(static_cast(edge)); deba@1820: } deba@1820: edge.forward = !edge.forward; deba@1820: } deba@1820: deba@1820: void firstOut(Edge& edge, const Node& node) const { deba@1820: if (Parent::upper(node)) { deba@1820: Parent::firstDown(edge, node); deba@1820: edge.forward = true; deba@1820: } else { deba@1820: Parent::firstUp(edge, node); klao@1909: edge.forward = static_cast(edge) == INVALID; deba@1820: } deba@1820: } deba@1820: void nextOut(Edge& edge) const { deba@1820: if (edge.forward) { deba@1820: Parent::nextDown(edge); deba@1820: } else { deba@1820: Parent::nextUp(edge); klao@1909: edge.forward = static_cast(edge) == INVALID; deba@1820: } deba@1820: } deba@1820: deba@1820: void firstIn(Edge& edge, const Node& node) const { deba@1820: if (Parent::lower(node)) { deba@1820: Parent::firstUp(edge, node); deba@1820: edge.forward = true; deba@1820: } else { deba@1820: Parent::firstDown(edge, node); klao@1909: edge.forward = static_cast(edge) == INVALID; deba@1820: } deba@1820: } deba@1820: void nextIn(Edge& edge) const { deba@1820: if (edge.forward) { deba@1820: Parent::nextUp(edge); deba@1820: } else { deba@1820: Parent::nextDown(edge); klao@1909: edge.forward = static_cast(edge) == INVALID; deba@1820: } deba@1820: } deba@1820: deba@1820: Node source(const Edge& edge) const { deba@1820: return edge.forward ? Parent::upperNode(edge) : Parent::lowerNode(edge); deba@1820: } deba@1820: Node target(const Edge& edge) const { deba@1820: return edge.forward ? Parent::lowerNode(edge) : Parent::upperNode(edge); deba@1820: } deba@1820: deba@1820: bool direction(const Edge& edge) const { deba@1820: return edge.forward; deba@1820: } deba@1820: klao@1909: Edge direct(const UEdge& edge, const Node& node) const { deba@1820: return Edge(edge, node == Parent::source(edge)); deba@1820: } deba@1820: klao@1909: Edge direct(const UEdge& edge, bool direction) const { deba@1820: return Edge(edge, direction); deba@1820: } deba@1820: klao@1909: Node oppositeNode(const UEdge& edge, const Node& node) const { deba@1820: return source(edge) == node ? deba@1820: target(edge) : source(edge); deba@1820: } deba@1820: deba@1820: Edge oppositeEdge(const Edge& edge) const { deba@1820: return Edge(edge, !edge.forward); deba@1820: } deba@1820: deba@1820: int id(const Edge& edge) const { deba@1820: return (Parent::id(edge) << 1) + (edge.forward ? 0 : 1); deba@1820: } deba@1820: Edge edgeFromId(int id) const { klao@1909: return Edge(Parent::fromId(id >> 1, UEdge()), (id & 1) == 0); deba@1820: } deba@1820: int maxEdgeId() const { klao@1909: return (Parent::maxId(UEdge()) << 1) + 1; deba@1820: } deba@1820: deba@1820: class UpperNode : public Node { klao@1909: friend class UBipartiteGraphExtender; deba@1820: public: deba@1820: UpperNode() {} deba@1820: UpperNode(const Node& node) : Node(node) { deba@1820: LEMON_ASSERT(Parent::upper(node) || node == INVALID, deba@1820: typename Parent::NodeSetError()); deba@1820: } deba@1820: UpperNode(Invalid) : Node(INVALID) {} deba@1820: }; deba@1820: deba@1820: void first(UpperNode& node) const { deba@1820: Parent::firstUpper(static_cast(node)); deba@1820: } deba@1820: void next(UpperNode& node) const { deba@1820: Parent::nextUpper(static_cast(node)); deba@1820: } deba@1820: deba@1820: int id(const UpperNode& node) const { deba@1820: return Parent::upperId(node); deba@1820: } deba@1820: deba@1820: class LowerNode : public Node { klao@1909: friend class UBipartiteGraphExtender; deba@1820: public: deba@1820: LowerNode() {} deba@1820: LowerNode(const Node& node) : Node(node) { deba@1820: LEMON_ASSERT(Parent::lower(node) || node == INVALID, deba@1820: typename Parent::NodeSetError()); deba@1820: } deba@1820: LowerNode(Invalid) : Node(INVALID) {} deba@1820: }; deba@1820: deba@1820: void first(LowerNode& node) const { deba@1820: Parent::firstLower(static_cast(node)); deba@1820: } deba@1820: void next(LowerNode& node) const { deba@1820: Parent::nextLower(static_cast(node)); deba@1820: } deba@1820: deba@1820: int id(const LowerNode& node) const { deba@1820: return Parent::upperId(node); deba@1820: } deba@1820: deba@1820: deba@1820: deba@1820: int maxId(Node) const { deba@1820: return Parent::maxNodeId(); deba@1820: } deba@1820: int maxId(LowerNode) const { deba@1820: return Parent::maxLowerId(); deba@1820: } deba@1820: int maxId(UpperNode) const { deba@1820: return Parent::maxUpperId(); deba@1820: } deba@1820: int maxId(Edge) const { deba@1820: return maxEdgeId(); deba@1820: } klao@1909: int maxId(UEdge) const { klao@1909: return maxUEdgeId(); deba@1820: } deba@1820: deba@1820: deba@1820: Node fromId(int id, Node) const { deba@1820: return Parent::nodeFromId(id); deba@1820: } deba@1820: UpperNode fromId(int id, UpperNode) const { deba@1820: return Parent::fromUpperId(id); deba@1820: } deba@1820: LowerNode fromId(int id, LowerNode) const { deba@1820: return Parent::fromLowerId(id); deba@1820: } deba@1820: Edge fromId(int id, Edge) const { deba@1820: return edgeFromId(id); deba@1820: } klao@1909: UEdge fromId(int id, UEdge) const { klao@1909: return uEdgeFromId(id); deba@1820: } deba@1820: deba@1820: }; deba@1820: deba@1791: } deba@1791: deba@1791: #endif // LEMON_UNDIR_GRAPH_EXTENDER_H