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 <lemon/invalid.h>
klao@962: 
klao@962: namespace lemon {
klao@962: 
klao@962:   template <typename _Base>
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<that.forward ||
klao@962: 	  (!(that.forward<forward) && UndirEdge(*this)<UndirEdge(that));
klao@962:       }
klao@962:     };
klao@962: 
klao@962: 
klao@1158:     /// \brief Edge of opposite direction.
klao@962:     ///
klao@1158:     /// Returns the Edge of opposite direction.
klao@962:     Edge opposite(const Edge &e) const {
klao@962:       return Edge(e,!e.forward);
klao@962:     }
klao@962: 
klao@1021:   protected:
klao@1021: 
klao@1021:     template <typename E>
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 <typename E>
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 {
deba@1189:       return Edge(*this, ue, 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 <typename E>
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 <typename E>
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 <typename E>
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 <typename E>
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