src/lemon/undir_graph_extender.h
author deba
Wed, 15 Dec 2004 19:56:55 +0000
changeset 1037 3eaff8d04171
parent 1021 fd1d073b6557
child 1053 90f8696360b2
permissions -rw-r--r--
graph_io under construction
This is a working version, but needs more improvments.

todo:
documention + fix the file format
improve the exception system

add some possible asserts

tutorials
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@962
    51
      Edge(Invalid i) : UndirEdge(i), forward(false) {}
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@962
   143
      Parent::firstOut(e,n);
klao@962
   144
      if( UndirEdge(e) != INVALID ) {
klao@962
   145
	e.forward = true;
klao@962
   146
      }
klao@962
   147
      else {
klao@962
   148
	Parent::firstIn(e,n);
klao@962
   149
	e.forward = false;
klao@962
   150
      }
klao@962
   151
    }
klao@1021
   152
    template <typename E>
klao@1021
   153
    void _dirFirstIn(E &e, const Node &n) const {
klao@962
   154
      Parent::firstIn(e,n);
klao@962
   155
      if( UndirEdge(e) != INVALID ) {
klao@962
   156
	e.forward = true;
klao@962
   157
      }
klao@962
   158
      else {
klao@962
   159
	Parent::firstOut(e,n);
klao@962
   160
	e.forward = false;
klao@962
   161
      }
klao@962
   162
    }
klao@962
   163
klao@1021
   164
    template <typename E>
klao@1021
   165
    void _dirNextOut(E &e) const {
klao@962
   166
      if( e.forward ) {
klao@962
   167
	Parent::nextOut(e);
klao@962
   168
	if( UndirEdge(e) == INVALID ) {
alpar@986
   169
	  Parent::firstIn(e, Parent::source(e));
klao@962
   170
	  e.forward = false;
klao@962
   171
	}
klao@962
   172
      }
klao@962
   173
      else {
klao@962
   174
	Parent::nextIn(e);
klao@962
   175
      }
klao@962
   176
    }
klao@1021
   177
    template <typename E>
klao@1021
   178
    void _dirNextIn(E &e) const {
klao@962
   179
      if( e.forward ) {
klao@962
   180
	Parent::nextIn(e);
klao@962
   181
	if( UndirEdge(e) == INVALID ) {
alpar@986
   182
	  Parent::firstOut(e, Parent::target(e));
klao@962
   183
	  e.forward = false;
klao@962
   184
	}
klao@962
   185
      }
klao@962
   186
      else {
klao@962
   187
	Parent::nextOut(e);
klao@962
   188
      }
klao@962
   189
    }
klao@962
   190
klao@1021
   191
  public:
klao@1021
   192
klao@1021
   193
    void firstOut(Edge &e, const Node &n) const {
klao@1021
   194
      _dirFirstOut(e, n);
klao@1021
   195
    }
klao@1021
   196
    void firstIn(Edge &e, const Node &n) const {
klao@1021
   197
      _dirFirstIn(e, n);
klao@1021
   198
    }
klao@1021
   199
klao@1021
   200
    void nextOut(Edge &e) const {
klao@1021
   201
      _dirNextOut(e);
klao@1021
   202
    }
klao@1021
   203
    void nextIn(Edge &e) const {
klao@1021
   204
      _dirNextIn(e);
klao@1021
   205
    }
klao@1021
   206
klao@962
   207
    // Miscellaneous stuff:
klao@962
   208
klao@962
   209
    /// \todo these methods (id, maxEdgeId) should be moved into separate
klao@962
   210
    /// Extender
klao@962
   211
klao@1021
   212
    // using Parent::id;
klao@1021
   213
    // Using "using" is not a good idea, cause it could be that there is
klao@1021
   214
    // no "id" in Parent...
klao@1021
   215
klao@1021
   216
    int id(const Node &n) const {
klao@1021
   217
      return Parent::id(n);
klao@1021
   218
    }
klao@1021
   219
klao@1021
   220
    int id(const UndirEdge &e) const {
klao@1021
   221
      return Parent::id(e);
klao@1021
   222
    }
klao@962
   223
klao@962
   224
    int id(const Edge &e) const {
deba@981
   225
      return 2 * Parent::id(e) + int(e.forward);
klao@962
   226
    }
klao@962
   227
klao@1021
   228
klao@1021
   229
    int maxId(Node n) const {
klao@1021
   230
      return Parent::maxId(Node());
klao@1021
   231
    }
klao@1021
   232
klao@1021
   233
    int maxId(Edge) const {
deba@981
   234
      return 2 * Parent::maxId(typename Parent::Edge()) + 1;
klao@962
   235
    }
klao@1021
   236
    int maxId(UndirEdge) const {
deba@981
   237
      return Parent::maxId(typename Parent::Edge());
klao@962
   238
    }
klao@962
   239
klao@962
   240
  };
klao@962
   241
klao@962
   242
}
klao@962
   243
klao@962
   244
#endif // LEMON_UNDIR_GRAPH_EXTENDER_H