/* -*- C++ -*- * * This file is a part of LEMON, a generic C++ optimization library * * Copyright (C) 2003-2007 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport * (Egervary Research Group on Combinatorial Optimization, EGRES). * * Permission to use, modify and distribute this software is granted * provided that this copyright notice appears in all copies. For * precise terms see the accompanying LICENSE file. * * This software is provided "AS IS" with no warranty of any kind, * express or implied, and with no claim as to its suitability for any * purpose. * */ #ifndef LEMON_BITS_BASE_EXTENDER_H #define LEMON_BITS_BASE_EXTENDER_H #include #include #include #include #include #include ///\ingroup digraphbits ///\file ///\brief Extenders for the digraph types namespace lemon { /// \ingroup digraphbits /// /// \brief BaseDigraph to BaseGraph extender template class UndirDigraphExtender : public Base { public: typedef Base Parent; typedef typename Parent::Arc Edge; typedef typename Parent::Node Node; typedef True UndirectedTag; class Arc : public Edge { friend class UndirDigraphExtender; protected: bool forward; Arc(const Edge &ue, bool _forward) : Edge(ue), forward(_forward) {} public: Arc() {} /// Invalid arc constructor Arc(Invalid i) : Edge(i), forward(true) {} bool operator==(const Arc &that) const { return forward==that.forward && Edge(*this)==Edge(that); } bool operator!=(const Arc &that) const { return forward!=that.forward || Edge(*this)!=Edge(that); } bool operator<(const Arc &that) const { return forward> 1), bool(ix & 1)); } Edge edgeFromId(int ix) const { return Parent::arcFromId(ix); } int id(const Node &n) const { return Parent::id(n); } int id(const Edge &e) const { return Parent::id(e); } int id(const Arc &e) const { return 2 * Parent::id(e) + int(e.forward); } int maxNodeId() const { return Parent::maxNodeId(); } int maxArcId() const { return 2 * Parent::maxArcId() + 1; } int maxEdgeId() const { return Parent::maxArcId(); } int arcNum() const { return 2 * Parent::arcNum(); } int edgeNum() const { return Parent::arcNum(); } Arc findArc(Node s, Node t, Arc p = INVALID) const { if (p == INVALID) { Edge arc = Parent::findArc(s, t); if (arc != INVALID) return direct(arc, true); arc = Parent::findArc(t, s); if (arc != INVALID) return direct(arc, false); } else if (direction(p)) { Edge arc = Parent::findArc(s, t, p); if (arc != INVALID) return direct(arc, true); arc = Parent::findArc(t, s); if (arc != INVALID) return direct(arc, false); } else { Edge arc = Parent::findArc(t, s, p); if (arc != INVALID) return direct(arc, false); } return INVALID; } Edge findEdge(Node s, Node t, Edge p = INVALID) const { if (s != t) { if (p == INVALID) { Edge arc = Parent::findArc(s, t); if (arc != INVALID) return arc; arc = Parent::findArc(t, s); if (arc != INVALID) return arc; } else if (Parent::s(p) == s) { Edge arc = Parent::findArc(s, t, p); if (arc != INVALID) return arc; arc = Parent::findArc(t, s); if (arc != INVALID) return arc; } else { Edge arc = Parent::findArc(t, s, p); if (arc != INVALID) return arc; } } else { return Parent::findArc(s, t, p); } return INVALID; } }; template class BidirBpGraphExtender : public Base { public: typedef Base Parent; typedef BidirBpGraphExtender Digraph; typedef typename Parent::Node Node; typedef typename Parent::Edge Edge; using Parent::first; using Parent::next; using Parent::id; class Red : public Node { friend class BidirBpGraphExtender; public: Red() {} Red(const Node& node) : Node(node) { LEMON_ASSERT(Parent::red(node) || node == INVALID, typename Parent::NodeSetError()); } Red& operator=(const Node& node) { LEMON_ASSERT(Parent::red(node) || node == INVALID, typename Parent::NodeSetError()); Node::operator=(node); return *this; } Red(Invalid) : Node(INVALID) {} Red& operator=(Invalid) { Node::operator=(INVALID); return *this; } }; void first(Red& node) const { Parent::firstRed(static_cast(node)); } void next(Red& node) const { Parent::nextRed(static_cast(node)); } int id(const Red& node) const { return Parent::redId(node); } class Blue : public Node { friend class BidirBpGraphExtender; public: Blue() {} Blue(const Node& node) : Node(node) { LEMON_ASSERT(Parent::blue(node) || node == INVALID, typename Parent::NodeSetError()); } Blue& operator=(const Node& node) { LEMON_ASSERT(Parent::blue(node) || node == INVALID, typename Parent::NodeSetError()); Node::operator=(node); return *this; } Blue(Invalid) : Node(INVALID) {} Blue& operator=(Invalid) { Node::operator=(INVALID); return *this; } }; void first(Blue& node) const { Parent::firstBlue(static_cast(node)); } void next(Blue& node) const { Parent::nextBlue(static_cast(node)); } int id(const Blue& node) const { return Parent::redId(node); } Node source(const Edge& arc) const { return red(arc); } Node target(const Edge& arc) const { return blue(arc); } void firstInc(Edge& arc, bool& dir, const Node& node) const { if (Parent::red(node)) { Parent::firstFromRed(arc, node); dir = true; } else { Parent::firstFromBlue(arc, node); dir = static_cast(arc) == INVALID; } } void nextInc(Edge& arc, bool& dir) const { if (dir) { Parent::nextFromRed(arc); } else { Parent::nextFromBlue(arc); if (arc == INVALID) dir = true; } } class Arc : public Edge { friend class BidirBpGraphExtender; protected: bool forward; Arc(const Edge& arc, bool _forward) : Edge(arc), forward(_forward) {} public: Arc() {} Arc (Invalid) : Edge(INVALID), forward(true) {} bool operator==(const Arc& i) const { return Edge::operator==(i) && forward == i.forward; } bool operator!=(const Arc& i) const { return Edge::operator!=(i) || forward != i.forward; } bool operator<(const Arc& i) const { return Edge::operator<(i) || (!(i.forward(arc)); arc.forward = true; } void next(Arc& arc) const { if (!arc.forward) { Parent::next(static_cast(arc)); } arc.forward = !arc.forward; } void firstOut(Arc& arc, const Node& node) const { if (Parent::red(node)) { Parent::firstFromRed(arc, node); arc.forward = true; } else { Parent::firstFromBlue(arc, node); arc.forward = static_cast(arc) == INVALID; } } void nextOut(Arc& arc) const { if (arc.forward) { Parent::nextFromRed(arc); } else { Parent::nextFromBlue(arc); arc.forward = static_cast(arc) == INVALID; } } void firstIn(Arc& arc, const Node& node) const { if (Parent::blue(node)) { Parent::firstFromBlue(arc, node); arc.forward = true; } else { Parent::firstFromRed(arc, node); arc.forward = static_cast(arc) == INVALID; } } void nextIn(Arc& arc) const { if (arc.forward) { Parent::nextFromBlue(arc); } else { Parent::nextFromRed(arc); arc.forward = static_cast(arc) == INVALID; } } Node source(const Arc& arc) const { return arc.forward ? Parent::red(arc) : Parent::blue(arc); } Node target(const Arc& arc) const { return arc.forward ? Parent::blue(arc) : Parent::red(arc); } int id(const Arc& arc) const { return (Parent::id(static_cast(arc)) << 1) + (arc.forward ? 0 : 1); } Arc arcFromId(int ix) const { return Arc(Parent::fromEdgeId(ix >> 1), (ix & 1) == 0); } int maxArcId() const { return (Parent::maxEdgeId() << 1) + 1; } bool direction(const Arc& arc) const { return arc.forward; } Arc direct(const Edge& arc, bool dir) const { return Arc(arc, dir); } int arcNum() const { return 2 * Parent::edgeNum(); } int edgeNum() const { return Parent::edgeNum(); } }; } #endif