src/lemon/undir_graph_extender.h
author alpar
Tue, 18 Jan 2005 12:02:27 +0000
changeset 1086 caa13d291528
parent 1054 6a62b1b4cf23
child 1158 29961fa390a3
permissions -rw-r--r--
In graphToEps(), nodes may have different shapes (circles or squares).
klao@962
     1
/* -*- C++ -*-
klao@962
     2
 *
klao@962
     3
 * src/lemon/undir_graph_extender.h - Part of LEMON, a generic C++
klao@962
     4
 * optimization library
klao@962
     5
 *
klao@962
     6
 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi
klao@962
     7
 * Kutatocsoport (Egervary Combinatorial Optimization Research Group,
klao@962
     8
 * EGRES).
klao@962
     9
 *
klao@962
    10
 * Permission to use, modify and distribute this software is granted
klao@962
    11
 * provided that this copyright notice appears in all copies. For
klao@962
    12
 * precise terms see the accompanying LICENSE file.
klao@962
    13
 *
klao@962
    14
 * This software is provided "AS IS" with no warranty of any kind,
klao@962
    15
 * express or implied, and with no claim as to its suitability for any
klao@962
    16
 * purpose.
klao@962
    17
 *
klao@962
    18
 */
klao@962
    19
klao@962
    20
#ifndef LEMON_UNDIR_GRAPH_EXTENDER_H
klao@962
    21
#define LEMON_UNDIR_GRAPH_EXTENDER_H
klao@962
    22
klao@962
    23
#include <lemon/invalid.h>
klao@962
    24
klao@962
    25
namespace lemon {
klao@962
    26
klao@962
    27
  template <typename _Base>
klao@962
    28
  class UndirGraphExtender : public _Base {
klao@962
    29
    typedef _Base Parent;
klao@962
    30
    typedef UndirGraphExtender Graph;
klao@962
    31
klao@962
    32
  public:
klao@962
    33
klao@962
    34
    typedef typename Parent::Edge UndirEdge;
klao@962
    35
    typedef typename Parent::Node Node;
klao@962
    36
klao@962
    37
    class Edge : public UndirEdge {
klao@978
    38
      friend class UndirGraphExtender;
klao@962
    39
klao@962
    40
    protected:
klao@962
    41
      // FIXME: Marci use opposite logic in his graph wrappers. It would
klao@962
    42
      // be reasonable to syncronize...
klao@962
    43
      bool forward;
klao@962
    44
klao@962
    45
    public:
klao@962
    46
      Edge() {}
klao@962
    47
      /// Construct a direct edge from undirect edge and a direction.
klao@962
    48
      Edge(const UndirEdge &ue, bool _forward) :
klao@962
    49
	UndirEdge(ue), forward(_forward) {}
klao@962
    50
      /// Invalid edge constructor
klao@1053
    51
      Edge(Invalid i) : UndirEdge(i), forward(true) {}
klao@962
    52
klao@962
    53
      bool operator==(const Edge &that) const {
klao@962
    54
	return forward==that.forward && UndirEdge(*this)==UndirEdge(that);
klao@962
    55
      }
klao@962
    56
      bool operator!=(const Edge &that) const {
klao@962
    57
	return forward!=that.forward || UndirEdge(*this)!=UndirEdge(that);
klao@962
    58
      }
klao@962
    59
      bool operator<(const Edge &that) const {
klao@962
    60
	return forward<that.forward ||
klao@962
    61
	  (!(that.forward<forward) && UndirEdge(*this)<UndirEdge(that));
klao@962
    62
      }
klao@962
    63
    };
klao@962
    64
klao@962
    65
klao@962
    66
    /// \brief Returns the Edge of opposite direction.
klao@962
    67
    ///
klao@962
    68
    /// \bug Is this a good name for this? Or "reverse" is better?
klao@962
    69
    Edge opposite(const Edge &e) const {
klao@962
    70
      return Edge(e,!e.forward);
klao@962
    71
    }
klao@962
    72
klao@1021
    73
  protected:
klao@1021
    74
klao@1021
    75
    template <typename E>
klao@1021
    76
    Node _dirSource(const E &e) const {
alpar@986
    77
      return e.forward ? Parent::source(e) : Parent::target(e);
klao@962
    78
    }
klao@962
    79
klao@1021
    80
    template <typename E>
klao@1021
    81
    Node _dirTarget(const E &e) const {
klao@1021
    82
      return e.forward ? Parent::target(e) : Parent::source(e);
klao@1021
    83
    }
klao@1021
    84
klao@1021
    85
  public:
alpar@986
    86
    /// \todo Shouldn't the "source" of an undirected edge be called "aNode"
klao@962
    87
    /// or something???
alpar@986
    88
    using Parent::source;
klao@962
    89
klao@1021
    90
    /// Source of the given Edge.
klao@1021
    91
    Node source(const Edge &e) const {
klao@1021
    92
      return _dirSource(e);
klao@962
    93
    }
klao@962
    94
alpar@986
    95
    /// \todo Shouldn't the "target" of an undirected edge be called "bNode"
klao@962
    96
    /// or something???
alpar@986
    97
    using Parent::target;
klao@962
    98
klao@1021
    99
    /// Target of the given Edge.
klao@1021
   100
    Node target(const Edge &e) const {
klao@1021
   101
      return _dirTarget(e);
klao@1021
   102
    }
klao@1021
   103
klao@962
   104
    /// Returns whether the given directed edge is same orientation as the
klao@962
   105
    /// corresponding undirected edge.
klao@962
   106
    ///
klao@962
   107
    /// \todo reference to the corresponding point of the undirected graph
klao@962
   108
    /// concept. "What does the direction of an undirected edge mean?"
klao@962
   109
    bool forward(const Edge &e) const { return e.forward; }
klao@962
   110
klao@1030
   111
    Node oppositeNode(const Node &n, const UndirEdge &e) const {
alpar@986
   112
      if( n == Parent::source(e))
alpar@986
   113
	return Parent::target(e);
alpar@986
   114
      else if( n == Parent::target(e))
alpar@986
   115
	return Parent::source(e);
klao@962
   116
      else
klao@962
   117
	return INVALID;
klao@962
   118
    }
klao@962
   119
klao@962
   120
klao@962
   121
    using Parent::first;
klao@962
   122
    void first(Edge &e) const {
klao@962
   123
      Parent::first(e);
klao@962
   124
      e.forward=true;
klao@962
   125
    }
klao@962
   126
klao@962
   127
    using Parent::next;
klao@962
   128
    void next(Edge &e) const {
klao@962
   129
      if( e.forward ) {
klao@962
   130
	e.forward = false;
klao@962
   131
      }
klao@962
   132
      else {
klao@962
   133
	Parent::next(e);
klao@962
   134
	e.forward = true;
klao@962
   135
      }
klao@962
   136
    }
klao@962
   137
klao@1021
   138
    
klao@1021
   139
  protected:
klao@1021
   140
klao@1021
   141
    template <typename E>
klao@1021
   142
    void _dirFirstOut(E &e, const Node &n) const {
klao@1060
   143
      Parent::firstIn(e,n);
klao@962
   144
      if( UndirEdge(e) != INVALID ) {
klao@1060
   145
	e.forward = false;
klao@962
   146
      }
klao@962
   147
      else {
klao@1060
   148
	Parent::firstOut(e,n);
klao@1060
   149
	e.forward = true;
klao@962
   150
      }
klao@962
   151
    }
klao@1021
   152
    template <typename E>
klao@1021
   153
    void _dirFirstIn(E &e, const Node &n) const {
klao@1060
   154
      Parent::firstOut(e,n);
klao@962
   155
      if( UndirEdge(e) != INVALID ) {
klao@1060
   156
	e.forward = false;
klao@962
   157
      }
klao@962
   158
      else {
klao@1060
   159
	Parent::firstIn(e,n);
klao@1060
   160
	e.forward = true;
klao@962
   161
      }
klao@962
   162
    }
klao@962
   163
klao@1021
   164
    template <typename E>
klao@1021
   165
    void _dirNextOut(E &e) const {
klao@1060
   166
      if( ! e.forward ) {
klao@1060
   167
	Node n = Parent::target(e);
klao@1060
   168
	Parent::nextIn(e);
klao@1060
   169
	if( UndirEdge(e) == INVALID ) {
klao@1060
   170
	  Parent::firstOut(e, n);
klao@1060
   171
	  e.forward = true;
klao@1060
   172
	}
klao@1060
   173
      }
klao@1060
   174
      else {
klao@1060
   175
	Parent::nextOut(e);
klao@1060
   176
      }
klao@1060
   177
    }
klao@1060
   178
    template <typename E>
klao@1060
   179
    void _dirNextIn(E &e) const {
klao@1060
   180
      if( ! e.forward ) {
klao@1060
   181
	Node n = Parent::source(e);
klao@962
   182
	Parent::nextOut(e);
klao@962
   183
	if( UndirEdge(e) == INVALID ) {
klao@1060
   184
	  Parent::firstIn(e, n);
klao@1060
   185
	  e.forward = true;
klao@962
   186
	}
klao@962
   187
      }
klao@962
   188
      else {
klao@962
   189
	Parent::nextIn(e);
klao@962
   190
      }
klao@962
   191
    }
klao@962
   192
klao@1021
   193
  public:
klao@1021
   194
klao@1021
   195
    void firstOut(Edge &e, const Node &n) const {
klao@1021
   196
      _dirFirstOut(e, n);
klao@1021
   197
    }
klao@1021
   198
    void firstIn(Edge &e, const Node &n) const {
klao@1021
   199
      _dirFirstIn(e, n);
klao@1021
   200
    }
klao@1021
   201
klao@1021
   202
    void nextOut(Edge &e) const {
klao@1021
   203
      _dirNextOut(e);
klao@1021
   204
    }
klao@1021
   205
    void nextIn(Edge &e) const {
klao@1021
   206
      _dirNextIn(e);
klao@1021
   207
    }
klao@1021
   208
klao@962
   209
    // Miscellaneous stuff:
klao@962
   210
klao@962
   211
    /// \todo these methods (id, maxEdgeId) should be moved into separate
klao@962
   212
    /// Extender
klao@962
   213
klao@1021
   214
    // using Parent::id;
klao@1021
   215
    // Using "using" is not a good idea, cause it could be that there is
klao@1021
   216
    // no "id" in Parent...
klao@1021
   217
klao@1021
   218
    int id(const Node &n) const {
klao@1021
   219
      return Parent::id(n);
klao@1021
   220
    }
klao@1021
   221
klao@1021
   222
    int id(const UndirEdge &e) const {
klao@1021
   223
      return Parent::id(e);
klao@1021
   224
    }
klao@962
   225
klao@962
   226
    int id(const Edge &e) const {
deba@981
   227
      return 2 * Parent::id(e) + int(e.forward);
klao@962
   228
    }
klao@962
   229
klao@1021
   230
klao@1060
   231
    int maxId(Node) const {
klao@1021
   232
      return Parent::maxId(Node());
klao@1021
   233
    }
klao@1021
   234
klao@1021
   235
    int maxId(Edge) const {
deba@981
   236
      return 2 * Parent::maxId(typename Parent::Edge()) + 1;
klao@962
   237
    }
klao@1021
   238
    int maxId(UndirEdge) const {
deba@981
   239
      return Parent::maxId(typename Parent::Edge());
klao@962
   240
    }
klao@962
   241
klao@1054
   242
klao@1054
   243
    int edgeNum() const {
klao@1054
   244
      return 2 * Parent::edgeNum();
klao@1054
   245
    }
klao@1054
   246
    int undirEdgeNum() const {
klao@1054
   247
      return Parent::edgeNum();
klao@1054
   248
    }
klao@1054
   249
klao@962
   250
  };
klao@962
   251
klao@962
   252
}
klao@962
   253
klao@962
   254
#endif // LEMON_UNDIR_GRAPH_EXTENDER_H