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 deba@1791: class UndirGraphExtender : public _Base { deba@1791: typedef _Base Parent; deba@1791: typedef UndirGraphExtender Graph; deba@1791: deba@1791: public: deba@1791: deba@1791: typedef typename Parent::Edge UndirEdge; deba@1791: typedef typename Parent::Node Node; deba@1791: deba@1791: class Edge : public UndirEdge { deba@1791: friend class UndirGraphExtender; 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: deba@1791: Edge(const UndirEdge &ue, bool _forward) : deba@1791: UndirEdge(ue), forward(_forward) {} deba@1791: deba@1791: public: deba@1791: Edge() {} deba@1791: deba@1791: /// Invalid edge constructor deba@1791: Edge(Invalid i) : UndirEdge(i), forward(true) {} deba@1791: deba@1791: bool operator==(const Edge &that) const { deba@1791: return forward==that.forward && UndirEdge(*this)==UndirEdge(that); deba@1791: } deba@1791: bool operator!=(const Edge &that) const { deba@1791: return forward!=that.forward || UndirEdge(*this)!=UndirEdge(that); deba@1791: } deba@1791: bool operator<(const Edge &that) const { deba@1791: return forward> 1), bool(id & 1)); deba@1791: } deba@1791: deba@1791: UndirEdge undirEdgeFromId(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: deba@1791: UndirEdge fromId(int id, UndirEdge) const { deba@1791: return undirEdgeFromId(id); deba@1791: } deba@1791: deba@1791: deba@1791: Edge findEdge(Node source, Node target, Edge prev) const { deba@1791: if (prev == INVALID) { deba@1791: UndirEdge 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)) { deba@1791: UndirEdge 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 { deba@1791: UndirEdge 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: deba@1791: UndirEdge findUndirEdge(Node source, Node target, UndirEdge prev) const { deba@1791: if (prev == INVALID) { deba@1791: UndirEdge 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) { deba@1791: UndirEdge 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 { deba@1791: UndirEdge 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 deba@1820: class UndirBipartiteGraphExtender : public _Base { deba@1820: public: deba@1820: typedef _Base Parent; deba@1820: typedef UndirBipartiteGraphExtender Graph; deba@1820: deba@1820: typedef typename Parent::Node Node; deba@1820: typedef typename Parent::Edge UndirEdge; deba@1820: deba@1820: using Parent::first; deba@1820: using Parent::next; deba@1820: deba@1820: using Parent::id; deba@1820: deba@1820: Node source(const UndirEdge& edge) const { deba@1820: return upperNode(edge); deba@1820: } deba@1820: Node target(const UndirEdge& edge) const { deba@1820: return lowerNode(edge); deba@1820: } deba@1820: deba@1820: void firstInc(UndirEdge& 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); deba@1820: direction = static_cast(edge) == INVALID; deba@1820: } deba@1820: } deba@1820: void nextInc(UndirEdge& 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: deba@1820: int maxUndirEdgeId() const { deba@1820: return Parent::maxEdgeId(); deba@1820: } deba@1820: deba@1820: UndirEdge undirEdgeFromId(int id) const { deba@1820: return Parent::edgeFromId(id); deba@1820: } deba@1820: deba@1820: class Edge : public UndirEdge { deba@1820: friend class UndirBipartiteGraphExtender; deba@1820: protected: deba@1820: bool forward; deba@1820: deba@1820: Edge(const UndirEdge& edge, bool _forward) deba@1820: : UndirEdge(edge), forward(_forward) {} deba@1820: deba@1820: public: deba@1820: Edge() {} deba@1820: Edge (Invalid) : UndirEdge(INVALID), forward(true) {} deba@1820: bool operator==(const Edge& i) const { deba@1820: return UndirEdge::operator==(i) && forward == i.forward; deba@1820: } deba@1820: bool operator!=(const Edge& i) const { deba@1820: return UndirEdge::operator!=(i) || forward != i.forward; deba@1820: } deba@1820: bool operator<(const Edge& i) const { deba@1820: return UndirEdge::operator<(i) || deba@1820: (!(i.forward(edge)); deba@1820: edge.forward = true; deba@1820: } deba@1820: deba@1820: void next(Edge& edge) const { deba@1820: if (!edge.forward) { deba@1820: 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); deba@1820: 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); deba@1868: 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); deba@1820: 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); deba@1868: 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: deba@1820: Edge direct(const UndirEdge& edge, const Node& node) const { deba@1820: return Edge(edge, node == Parent::source(edge)); deba@1820: } deba@1820: deba@1820: Edge direct(const UndirEdge& edge, bool direction) const { deba@1820: return Edge(edge, direction); deba@1820: } deba@1820: deba@1820: Node oppositeNode(const UndirEdge& 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 { deba@1820: return Edge(Parent::fromId(id >> 1, UndirEdge()), (id & 1) == 0); deba@1820: } deba@1820: int maxEdgeId() const { deba@1820: return (Parent::maxId(UndirEdge()) << 1) + 1; deba@1820: } deba@1820: deba@1820: class UpperNode : public Node { deba@1820: friend class UndirBipartiteGraphExtender; 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 { deba@1820: friend class UndirBipartiteGraphExtender; 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: } deba@1820: int maxId(UndirEdge) const { deba@1820: return maxUndirEdgeId(); 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: } deba@1820: UndirEdge fromId(int id, UndirEdge) const { deba@1820: return undirEdgeFromId(id); deba@1820: } deba@1820: deba@1820: }; deba@1820: deba@1791: } deba@1791: deba@1791: #endif // LEMON_UNDIR_GRAPH_EXTENDER_H