lemon/bits/base_extender.h
author alpar
Wed, 09 Aug 2006 12:51:21 +0000
changeset 2170 42fffa713424
parent 2031 080d51024ac5
child 2187 a54a2dd03f03
permissions -rw-r--r--
Do not list the header itself.
deba@1999
     1
/* -*- C++ -*-
deba@1999
     2
 *
deba@1999
     3
 * This file is a part of LEMON, a generic C++ optimization library
deba@1999
     4
 *
deba@1999
     5
 * Copyright (C) 2003-2006
deba@1999
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@1999
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@1999
     8
 *
deba@1999
     9
 * Permission to use, modify and distribute this software is granted
deba@1999
    10
 * provided that this copyright notice appears in all copies. For
deba@1999
    11
 * precise terms see the accompanying LICENSE file.
deba@1999
    12
 *
deba@1999
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@1999
    14
 * express or implied, and with no claim as to its suitability for any
deba@1999
    15
 * purpose.
deba@1999
    16
 *
deba@1999
    17
 */
deba@1999
    18
deba@1999
    19
#ifndef LEMON_BITS_BASE_EXTENDER_H
deba@1999
    20
#define LEMON_BITS_BASE_EXTENDER_H
deba@1999
    21
deba@1999
    22
#include <lemon/bits/invalid.h>
deba@1999
    23
#include <lemon/error.h>
deba@1999
    24
deba@1999
    25
#include <lemon/bits/map_extender.h>
deba@1999
    26
#include <lemon/bits/default_map.h>
deba@1999
    27
deba@1999
    28
#include <lemon/concept_check.h>
deba@1999
    29
#include <lemon/concept/maps.h>
deba@1999
    30
deba@1999
    31
///\ingroup graphbits
deba@1999
    32
///\file
deba@1999
    33
///\brief Extenders for the graph types
deba@1999
    34
namespace lemon {
deba@1999
    35
deba@1999
    36
  /// \ingroup graphbits
deba@1999
    37
  ///
deba@1999
    38
  /// \brief BaseExtender for the UGraphs
deba@1999
    39
  template <typename Base>
deba@2076
    40
  class UndirGraphExtender : public Base {
deba@1999
    41
deba@1999
    42
  public:
deba@1999
    43
deba@1999
    44
    typedef Base Parent;
deba@1999
    45
    typedef typename Parent::Edge UEdge;
deba@1999
    46
    typedef typename Parent::Node Node;
deba@1999
    47
deba@1999
    48
    typedef True UndirectedTag;
deba@1999
    49
deba@1999
    50
    class Edge : public UEdge {
deba@2076
    51
      friend class UndirGraphExtender;
deba@1999
    52
deba@1999
    53
    protected:
deba@1999
    54
      bool forward;
deba@1999
    55
deba@1999
    56
      Edge(const UEdge &ue, bool _forward) :
deba@1999
    57
        UEdge(ue), forward(_forward) {}
deba@1999
    58
deba@1999
    59
    public:
deba@1999
    60
      Edge() {}
deba@1999
    61
deba@1999
    62
      /// Invalid edge constructor
deba@1999
    63
      Edge(Invalid i) : UEdge(i), forward(true) {}
deba@1999
    64
deba@1999
    65
      bool operator==(const Edge &that) const {
deba@1999
    66
	return forward==that.forward && UEdge(*this)==UEdge(that);
deba@1999
    67
      }
deba@1999
    68
      bool operator!=(const Edge &that) const {
deba@1999
    69
	return forward!=that.forward || UEdge(*this)!=UEdge(that);
deba@1999
    70
      }
deba@1999
    71
      bool operator<(const Edge &that) const {
deba@1999
    72
	return forward<that.forward ||
deba@1999
    73
	  (!(that.forward<forward) && UEdge(*this)<UEdge(that));
deba@1999
    74
      }
deba@1999
    75
    };
deba@1999
    76
deba@1999
    77
deba@1999
    78
deba@1999
    79
    using Parent::source;
deba@1999
    80
deba@1999
    81
    /// Source of the given Edge.
deba@1999
    82
    Node source(const Edge &e) const {
deba@1999
    83
      return e.forward ? Parent::source(e) : Parent::target(e);
deba@1999
    84
    }
deba@1999
    85
deba@1999
    86
    using Parent::target;
deba@1999
    87
deba@1999
    88
    /// Target of the given Edge.
deba@1999
    89
    Node target(const Edge &e) const {
deba@1999
    90
      return e.forward ? Parent::target(e) : Parent::source(e);
deba@1999
    91
    }
deba@1999
    92
deba@1999
    93
    /// \brief Directed edge from an undirected edge.
deba@1999
    94
    ///
deba@1999
    95
    /// Returns a directed edge corresponding to the specified UEdge.
deba@1999
    96
    /// If the given bool is true the given undirected edge and the
deba@1999
    97
    /// returned edge have the same source node.
deba@1999
    98
    static Edge direct(const UEdge &ue, bool d) {
deba@1999
    99
      return Edge(ue, d);
deba@1999
   100
    }
deba@1999
   101
deba@1999
   102
    /// Returns whether the given directed edge is same orientation as the
deba@1999
   103
    /// corresponding undirected edge.
deba@1999
   104
    ///
deba@1999
   105
    /// \todo reference to the corresponding point of the undirected graph
deba@1999
   106
    /// concept. "What does the direction of an undirected edge mean?"
deba@1999
   107
    static bool direction(const Edge &e) { return e.forward; }
deba@1999
   108
deba@1999
   109
deba@1999
   110
    using Parent::first;
deba@1999
   111
    using Parent::next;
deba@1999
   112
deba@1999
   113
    void first(Edge &e) const {
deba@1999
   114
      Parent::first(e);
deba@1999
   115
      e.forward=true;
deba@1999
   116
    }
deba@1999
   117
deba@1999
   118
    void next(Edge &e) const {
deba@1999
   119
      if( e.forward ) {
deba@1999
   120
	e.forward = false;
deba@1999
   121
      }
deba@1999
   122
      else {
deba@1999
   123
	Parent::next(e);
deba@1999
   124
	e.forward = true;
deba@1999
   125
      }
deba@1999
   126
    }
deba@1999
   127
deba@1999
   128
    void firstOut(Edge &e, const Node &n) const {
deba@1999
   129
      Parent::firstIn(e,n);
deba@1999
   130
      if( UEdge(e) != INVALID ) {
deba@1999
   131
	e.forward = false;
deba@1999
   132
      }
deba@1999
   133
      else {
deba@1999
   134
	Parent::firstOut(e,n);
deba@1999
   135
	e.forward = true;
deba@1999
   136
      }
deba@1999
   137
    }
deba@1999
   138
    void nextOut(Edge &e) const {
deba@1999
   139
      if( ! e.forward ) {
deba@1999
   140
	Node n = Parent::target(e);
deba@1999
   141
	Parent::nextIn(e);
deba@1999
   142
	if( UEdge(e) == INVALID ) {
deba@1999
   143
	  Parent::firstOut(e, n);
deba@1999
   144
	  e.forward = true;
deba@1999
   145
	}
deba@1999
   146
      }
deba@1999
   147
      else {
deba@1999
   148
	Parent::nextOut(e);
deba@1999
   149
      }
deba@1999
   150
    }
deba@1999
   151
deba@1999
   152
    void firstIn(Edge &e, const Node &n) const {
deba@1999
   153
      Parent::firstOut(e,n);
deba@1999
   154
      if( UEdge(e) != INVALID ) {
deba@1999
   155
	e.forward = false;
deba@1999
   156
      }
deba@1999
   157
      else {
deba@1999
   158
	Parent::firstIn(e,n);
deba@1999
   159
	e.forward = true;
deba@1999
   160
      }
deba@1999
   161
    }
deba@1999
   162
    void nextIn(Edge &e) const {
deba@1999
   163
      if( ! e.forward ) {
deba@1999
   164
	Node n = Parent::source(e);
deba@1999
   165
	Parent::nextOut(e);
deba@1999
   166
	if( UEdge(e) == INVALID ) {
deba@1999
   167
	  Parent::firstIn(e, n);
deba@1999
   168
	  e.forward = true;
deba@1999
   169
	}
deba@1999
   170
      }
deba@1999
   171
      else {
deba@1999
   172
	Parent::nextIn(e);
deba@1999
   173
      }
deba@1999
   174
    }
deba@1999
   175
deba@1999
   176
    void firstInc(UEdge &e, bool &d, const Node &n) const {
deba@1999
   177
      d = true;
deba@1999
   178
      Parent::firstOut(e, n);
deba@1999
   179
      if (e != INVALID) return;
deba@1999
   180
      d = false;
deba@1999
   181
      Parent::firstIn(e, n);
deba@1999
   182
    }
deba@1999
   183
deba@1999
   184
    void nextInc(UEdge &e, bool &d) const {
deba@1999
   185
      if (d) {
deba@1999
   186
	Node s = Parent::source(e);
deba@1999
   187
	Parent::nextOut(e);
deba@1999
   188
	if (e != INVALID) return;
deba@1999
   189
	d = false;
deba@1999
   190
	Parent::firstIn(e, s);
deba@1999
   191
      } else {
deba@1999
   192
	Parent::nextIn(e);
deba@1999
   193
      }
deba@1999
   194
    }
deba@1999
   195
deba@1999
   196
    Node nodeFromId(int id) const {
deba@1999
   197
      return Parent::nodeFromId(id);
deba@1999
   198
    }
deba@1999
   199
deba@1999
   200
    Edge edgeFromId(int id) const {
deba@1999
   201
      return direct(Parent::edgeFromId(id >> 1), bool(id & 1));
deba@1999
   202
    }
deba@1999
   203
deba@1999
   204
    UEdge uEdgeFromId(int id) const {
deba@1999
   205
      return Parent::edgeFromId(id >> 1);
deba@1999
   206
    }
deba@1999
   207
deba@1999
   208
    int id(const Node &n) const {
deba@1999
   209
      return Parent::id(n);
deba@1999
   210
    }
deba@1999
   211
deba@1999
   212
    int id(const UEdge &e) const {
deba@1999
   213
      return Parent::id(e);
deba@1999
   214
    }
deba@1999
   215
deba@1999
   216
    int id(const Edge &e) const {
deba@1999
   217
      return 2 * Parent::id(e) + int(e.forward);
deba@1999
   218
    }
deba@1999
   219
deba@1999
   220
    int maxNodeId() const {
deba@1999
   221
      return Parent::maxNodeId();
deba@1999
   222
    }
deba@1999
   223
deba@1999
   224
    int maxEdgeId() const {
deba@1999
   225
      return 2 * Parent::maxEdgeId() + 1;
deba@1999
   226
    }
deba@1999
   227
deba@1999
   228
    int maxUEdgeId() const {
deba@1999
   229
      return Parent::maxEdgeId();
deba@1999
   230
    }
deba@1999
   231
deba@1999
   232
deba@1999
   233
    int edgeNum() const {
deba@1999
   234
      return 2 * Parent::edgeNum();
deba@1999
   235
    }
deba@1999
   236
deba@1999
   237
    int uEdgeNum() const {
deba@1999
   238
      return Parent::edgeNum();
deba@1999
   239
    }
deba@1999
   240
deba@1999
   241
    Edge findEdge(Node source, Node target, Edge prev) const {
deba@1999
   242
      if (prev == INVALID) {
deba@1999
   243
	UEdge edge = Parent::findEdge(source, target);
deba@1999
   244
	if (edge != INVALID) return direct(edge, true);
deba@1999
   245
	edge = Parent::findEdge(target, source);
deba@1999
   246
	if (edge != INVALID) return direct(edge, false);
deba@1999
   247
      } else if (direction(prev)) {
deba@1999
   248
	UEdge edge = Parent::findEdge(source, target, prev);
deba@1999
   249
	if (edge != INVALID) return direct(edge, true);
deba@1999
   250
	edge = Parent::findEdge(target, source);
deba@1999
   251
	if (edge != INVALID) return direct(edge, false);	
deba@1999
   252
      } else {
deba@1999
   253
	UEdge edge = Parent::findEdge(target, source, prev);
deba@1999
   254
	if (edge != INVALID) return direct(edge, false);	      
deba@1999
   255
      }
deba@1999
   256
      return INVALID;
deba@1999
   257
    }
deba@1999
   258
deba@1999
   259
    UEdge findUEdge(Node source, Node target, UEdge prev) const {
deba@1999
   260
      if (prev == INVALID) {
deba@1999
   261
	UEdge edge = Parent::findEdge(source, target);
deba@1999
   262
	if (edge != INVALID) return edge;
deba@1999
   263
	edge = Parent::findEdge(target, source);
deba@1999
   264
	if (edge != INVALID) return edge;
deba@1999
   265
      } else if (Parent::source(prev) == source) {
deba@1999
   266
	UEdge edge = Parent::findEdge(source, target, prev);
deba@1999
   267
	if (edge != INVALID) return edge;
deba@1999
   268
	edge = Parent::findEdge(target, source);
deba@1999
   269
	if (edge != INVALID) return edge;	
deba@1999
   270
      } else {
deba@1999
   271
	UEdge edge = Parent::findEdge(target, source, prev);
deba@1999
   272
	if (edge != INVALID) return edge;	      
deba@1999
   273
      }
deba@1999
   274
      return INVALID;
deba@1999
   275
    }
deba@1999
   276
  };
deba@1999
   277
deba@1999
   278
}
deba@1999
   279
deba@1999
   280
#endif