klao@962: /* -*- C++ -*- klao@962: * klao@962: * src/lemon/undir_graph_extender.h - Part of LEMON, a generic C++ klao@962: * optimization library klao@962: * alpar@1164: * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi klao@962: * Kutatocsoport (Egervary Combinatorial Optimization Research Group, klao@962: * EGRES). klao@962: * klao@962: * Permission to use, modify and distribute this software is granted klao@962: * provided that this copyright notice appears in all copies. For klao@962: * precise terms see the accompanying LICENSE file. klao@962: * klao@962: * This software is provided "AS IS" with no warranty of any kind, klao@962: * express or implied, and with no claim as to its suitability for any klao@962: * purpose. klao@962: * klao@962: */ klao@962: klao@962: #ifndef LEMON_UNDIR_GRAPH_EXTENDER_H klao@962: #define LEMON_UNDIR_GRAPH_EXTENDER_H klao@962: klao@962: #include klao@962: klao@962: namespace lemon { klao@962: klao@962: template klao@962: class UndirGraphExtender : public _Base { klao@962: typedef _Base Parent; klao@962: typedef UndirGraphExtender Graph; klao@962: klao@962: public: klao@962: klao@962: typedef typename Parent::Edge UndirEdge; klao@962: typedef typename Parent::Node Node; klao@962: klao@962: class Edge : public UndirEdge { klao@978: friend class UndirGraphExtender; klao@962: klao@962: protected: klao@962: // FIXME: Marci use opposite logic in his graph wrappers. It would klao@962: // be reasonable to syncronize... klao@962: bool forward; klao@962: klao@962: public: klao@962: Edge() {} klao@1158: klao@1158: /// \brief Directed edge from undirected edge and a direction. klao@1158: /// klao@1158: /// This constructor is not a part of the concept interface of klao@1158: /// undirected graph, so please avoid using it if possible! klao@962: Edge(const UndirEdge &ue, bool _forward) : klao@1158: UndirEdge(ue), forward(_forward) {} klao@1158: klao@1158: /// \brief Directed edge from undirected edge and a source node. klao@1158: /// klao@1158: /// Constructs a directed edge from undirected edge and a source node. klao@1158: /// klao@1158: /// \note You have to specify the graph for this constructor. klao@1158: Edge(const Graph &g, const UndirEdge &ue, const Node &n) : klao@1158: UndirEdge(ue) { forward = (g.source(ue) == n); } klao@1158: klao@962: /// Invalid edge constructor klao@1053: Edge(Invalid i) : UndirEdge(i), forward(true) {} klao@962: klao@962: bool operator==(const Edge &that) const { klao@962: return forward==that.forward && UndirEdge(*this)==UndirEdge(that); klao@962: } klao@962: bool operator!=(const Edge &that) const { klao@962: return forward!=that.forward || UndirEdge(*this)!=UndirEdge(that); klao@962: } klao@962: bool operator<(const Edge &that) const { klao@962: return forward klao@1021: Node _dirSource(const E &e) const { alpar@986: return e.forward ? Parent::source(e) : Parent::target(e); klao@962: } klao@962: klao@1021: template klao@1021: Node _dirTarget(const E &e) const { klao@1021: return e.forward ? Parent::target(e) : Parent::source(e); klao@1021: } klao@1021: klao@1021: public: alpar@986: /// \todo Shouldn't the "source" of an undirected edge be called "aNode" klao@962: /// or something??? alpar@986: using Parent::source; klao@962: klao@1021: /// Source of the given Edge. klao@1021: Node source(const Edge &e) const { klao@1021: return _dirSource(e); klao@962: } klao@962: alpar@986: /// \todo Shouldn't the "target" of an undirected edge be called "bNode" klao@962: /// or something??? alpar@986: using Parent::target; klao@962: klao@1021: /// Target of the given Edge. klao@1021: Node target(const Edge &e) const { klao@1021: return _dirTarget(e); klao@1021: } klao@1021: klao@962: /// Returns whether the given directed edge is same orientation as the klao@962: /// corresponding undirected edge. klao@962: /// klao@962: /// \todo reference to the corresponding point of the undirected graph klao@962: /// concept. "What does the direction of an undirected edge mean?" klao@962: bool forward(const Edge &e) const { return e.forward; } klao@962: klao@1030: Node oppositeNode(const Node &n, const UndirEdge &e) const { alpar@986: if( n == Parent::source(e)) alpar@986: return Parent::target(e); alpar@986: else if( n == Parent::target(e)) alpar@986: return Parent::source(e); klao@962: else klao@962: return INVALID; klao@962: } klao@962: klao@1158: /// Directed edge from an undirected edge and a source node. klao@1158: /// klao@1158: /// Returns a (directed) Edge corresponding to the specified UndirEdge klao@1158: /// and source Node. klao@1158: /// klao@1158: ///\todo Do we need this? klao@1158: /// klao@1158: ///\todo Better name... klao@1158: Edge edgeWithSource(const UndirEdge &ue, const Node &s) const { klao@1158: return Edge(*this, eu, s); klao@1158: } klao@962: klao@962: using Parent::first; klao@962: void first(Edge &e) const { klao@962: Parent::first(e); klao@962: e.forward=true; klao@962: } klao@962: klao@962: using Parent::next; klao@962: void next(Edge &e) const { klao@962: if( e.forward ) { klao@962: e.forward = false; klao@962: } klao@962: else { klao@962: Parent::next(e); klao@962: e.forward = true; klao@962: } klao@962: } klao@962: klao@1021: klao@1021: protected: klao@1021: klao@1021: template klao@1021: void _dirFirstOut(E &e, const Node &n) const { klao@1060: Parent::firstIn(e,n); klao@962: if( UndirEdge(e) != INVALID ) { klao@1060: e.forward = false; klao@962: } klao@962: else { klao@1060: Parent::firstOut(e,n); klao@1060: e.forward = true; klao@962: } klao@962: } klao@1021: template klao@1021: void _dirFirstIn(E &e, const Node &n) const { klao@1060: Parent::firstOut(e,n); klao@962: if( UndirEdge(e) != INVALID ) { klao@1060: e.forward = false; klao@962: } klao@962: else { klao@1060: Parent::firstIn(e,n); klao@1060: e.forward = true; klao@962: } klao@962: } klao@962: klao@1021: template klao@1021: void _dirNextOut(E &e) const { klao@1060: if( ! e.forward ) { klao@1060: Node n = Parent::target(e); klao@1060: Parent::nextIn(e); klao@1060: if( UndirEdge(e) == INVALID ) { klao@1060: Parent::firstOut(e, n); klao@1060: e.forward = true; klao@1060: } klao@1060: } klao@1060: else { klao@1060: Parent::nextOut(e); klao@1060: } klao@1060: } klao@1060: template klao@1060: void _dirNextIn(E &e) const { klao@1060: if( ! e.forward ) { klao@1060: Node n = Parent::source(e); klao@962: Parent::nextOut(e); klao@962: if( UndirEdge(e) == INVALID ) { klao@1060: Parent::firstIn(e, n); klao@1060: e.forward = true; klao@962: } klao@962: } klao@962: else { klao@962: Parent::nextIn(e); klao@962: } klao@962: } klao@962: klao@1021: public: klao@1021: klao@1021: void firstOut(Edge &e, const Node &n) const { klao@1021: _dirFirstOut(e, n); klao@1021: } klao@1021: void firstIn(Edge &e, const Node &n) const { klao@1021: _dirFirstIn(e, n); klao@1021: } klao@1021: klao@1021: void nextOut(Edge &e) const { klao@1021: _dirNextOut(e); klao@1021: } klao@1021: void nextIn(Edge &e) const { klao@1021: _dirNextIn(e); klao@1021: } klao@1021: klao@962: // Miscellaneous stuff: klao@962: klao@962: /// \todo these methods (id, maxEdgeId) should be moved into separate klao@962: /// Extender klao@962: klao@1021: // using Parent::id; klao@1021: // Using "using" is not a good idea, cause it could be that there is klao@1021: // no "id" in Parent... klao@1021: klao@1021: int id(const Node &n) const { klao@1021: return Parent::id(n); klao@1021: } klao@1021: klao@1021: int id(const UndirEdge &e) const { klao@1021: return Parent::id(e); klao@1021: } klao@962: klao@962: int id(const Edge &e) const { deba@981: return 2 * Parent::id(e) + int(e.forward); klao@962: } klao@962: klao@1021: klao@1060: int maxId(Node) const { klao@1021: return Parent::maxId(Node()); klao@1021: } klao@1021: klao@1021: int maxId(Edge) const { deba@981: return 2 * Parent::maxId(typename Parent::Edge()) + 1; klao@962: } klao@1021: int maxId(UndirEdge) const { deba@981: return Parent::maxId(typename Parent::Edge()); klao@962: } klao@962: klao@1054: klao@1054: int edgeNum() const { klao@1054: return 2 * Parent::edgeNum(); klao@1054: } klao@1054: int undirEdgeNum() const { klao@1054: return Parent::edgeNum(); klao@1054: } klao@1054: klao@962: }; klao@962: klao@962: } klao@962: klao@962: #endif // LEMON_UNDIR_GRAPH_EXTENDER_H