lemon/bits/undir_graph_extender.h
author alpar
Tue, 08 Nov 2005 10:10:09 +0000
changeset 1779 f6cafba4dbf2
parent 1627 3fd1ba6e9872
permissions -rw-r--r--
Obsolete bug removed
klao@962
     1
/* -*- C++ -*-
klao@962
     2
 *
ladanyi@1435
     3
 * lemon/undir_graph_extender.h - Part of LEMON, a generic C++
klao@962
     4
 * optimization library
klao@962
     5
 *
alpar@1164
     6
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi
alpar@1359
     7
 * Kutatocsoport (Egervary Research Group on Combinatorial Optimization,
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:
alpar@1401
    41
      // FIXME: Marci use opposite logic in his graph adaptors. It would
klao@962
    42
      // be reasonable to syncronize...
klao@962
    43
      bool forward;
klao@962
    44
klao@962
    45
      Edge(const UndirEdge &ue, bool _forward) :
klao@1158
    46
        UndirEdge(ue), forward(_forward) {}
klao@1158
    47
deba@1627
    48
    public:
deba@1627
    49
      Edge() {}
klao@1158
    50
klao@962
    51
      /// Invalid edge constructor
klao@1053
    52
      Edge(Invalid i) : UndirEdge(i), forward(true) {}
klao@962
    53
klao@962
    54
      bool operator==(const Edge &that) const {
klao@962
    55
	return forward==that.forward && UndirEdge(*this)==UndirEdge(that);
klao@962
    56
      }
klao@962
    57
      bool operator!=(const Edge &that) const {
klao@962
    58
	return forward!=that.forward || UndirEdge(*this)!=UndirEdge(that);
klao@962
    59
      }
klao@962
    60
      bool operator<(const Edge &that) const {
klao@962
    61
	return forward<that.forward ||
klao@962
    62
	  (!(that.forward<forward) && UndirEdge(*this)<UndirEdge(that));
klao@962
    63
      }
klao@962
    64
    };
klao@962
    65
klao@962
    66
klao@1158
    67
    /// \brief Edge of opposite direction.
klao@962
    68
    ///
klao@1158
    69
    /// Returns the Edge of opposite direction.
deba@1627
    70
    Edge oppositeEdge(const Edge &e) const {
klao@962
    71
      return Edge(e,!e.forward);
klao@962
    72
    }
klao@962
    73
klao@1021
    74
  public:
alpar@986
    75
    /// \todo Shouldn't the "source" of an undirected edge be called "aNode"
klao@962
    76
    /// or something???
alpar@986
    77
    using Parent::source;
klao@962
    78
klao@1021
    79
    /// Source of the given Edge.
klao@1021
    80
    Node source(const Edge &e) const {
deba@1704
    81
      return e.forward ? Parent::source(e) : Parent::target(e);
klao@962
    82
    }
klao@962
    83
alpar@986
    84
    /// \todo Shouldn't the "target" of an undirected edge be called "bNode"
klao@962
    85
    /// or something???
alpar@986
    86
    using Parent::target;
klao@962
    87
klao@1021
    88
    /// Target of the given Edge.
klao@1021
    89
    Node target(const Edge &e) const {
deba@1704
    90
      return e.forward ? Parent::target(e) : Parent::source(e);
klao@1021
    91
    }
klao@1021
    92
klao@1030
    93
    Node oppositeNode(const Node &n, const UndirEdge &e) const {
alpar@986
    94
      if( n == Parent::source(e))
alpar@986
    95
	return Parent::target(e);
alpar@986
    96
      else if( n == Parent::target(e))
alpar@986
    97
	return Parent::source(e);
klao@962
    98
      else
klao@962
    99
	return INVALID;
klao@962
   100
    }
klao@962
   101
deba@1627
   102
    /// \brief Directed edge from an undirected edge and a source node.
klao@1158
   103
    ///
klao@1158
   104
    /// Returns a (directed) Edge corresponding to the specified UndirEdge
klao@1158
   105
    /// and source Node.
klao@1158
   106
    ///
deba@1627
   107
    Edge direct(const UndirEdge &ue, const Node &s) const {
deba@1627
   108
      return Edge(ue, s == source(ue));
deba@1627
   109
    }
deba@1627
   110
deba@1627
   111
    /// \brief Directed edge from an undirected edge.
klao@1158
   112
    ///
deba@1627
   113
    /// Returns a directed edge corresponding to the specified UndirEdge.
deba@1627
   114
    /// If the given bool is true the given undirected edge and the
deba@1627
   115
    /// returned edge have the same source node.
deba@1627
   116
    Edge direct(const UndirEdge &ue, bool d) const {
deba@1627
   117
      return Edge(ue, d);
klao@1158
   118
    }
klao@962
   119
deba@1627
   120
    /// Returns whether the given directed edge is same orientation as the
deba@1627
   121
    /// corresponding undirected edge.
deba@1627
   122
    ///
deba@1627
   123
    /// \todo reference to the corresponding point of the undirected graph
deba@1627
   124
    /// concept. "What does the direction of an undirected edge mean?"
deba@1627
   125
    bool direction(const Edge &e) const { return e.forward; }
deba@1627
   126
deba@1627
   127
klao@962
   128
    using Parent::first;
klao@962
   129
    void first(Edge &e) const {
klao@962
   130
      Parent::first(e);
klao@962
   131
      e.forward=true;
klao@962
   132
    }
klao@962
   133
klao@962
   134
    using Parent::next;
klao@962
   135
    void next(Edge &e) const {
klao@962
   136
      if( e.forward ) {
klao@962
   137
	e.forward = false;
klao@962
   138
      }
klao@962
   139
      else {
klao@962
   140
	Parent::next(e);
klao@962
   141
	e.forward = true;
klao@962
   142
      }
klao@962
   143
    }
klao@962
   144
deba@1704
   145
  public:
klao@1021
   146
deba@1704
   147
    void firstOut(Edge &e, const Node &n) const {
klao@1060
   148
      Parent::firstIn(e,n);
klao@962
   149
      if( UndirEdge(e) != INVALID ) {
klao@1060
   150
	e.forward = false;
klao@962
   151
      }
klao@962
   152
      else {
klao@1060
   153
	Parent::firstOut(e,n);
klao@1060
   154
	e.forward = true;
klao@962
   155
      }
klao@962
   156
    }
deba@1704
   157
    void nextOut(Edge &e) const {
klao@1060
   158
      if( ! e.forward ) {
klao@1060
   159
	Node n = Parent::target(e);
klao@1060
   160
	Parent::nextIn(e);
klao@1060
   161
	if( UndirEdge(e) == INVALID ) {
klao@1060
   162
	  Parent::firstOut(e, n);
klao@1060
   163
	  e.forward = true;
klao@1060
   164
	}
klao@1060
   165
      }
klao@1060
   166
      else {
klao@1060
   167
	Parent::nextOut(e);
klao@1060
   168
      }
klao@1060
   169
    }
deba@1704
   170
deba@1704
   171
    void firstIn(Edge &e, const Node &n) const {
deba@1704
   172
      Parent::firstOut(e,n);
deba@1704
   173
      if( UndirEdge(e) != INVALID ) {
deba@1704
   174
	e.forward = false;
deba@1704
   175
      }
deba@1704
   176
      else {
deba@1704
   177
	Parent::firstIn(e,n);
deba@1704
   178
	e.forward = true;
deba@1704
   179
      }
deba@1704
   180
    }
deba@1704
   181
    void nextIn(Edge &e) const {
klao@1060
   182
      if( ! e.forward ) {
klao@1060
   183
	Node n = Parent::source(e);
klao@962
   184
	Parent::nextOut(e);
klao@962
   185
	if( UndirEdge(e) == INVALID ) {
klao@1060
   186
	  Parent::firstIn(e, n);
klao@1060
   187
	  e.forward = true;
klao@962
   188
	}
klao@962
   189
      }
klao@962
   190
      else {
klao@962
   191
	Parent::nextIn(e);
klao@962
   192
      }
klao@962
   193
    }
klao@962
   194
deba@1704
   195
    void firstInc(UndirEdge &e, const Node &n) const {
deba@1704
   196
      Parent::firstOut(e, n);
deba@1704
   197
      if (e != INVALID) return;
deba@1704
   198
      Parent::firstIn(e, n);
klao@1021
   199
    }
deba@1704
   200
    void nextInc(UndirEdge &e, const Node &n) const {
deba@1704
   201
      if (Parent::source(e) == n) {
deba@1704
   202
	Parent::nextOut(e);
deba@1704
   203
	if (e != INVALID) return;
deba@1704
   204
	Parent::firstIn(e, n);
deba@1704
   205
      } else {
deba@1704
   206
	Parent::nextIn(e);
deba@1704
   207
      }
klao@1021
   208
    }
klao@1021
   209
deba@1704
   210
    void firstInc(UndirEdge &e, bool &d, const Node &n) const {
deba@1704
   211
      d = true;
deba@1704
   212
      Parent::firstOut(e, n);
deba@1704
   213
      if (e != INVALID) return;
deba@1704
   214
      d = false;
deba@1704
   215
      Parent::firstIn(e, n);
klao@1021
   216
    }
deba@1704
   217
    void nextInc(UndirEdge &e, bool &d) const {
deba@1704
   218
      if (d) {
deba@1704
   219
	Node s = Parent::source(e);
deba@1704
   220
	Parent::nextOut(e);
deba@1704
   221
	if (e != INVALID) return;
deba@1704
   222
	d = false;
deba@1704
   223
	Parent::firstIn(e, s);
deba@1704
   224
      } else {
deba@1704
   225
	Parent::nextIn(e);
deba@1704
   226
      }
klao@1021
   227
    }
klao@1021
   228
klao@962
   229
    // Miscellaneous stuff:
klao@962
   230
klao@962
   231
    /// \todo these methods (id, maxEdgeId) should be moved into separate
klao@962
   232
    /// Extender
klao@962
   233
klao@1021
   234
    // using Parent::id;
klao@1021
   235
    // Using "using" is not a good idea, cause it could be that there is
klao@1021
   236
    // no "id" in Parent...
klao@1021
   237
klao@1021
   238
    int id(const Node &n) const {
klao@1021
   239
      return Parent::id(n);
klao@1021
   240
    }
klao@1021
   241
klao@1021
   242
    int id(const UndirEdge &e) const {
klao@1021
   243
      return Parent::id(e);
klao@1021
   244
    }
klao@962
   245
klao@962
   246
    int id(const Edge &e) const {
deba@981
   247
      return 2 * Parent::id(e) + int(e.forward);
klao@962
   248
    }
klao@962
   249
klao@1021
   250
klao@1060
   251
    int maxId(Node) const {
klao@1021
   252
      return Parent::maxId(Node());
klao@1021
   253
    }
klao@1021
   254
klao@1021
   255
    int maxId(Edge) const {
deba@981
   256
      return 2 * Parent::maxId(typename Parent::Edge()) + 1;
klao@962
   257
    }
klao@1021
   258
    int maxId(UndirEdge) const {
deba@981
   259
      return Parent::maxId(typename Parent::Edge());
klao@962
   260
    }
klao@962
   261
klao@1054
   262
klao@1054
   263
    int edgeNum() const {
klao@1054
   264
      return 2 * Parent::edgeNum();
klao@1054
   265
    }
deba@1704
   266
klao@1054
   267
    int undirEdgeNum() const {
klao@1054
   268
      return Parent::edgeNum();
klao@1054
   269
    }
klao@1054
   270
deba@1704
   271
    Edge findEdge(Node source, Node target, Edge prev) const {
deba@1704
   272
      if (prev == INVALID) {
deba@1704
   273
	UndirEdge edge = Parent::findEdge(source, target);
deba@1704
   274
	if (edge != INVALID) return direct(edge, true);
deba@1704
   275
	edge = Parent::findEdge(target, source);
deba@1704
   276
	if (edge != INVALID) return direct(edge, false);
deba@1704
   277
      } else if (direction(prev)) {
deba@1704
   278
	UndirEdge edge = Parent::findEdge(source, target, prev);
deba@1704
   279
	if (edge != INVALID) return direct(edge, true);
deba@1704
   280
	edge = Parent::findEdge(target, source);
deba@1704
   281
	if (edge != INVALID) return direct(edge, false);	
deba@1704
   282
      } else {
deba@1704
   283
	UndirEdge edge = Parent::findEdge(target, source, prev);
deba@1704
   284
	if (edge != INVALID) return direct(edge, false);	      
deba@1704
   285
      }
deba@1704
   286
      return INVALID;
deba@1704
   287
    }
deba@1704
   288
deba@1704
   289
    UndirEdge findUndirEdge(Node source, Node target, UndirEdge prev) const {
deba@1704
   290
      if (prev == INVALID) {
deba@1704
   291
	UndirEdge edge = Parent::findEdge(source, target);
deba@1704
   292
	if (edge != INVALID) return edge;
deba@1704
   293
	edge = Parent::findEdge(target, source);
deba@1704
   294
	if (edge != INVALID) return edge;
deba@1704
   295
      } else if (Parent::source(prev) == source) {
deba@1704
   296
	UndirEdge edge = Parent::findEdge(source, target, prev);
deba@1704
   297
	if (edge != INVALID) return edge;
deba@1704
   298
	edge = Parent::findEdge(target, source);
deba@1704
   299
	if (edge != INVALID) return edge;	
deba@1704
   300
      } else {
deba@1704
   301
	UndirEdge edge = Parent::findEdge(target, source, prev);
deba@1704
   302
	if (edge != INVALID) return edge;	      
deba@1704
   303
      }
deba@1704
   304
      return INVALID;
deba@1704
   305
    }
deba@1704
   306
klao@962
   307
  };
klao@962
   308
klao@962
   309
}
klao@962
   310
klao@962
   311
#endif // LEMON_UNDIR_GRAPH_EXTENDER_H