lemon/bits/undir_graph_extender.h
author alpar
Thu, 01 Sep 2005 20:35:30 +0000
changeset 1674 648aa2f33dc8
parent 1435 8e85e6bbefdf
child 1704 467d7927a901
permissions -rw-r--r--
Warning added on the usage of InDegMap/OutDegMap
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
  protected:
klao@1021
    75
klao@1021
    76
    template <typename E>
klao@1021
    77
    Node _dirSource(const E &e) const {
alpar@986
    78
      return e.forward ? Parent::source(e) : Parent::target(e);
klao@962
    79
    }
klao@962
    80
klao@1021
    81
    template <typename E>
klao@1021
    82
    Node _dirTarget(const E &e) const {
klao@1021
    83
      return e.forward ? Parent::target(e) : Parent::source(e);
klao@1021
    84
    }
klao@1021
    85
klao@1021
    86
  public:
alpar@986
    87
    /// \todo Shouldn't the "source" of an undirected edge be called "aNode"
klao@962
    88
    /// or something???
alpar@986
    89
    using Parent::source;
klao@962
    90
klao@1021
    91
    /// Source of the given Edge.
klao@1021
    92
    Node source(const Edge &e) const {
klao@1021
    93
      return _dirSource(e);
klao@962
    94
    }
klao@962
    95
alpar@986
    96
    /// \todo Shouldn't the "target" of an undirected edge be called "bNode"
klao@962
    97
    /// or something???
alpar@986
    98
    using Parent::target;
klao@962
    99
klao@1021
   100
    /// Target of the given Edge.
klao@1021
   101
    Node target(const Edge &e) const {
klao@1021
   102
      return _dirTarget(e);
klao@1021
   103
    }
klao@1021
   104
klao@1030
   105
    Node oppositeNode(const Node &n, const UndirEdge &e) const {
alpar@986
   106
      if( n == Parent::source(e))
alpar@986
   107
	return Parent::target(e);
alpar@986
   108
      else if( n == Parent::target(e))
alpar@986
   109
	return Parent::source(e);
klao@962
   110
      else
klao@962
   111
	return INVALID;
klao@962
   112
    }
klao@962
   113
deba@1627
   114
    /// \brief Directed edge from an undirected edge and a source node.
klao@1158
   115
    ///
klao@1158
   116
    /// Returns a (directed) Edge corresponding to the specified UndirEdge
klao@1158
   117
    /// and source Node.
klao@1158
   118
    ///
deba@1627
   119
    Edge direct(const UndirEdge &ue, const Node &s) const {
deba@1627
   120
      return Edge(ue, s == source(ue));
deba@1627
   121
    }
deba@1627
   122
deba@1627
   123
    /// \brief Directed edge from an undirected edge.
klao@1158
   124
    ///
deba@1627
   125
    /// Returns a directed edge corresponding to the specified UndirEdge.
deba@1627
   126
    /// If the given bool is true the given undirected edge and the
deba@1627
   127
    /// returned edge have the same source node.
deba@1627
   128
    Edge direct(const UndirEdge &ue, bool d) const {
deba@1627
   129
      return Edge(ue, d);
klao@1158
   130
    }
klao@962
   131
deba@1627
   132
    /// Returns whether the given directed edge is same orientation as the
deba@1627
   133
    /// corresponding undirected edge.
deba@1627
   134
    ///
deba@1627
   135
    /// \todo reference to the corresponding point of the undirected graph
deba@1627
   136
    /// concept. "What does the direction of an undirected edge mean?"
deba@1627
   137
    bool direction(const Edge &e) const { return e.forward; }
deba@1627
   138
deba@1627
   139
klao@962
   140
    using Parent::first;
klao@962
   141
    void first(Edge &e) const {
klao@962
   142
      Parent::first(e);
klao@962
   143
      e.forward=true;
klao@962
   144
    }
klao@962
   145
klao@962
   146
    using Parent::next;
klao@962
   147
    void next(Edge &e) const {
klao@962
   148
      if( e.forward ) {
klao@962
   149
	e.forward = false;
klao@962
   150
      }
klao@962
   151
      else {
klao@962
   152
	Parent::next(e);
klao@962
   153
	e.forward = true;
klao@962
   154
      }
klao@962
   155
    }
klao@962
   156
klao@1021
   157
    
klao@1021
   158
  protected:
klao@1021
   159
klao@1021
   160
    template <typename E>
klao@1021
   161
    void _dirFirstOut(E &e, const Node &n) const {
klao@1060
   162
      Parent::firstIn(e,n);
klao@962
   163
      if( UndirEdge(e) != INVALID ) {
klao@1060
   164
	e.forward = false;
klao@962
   165
      }
klao@962
   166
      else {
klao@1060
   167
	Parent::firstOut(e,n);
klao@1060
   168
	e.forward = true;
klao@962
   169
      }
klao@962
   170
    }
klao@1021
   171
    template <typename E>
klao@1021
   172
    void _dirFirstIn(E &e, const Node &n) const {
klao@1060
   173
      Parent::firstOut(e,n);
klao@962
   174
      if( UndirEdge(e) != INVALID ) {
klao@1060
   175
	e.forward = false;
klao@962
   176
      }
klao@962
   177
      else {
klao@1060
   178
	Parent::firstIn(e,n);
klao@1060
   179
	e.forward = true;
klao@962
   180
      }
klao@962
   181
    }
klao@962
   182
klao@1021
   183
    template <typename E>
klao@1021
   184
    void _dirNextOut(E &e) const {
klao@1060
   185
      if( ! e.forward ) {
klao@1060
   186
	Node n = Parent::target(e);
klao@1060
   187
	Parent::nextIn(e);
klao@1060
   188
	if( UndirEdge(e) == INVALID ) {
klao@1060
   189
	  Parent::firstOut(e, n);
klao@1060
   190
	  e.forward = true;
klao@1060
   191
	}
klao@1060
   192
      }
klao@1060
   193
      else {
klao@1060
   194
	Parent::nextOut(e);
klao@1060
   195
      }
klao@1060
   196
    }
klao@1060
   197
    template <typename E>
klao@1060
   198
    void _dirNextIn(E &e) const {
klao@1060
   199
      if( ! e.forward ) {
klao@1060
   200
	Node n = Parent::source(e);
klao@962
   201
	Parent::nextOut(e);
klao@962
   202
	if( UndirEdge(e) == INVALID ) {
klao@1060
   203
	  Parent::firstIn(e, n);
klao@1060
   204
	  e.forward = true;
klao@962
   205
	}
klao@962
   206
      }
klao@962
   207
      else {
klao@962
   208
	Parent::nextIn(e);
klao@962
   209
      }
klao@962
   210
    }
klao@962
   211
klao@1021
   212
  public:
klao@1021
   213
klao@1021
   214
    void firstOut(Edge &e, const Node &n) const {
klao@1021
   215
      _dirFirstOut(e, n);
klao@1021
   216
    }
klao@1021
   217
    void firstIn(Edge &e, const Node &n) const {
klao@1021
   218
      _dirFirstIn(e, n);
klao@1021
   219
    }
klao@1021
   220
klao@1021
   221
    void nextOut(Edge &e) const {
klao@1021
   222
      _dirNextOut(e);
klao@1021
   223
    }
klao@1021
   224
    void nextIn(Edge &e) const {
klao@1021
   225
      _dirNextIn(e);
klao@1021
   226
    }
klao@1021
   227
klao@962
   228
    // Miscellaneous stuff:
klao@962
   229
klao@962
   230
    /// \todo these methods (id, maxEdgeId) should be moved into separate
klao@962
   231
    /// Extender
klao@962
   232
klao@1021
   233
    // using Parent::id;
klao@1021
   234
    // Using "using" is not a good idea, cause it could be that there is
klao@1021
   235
    // no "id" in Parent...
klao@1021
   236
klao@1021
   237
    int id(const Node &n) const {
klao@1021
   238
      return Parent::id(n);
klao@1021
   239
    }
klao@1021
   240
klao@1021
   241
    int id(const UndirEdge &e) const {
klao@1021
   242
      return Parent::id(e);
klao@1021
   243
    }
klao@962
   244
klao@962
   245
    int id(const Edge &e) const {
deba@981
   246
      return 2 * Parent::id(e) + int(e.forward);
klao@962
   247
    }
klao@962
   248
klao@1021
   249
klao@1060
   250
    int maxId(Node) const {
klao@1021
   251
      return Parent::maxId(Node());
klao@1021
   252
    }
klao@1021
   253
klao@1021
   254
    int maxId(Edge) const {
deba@981
   255
      return 2 * Parent::maxId(typename Parent::Edge()) + 1;
klao@962
   256
    }
klao@1021
   257
    int maxId(UndirEdge) const {
deba@981
   258
      return Parent::maxId(typename Parent::Edge());
klao@962
   259
    }
klao@962
   260
klao@1054
   261
klao@1054
   262
    int edgeNum() const {
klao@1054
   263
      return 2 * Parent::edgeNum();
klao@1054
   264
    }
klao@1054
   265
    int undirEdgeNum() const {
klao@1054
   266
      return Parent::edgeNum();
klao@1054
   267
    }
klao@1054
   268
klao@962
   269
  };
klao@962
   270
klao@962
   271
}
klao@962
   272
klao@962
   273
#endif // LEMON_UNDIR_GRAPH_EXTENDER_H