src/lemon/undir_graph_extender.h
author alpar
Sat, 20 Nov 2004 10:19:06 +0000
changeset 1011 5bd6c7671c9e
parent 981 2e34b796d532
child 1021 fd1d073b6557
permissions -rw-r--r--
- snapshot-rollback functionarity added to ListGraph
- The iterface of the snapshot-rollback functionarity in SmartGraph has
changed to be compatible with ListGraph::SnapShot.
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
alpar@986
    73
    /// Source of the given Edge.
alpar@986
    74
    Node source(const Edge &e) const {
alpar@986
    75
      return e.forward ? Parent::source(e) : Parent::target(e);
klao@962
    76
    }
klao@962
    77
alpar@986
    78
    /// \todo Shouldn't the "source" of an undirected edge be called "aNode"
klao@962
    79
    /// or something???
alpar@986
    80
    using Parent::source;
klao@962
    81
alpar@986
    82
    /// Target of the given Edge.
alpar@986
    83
    Node target(const Edge &e) const {
alpar@986
    84
      return e.forward ? Parent::target(e) : Parent::source(e);
klao@962
    85
    }
klao@962
    86
alpar@986
    87
    /// \todo Shouldn't the "target" of an undirected edge be called "bNode"
klao@962
    88
    /// or something???
alpar@986
    89
    using Parent::target;
klao@962
    90
klao@962
    91
    /// Returns whether the given directed edge is same orientation as the
klao@962
    92
    /// corresponding undirected edge.
klao@962
    93
    ///
klao@962
    94
    /// \todo reference to the corresponding point of the undirected graph
klao@962
    95
    /// concept. "What does the direction of an undirected edge mean?"
klao@962
    96
    bool forward(const Edge &e) const { return e.forward; }
klao@962
    97
klao@962
    98
    Node oppsiteNode(const Node &n, const Edge &e) const {
alpar@986
    99
      if( n == Parent::source(e))
alpar@986
   100
	return Parent::target(e);
alpar@986
   101
      else if( n == Parent::target(e))
alpar@986
   102
	return Parent::source(e);
klao@962
   103
      else
klao@962
   104
	return INVALID;
klao@962
   105
    }
klao@962
   106
klao@962
   107
klao@962
   108
    using Parent::first;
klao@962
   109
    void first(Edge &e) const {
klao@962
   110
      Parent::first(e);
klao@962
   111
      e.forward=true;
klao@962
   112
    }
klao@962
   113
klao@962
   114
    using Parent::next;
klao@962
   115
    void next(Edge &e) const {
klao@962
   116
      if( e.forward ) {
klao@962
   117
	e.forward = false;
klao@962
   118
      }
klao@962
   119
      else {
klao@962
   120
	Parent::next(e);
klao@962
   121
	e.forward = true;
klao@962
   122
      }
klao@962
   123
    }
klao@962
   124
klao@962
   125
    void firstOut(Edge &e, const Node &n) const {
klao@962
   126
      Parent::firstOut(e,n);
klao@962
   127
      if( UndirEdge(e) != INVALID ) {
klao@962
   128
	e.forward = true;
klao@962
   129
      }
klao@962
   130
      else {
klao@962
   131
	Parent::firstIn(e,n);
klao@962
   132
	e.forward = false;
klao@962
   133
      }
klao@962
   134
    }
klao@962
   135
    void firstIn(Edge &e, const Node &n) const {
klao@962
   136
      Parent::firstIn(e,n);
klao@962
   137
      if( UndirEdge(e) != INVALID ) {
klao@962
   138
	e.forward = true;
klao@962
   139
      }
klao@962
   140
      else {
klao@962
   141
	Parent::firstOut(e,n);
klao@962
   142
	e.forward = false;
klao@962
   143
      }
klao@962
   144
    }
klao@962
   145
klao@962
   146
    void nextOut(Edge &e) const {
klao@962
   147
      if( e.forward ) {
klao@962
   148
	Parent::nextOut(e);
klao@962
   149
	if( UndirEdge(e) == INVALID ) {
alpar@986
   150
	  Parent::firstIn(e, Parent::source(e));
klao@962
   151
	  e.forward = false;
klao@962
   152
	}
klao@962
   153
      }
klao@962
   154
      else {
klao@962
   155
	Parent::nextIn(e);
klao@962
   156
      }
klao@962
   157
    }
klao@962
   158
    void nextIn(Edge &e) const {
klao@962
   159
      if( e.forward ) {
klao@962
   160
	Parent::nextIn(e);
klao@962
   161
	if( UndirEdge(e) == INVALID ) {
alpar@986
   162
	  Parent::firstOut(e, Parent::target(e));
klao@962
   163
	  e.forward = false;
klao@962
   164
	}
klao@962
   165
      }
klao@962
   166
      else {
klao@962
   167
	Parent::nextOut(e);
klao@962
   168
      }
klao@962
   169
    }
klao@962
   170
klao@962
   171
    // Miscellaneous stuff:
klao@962
   172
klao@962
   173
    /// \todo these methods (id, maxEdgeId) should be moved into separate
klao@962
   174
    /// Extender
klao@962
   175
klao@962
   176
    using Parent::id;
klao@962
   177
klao@962
   178
    int id(const Edge &e) const {
deba@981
   179
      return 2 * Parent::id(e) + int(e.forward);
klao@962
   180
    }
klao@962
   181
deba@981
   182
    int maxId(Edge = INVALID) const {
deba@981
   183
      return 2 * Parent::maxId(typename Parent::Edge()) + 1;
klao@962
   184
    }
deba@981
   185
    int maxId(UndirEdge = INVALID) const {
deba@981
   186
      return Parent::maxId(typename Parent::Edge());
klao@962
   187
    }
klao@962
   188
klao@962
   189
  };
klao@962
   190
klao@962
   191
}
klao@962
   192
klao@962
   193
#endif // LEMON_UNDIR_GRAPH_EXTENDER_H