lemon/bits/graph_extender.h
author deba
Mon, 13 Feb 2006 09:42:53 +0000
changeset 1967 5d81ba873b90
parent 1910 f95eea8c34b0
child 1979 c2992fd74dad
permissions -rw-r--r--
New algorithm:
MaxCardinalitySearch
MinimalCut // in UGraph
deba@1791
     1
/* -*- C++ -*-
deba@1791
     2
 *
alpar@1956
     3
 * This file is a part of LEMON, a generic C++ optimization library
alpar@1956
     4
 *
alpar@1956
     5
 * Copyright (C) 2003-2006
alpar@1956
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1956
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@1791
     8
 *
deba@1791
     9
 * Permission to use, modify and distribute this software is granted
deba@1791
    10
 * provided that this copyright notice appears in all copies. For
deba@1791
    11
 * precise terms see the accompanying LICENSE file.
deba@1791
    12
 *
deba@1791
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@1791
    14
 * express or implied, and with no claim as to its suitability for any
deba@1791
    15
 * purpose.
deba@1791
    16
 *
deba@1791
    17
 */
deba@1791
    18
deba@1791
    19
#ifndef LEMON_GRAPH_EXTENDER_H
deba@1791
    20
#define LEMON_GRAPH_EXTENDER_H
deba@1791
    21
deba@1791
    22
#include <lemon/invalid.h>
deba@1820
    23
#include <lemon/error.h>
deba@1791
    24
deba@1791
    25
namespace lemon {
deba@1791
    26
deba@1791
    27
  template <typename _Base>
deba@1791
    28
  class GraphExtender : public _Base {
deba@1791
    29
  public:
deba@1791
    30
deba@1791
    31
    typedef _Base Parent;
deba@1791
    32
    typedef GraphExtender Graph;
deba@1791
    33
deba@1791
    34
    typedef typename Parent::Node Node;
deba@1791
    35
    typedef typename Parent::Edge Edge;
deba@1791
    36
deba@1791
    37
    int maxId(Node) const {
deba@1791
    38
      return Parent::maxNodeId();
deba@1791
    39
    }
deba@1791
    40
deba@1791
    41
    int maxId(Edge) const {
deba@1791
    42
      return Parent::maxEdgeId();
deba@1791
    43
    }
deba@1791
    44
deba@1791
    45
    Node fromId(int id, Node) const {
deba@1791
    46
      return Parent::nodeFromId(id);
deba@1791
    47
    }
deba@1791
    48
deba@1791
    49
    Edge fromId(int id, Edge) const {
deba@1791
    50
      return Parent::edgeFromId(id);
deba@1791
    51
    }
deba@1791
    52
deba@1791
    53
    Node oppositeNode(const Node &n, const Edge &e) const {
deba@1791
    54
      if (n == Parent::source(e))
deba@1791
    55
	return Parent::target(e);
deba@1791
    56
      else if(n==Parent::target(e))
deba@1791
    57
	return Parent::source(e);
deba@1791
    58
      else
deba@1791
    59
	return INVALID;
deba@1791
    60
    }
deba@1791
    61
deba@1791
    62
  };
deba@1791
    63
deba@1791
    64
  template <typename _Base>
klao@1909
    65
  class UGraphExtender : public _Base {
deba@1791
    66
    typedef _Base Parent;
klao@1909
    67
    typedef UGraphExtender Graph;
deba@1791
    68
deba@1791
    69
  public:
deba@1791
    70
klao@1909
    71
    typedef typename Parent::Edge UEdge;
deba@1791
    72
    typedef typename Parent::Node Node;
deba@1791
    73
klao@1909
    74
    class Edge : public UEdge {
klao@1909
    75
      friend class UGraphExtender;
deba@1791
    76
deba@1791
    77
    protected:
deba@1791
    78
      // FIXME: Marci use opposite logic in his graph adaptors. It would
deba@1791
    79
      // be reasonable to syncronize...
deba@1791
    80
      bool forward;
deba@1791
    81
klao@1909
    82
      Edge(const UEdge &ue, bool _forward) :
klao@1909
    83
        UEdge(ue), forward(_forward) {}
deba@1791
    84
deba@1791
    85
    public:
deba@1791
    86
      Edge() {}
deba@1791
    87
deba@1791
    88
      /// Invalid edge constructor
klao@1909
    89
      Edge(Invalid i) : UEdge(i), forward(true) {}
deba@1791
    90
deba@1791
    91
      bool operator==(const Edge &that) const {
klao@1909
    92
	return forward==that.forward && UEdge(*this)==UEdge(that);
deba@1791
    93
      }
deba@1791
    94
      bool operator!=(const Edge &that) const {
klao@1909
    95
	return forward!=that.forward || UEdge(*this)!=UEdge(that);
deba@1791
    96
      }
deba@1791
    97
      bool operator<(const Edge &that) const {
deba@1791
    98
	return forward<that.forward ||
klao@1909
    99
	  (!(that.forward<forward) && UEdge(*this)<UEdge(that));
deba@1791
   100
      }
deba@1791
   101
    };
deba@1791
   102
deba@1791
   103
deba@1791
   104
    /// \brief Edge of opposite direction.
deba@1791
   105
    ///
deba@1791
   106
    /// Returns the Edge of opposite direction.
deba@1791
   107
    Edge oppositeEdge(const Edge &e) const {
deba@1791
   108
      return Edge(e,!e.forward);
deba@1791
   109
    }
deba@1791
   110
deba@1791
   111
  public:
deba@1791
   112
    /// \todo Shouldn't the "source" of an undirected edge be called "aNode"
deba@1791
   113
    /// or something???
deba@1791
   114
    using Parent::source;
deba@1791
   115
deba@1791
   116
    /// Source of the given Edge.
deba@1791
   117
    Node source(const Edge &e) const {
deba@1791
   118
      return e.forward ? Parent::source(e) : Parent::target(e);
deba@1791
   119
    }
deba@1791
   120
deba@1791
   121
    /// \todo Shouldn't the "target" of an undirected edge be called "bNode"
deba@1791
   122
    /// or something???
deba@1791
   123
    using Parent::target;
deba@1791
   124
deba@1791
   125
    /// Target of the given Edge.
deba@1791
   126
    Node target(const Edge &e) const {
deba@1791
   127
      return e.forward ? Parent::target(e) : Parent::source(e);
deba@1791
   128
    }
deba@1791
   129
klao@1909
   130
    Node oppositeNode(const Node &n, const UEdge &e) const {
deba@1791
   131
      if( n == Parent::source(e))
deba@1791
   132
	return Parent::target(e);
deba@1791
   133
      else if( n == Parent::target(e))
deba@1791
   134
	return Parent::source(e);
deba@1791
   135
      else
deba@1791
   136
	return INVALID;
deba@1791
   137
    }
deba@1791
   138
deba@1791
   139
    /// \brief Directed edge from an undirected edge and a source node.
deba@1791
   140
    ///
klao@1909
   141
    /// Returns a (directed) Edge corresponding to the specified UEdge
deba@1791
   142
    /// and source Node.
deba@1791
   143
    ///
klao@1909
   144
    Edge direct(const UEdge &ue, const Node &s) const {
deba@1791
   145
      return Edge(ue, s == source(ue));
deba@1791
   146
    }
deba@1791
   147
deba@1791
   148
    /// \brief Directed edge from an undirected edge.
deba@1791
   149
    ///
klao@1909
   150
    /// Returns a directed edge corresponding to the specified UEdge.
deba@1791
   151
    /// If the given bool is true the given undirected edge and the
deba@1791
   152
    /// returned edge have the same source node.
klao@1909
   153
    Edge direct(const UEdge &ue, bool d) const {
deba@1791
   154
      return Edge(ue, d);
deba@1791
   155
    }
deba@1791
   156
deba@1791
   157
    /// Returns whether the given directed edge is same orientation as the
deba@1791
   158
    /// corresponding undirected edge.
deba@1791
   159
    ///
deba@1791
   160
    /// \todo reference to the corresponding point of the undirected graph
deba@1791
   161
    /// concept. "What does the direction of an undirected edge mean?"
deba@1791
   162
    bool direction(const Edge &e) const { return e.forward; }
deba@1791
   163
deba@1791
   164
deba@1791
   165
    using Parent::first;
deba@1791
   166
    void first(Edge &e) const {
deba@1791
   167
      Parent::first(e);
deba@1791
   168
      e.forward=true;
deba@1791
   169
    }
deba@1791
   170
deba@1791
   171
    using Parent::next;
deba@1791
   172
    void next(Edge &e) const {
deba@1791
   173
      if( e.forward ) {
deba@1791
   174
	e.forward = false;
deba@1791
   175
      }
deba@1791
   176
      else {
deba@1791
   177
	Parent::next(e);
deba@1791
   178
	e.forward = true;
deba@1791
   179
      }
deba@1791
   180
    }
deba@1791
   181
deba@1791
   182
  public:
deba@1791
   183
deba@1791
   184
    void firstOut(Edge &e, const Node &n) const {
deba@1791
   185
      Parent::firstIn(e,n);
klao@1909
   186
      if( UEdge(e) != INVALID ) {
deba@1791
   187
	e.forward = false;
deba@1791
   188
      }
deba@1791
   189
      else {
deba@1791
   190
	Parent::firstOut(e,n);
deba@1791
   191
	e.forward = true;
deba@1791
   192
      }
deba@1791
   193
    }
deba@1791
   194
    void nextOut(Edge &e) const {
deba@1791
   195
      if( ! e.forward ) {
deba@1791
   196
	Node n = Parent::target(e);
deba@1791
   197
	Parent::nextIn(e);
klao@1909
   198
	if( UEdge(e) == INVALID ) {
deba@1791
   199
	  Parent::firstOut(e, n);
deba@1791
   200
	  e.forward = true;
deba@1791
   201
	}
deba@1791
   202
      }
deba@1791
   203
      else {
deba@1791
   204
	Parent::nextOut(e);
deba@1791
   205
      }
deba@1791
   206
    }
deba@1791
   207
deba@1791
   208
    void firstIn(Edge &e, const Node &n) const {
deba@1791
   209
      Parent::firstOut(e,n);
klao@1909
   210
      if( UEdge(e) != INVALID ) {
deba@1791
   211
	e.forward = false;
deba@1791
   212
      }
deba@1791
   213
      else {
deba@1791
   214
	Parent::firstIn(e,n);
deba@1791
   215
	e.forward = true;
deba@1791
   216
      }
deba@1791
   217
    }
deba@1791
   218
    void nextIn(Edge &e) const {
deba@1791
   219
      if( ! e.forward ) {
deba@1791
   220
	Node n = Parent::source(e);
deba@1791
   221
	Parent::nextOut(e);
klao@1909
   222
	if( UEdge(e) == INVALID ) {
deba@1791
   223
	  Parent::firstIn(e, n);
deba@1791
   224
	  e.forward = true;
deba@1791
   225
	}
deba@1791
   226
      }
deba@1791
   227
      else {
deba@1791
   228
	Parent::nextIn(e);
deba@1791
   229
      }
deba@1791
   230
    }
deba@1791
   231
klao@1909
   232
    void firstInc(UEdge &e, const Node &n) const {
deba@1791
   233
      Parent::firstOut(e, n);
deba@1791
   234
      if (e != INVALID) return;
deba@1791
   235
      Parent::firstIn(e, n);
deba@1791
   236
    }
klao@1909
   237
    void nextInc(UEdge &e, const Node &n) const {
deba@1791
   238
      if (Parent::source(e) == n) {
deba@1791
   239
	Parent::nextOut(e);
deba@1791
   240
	if (e != INVALID) return;
deba@1791
   241
	Parent::firstIn(e, n);
deba@1791
   242
      } else {
deba@1791
   243
	Parent::nextIn(e);
deba@1791
   244
      }
deba@1791
   245
    }
deba@1791
   246
klao@1909
   247
    void firstInc(UEdge &e, bool &d, const Node &n) const {
deba@1791
   248
      d = true;
deba@1791
   249
      Parent::firstOut(e, n);
deba@1791
   250
      if (e != INVALID) return;
deba@1791
   251
      d = false;
deba@1791
   252
      Parent::firstIn(e, n);
deba@1791
   253
    }
klao@1909
   254
    void nextInc(UEdge &e, bool &d) const {
deba@1791
   255
      if (d) {
deba@1791
   256
	Node s = Parent::source(e);
deba@1791
   257
	Parent::nextOut(e);
deba@1791
   258
	if (e != INVALID) return;
deba@1791
   259
	d = false;
deba@1791
   260
	Parent::firstIn(e, s);
deba@1791
   261
      } else {
deba@1791
   262
	Parent::nextIn(e);
deba@1791
   263
      }
deba@1791
   264
    }
deba@1791
   265
deba@1791
   266
    // Miscellaneous stuff:
deba@1791
   267
deba@1791
   268
    /// \todo these methods (id, maxEdgeId) should be moved into separate
deba@1791
   269
    /// Extender
deba@1791
   270
deba@1791
   271
    // using Parent::id;
deba@1791
   272
    // Using "using" is not a good idea, cause it could be that there is
deba@1791
   273
    // no "id" in Parent...
deba@1791
   274
deba@1791
   275
    int id(const Node &n) const {
deba@1791
   276
      return Parent::id(n);
deba@1791
   277
    }
deba@1791
   278
klao@1909
   279
    int id(const UEdge &e) const {
deba@1791
   280
      return Parent::id(e);
deba@1791
   281
    }
deba@1791
   282
deba@1791
   283
    int id(const Edge &e) const {
deba@1791
   284
      return 2 * Parent::id(e) + int(e.forward);
deba@1791
   285
    }
deba@1791
   286
deba@1791
   287
    int maxNodeId() const {
deba@1791
   288
      return Parent::maxNodeId();
deba@1791
   289
    }
deba@1791
   290
deba@1791
   291
    int maxEdgeId() const {
deba@1791
   292
      return 2 * Parent::maxEdgeId() + 1;
deba@1791
   293
    }
deba@1791
   294
klao@1909
   295
    int maxUEdgeId() const {
deba@1791
   296
      return Parent::maxEdgeId();
deba@1791
   297
    }
deba@1791
   298
deba@1791
   299
    int maxId(Node) const {
deba@1791
   300
      return maxNodeId();
deba@1791
   301
    }
deba@1791
   302
deba@1791
   303
    int maxId(Edge) const {
deba@1791
   304
      return maxEdgeId();
deba@1791
   305
    }
klao@1909
   306
    int maxId(UEdge) const {
klao@1909
   307
      return maxUEdgeId();
deba@1791
   308
    }
deba@1791
   309
deba@1791
   310
    int edgeNum() const {
deba@1791
   311
      return 2 * Parent::edgeNum();
deba@1791
   312
    }
deba@1791
   313
klao@1909
   314
    int uEdgeNum() const {
deba@1791
   315
      return Parent::edgeNum();
deba@1791
   316
    }
deba@1791
   317
deba@1791
   318
    Node nodeFromId(int id) const {
deba@1791
   319
      return Parent::nodeFromId(id);
deba@1791
   320
    }
deba@1791
   321
deba@1791
   322
    Edge edgeFromId(int id) const {
deba@1791
   323
      return direct(Parent::edgeFromId(id >> 1), bool(id & 1));
deba@1791
   324
    }
deba@1791
   325
klao@1909
   326
    UEdge uEdgeFromId(int id) const {
deba@1791
   327
      return Parent::edgeFromId(id >> 1);
deba@1791
   328
    }
deba@1791
   329
deba@1791
   330
    Node fromId(int id, Node) const {
deba@1791
   331
      return nodeFromId(id);
deba@1791
   332
    }
deba@1791
   333
deba@1791
   334
    Edge fromId(int id, Edge) const {
deba@1791
   335
      return edgeFromId(id);
deba@1791
   336
    }
deba@1791
   337
klao@1909
   338
    UEdge fromId(int id, UEdge) const {
klao@1909
   339
      return uEdgeFromId(id);
deba@1791
   340
    }
deba@1791
   341
deba@1791
   342
deba@1791
   343
    Edge findEdge(Node source, Node target, Edge prev) const {
deba@1791
   344
      if (prev == INVALID) {
klao@1909
   345
	UEdge edge = Parent::findEdge(source, target);
deba@1791
   346
	if (edge != INVALID) return direct(edge, true);
deba@1791
   347
	edge = Parent::findEdge(target, source);
deba@1791
   348
	if (edge != INVALID) return direct(edge, false);
deba@1791
   349
      } else if (direction(prev)) {
klao@1909
   350
	UEdge edge = Parent::findEdge(source, target, prev);
deba@1791
   351
	if (edge != INVALID) return direct(edge, true);
deba@1791
   352
	edge = Parent::findEdge(target, source);
deba@1791
   353
	if (edge != INVALID) return direct(edge, false);	
deba@1791
   354
      } else {
klao@1909
   355
	UEdge edge = Parent::findEdge(target, source, prev);
deba@1791
   356
	if (edge != INVALID) return direct(edge, false);	      
deba@1791
   357
      }
deba@1791
   358
      return INVALID;
deba@1791
   359
    }
deba@1791
   360
klao@1909
   361
    UEdge findUEdge(Node source, Node target, UEdge prev) const {
deba@1791
   362
      if (prev == INVALID) {
klao@1909
   363
	UEdge edge = Parent::findEdge(source, target);
deba@1791
   364
	if (edge != INVALID) return edge;
deba@1791
   365
	edge = Parent::findEdge(target, source);
deba@1791
   366
	if (edge != INVALID) return edge;
deba@1791
   367
      } else if (Parent::source(prev) == source) {
klao@1909
   368
	UEdge edge = Parent::findEdge(source, target, prev);
deba@1791
   369
	if (edge != INVALID) return edge;
deba@1791
   370
	edge = Parent::findEdge(target, source);
deba@1791
   371
	if (edge != INVALID) return edge;	
deba@1791
   372
      } else {
klao@1909
   373
	UEdge edge = Parent::findEdge(target, source, prev);
deba@1791
   374
	if (edge != INVALID) return edge;	      
deba@1791
   375
      }
deba@1791
   376
      return INVALID;
deba@1791
   377
    }
deba@1791
   378
deba@1791
   379
  };
deba@1791
   380
deba@1820
   381
deba@1820
   382
  template <typename _Base>
deba@1910
   383
  class BpUGraphExtender : public _Base {
deba@1820
   384
  public:
deba@1820
   385
    typedef _Base Parent;
deba@1910
   386
    typedef BpUGraphExtender Graph;
deba@1820
   387
deba@1820
   388
    typedef typename Parent::Node Node;
klao@1909
   389
    typedef typename Parent::Edge UEdge;
deba@1820
   390
deba@1820
   391
    using Parent::first;
deba@1820
   392
    using Parent::next;
deba@1820
   393
deba@1820
   394
    using Parent::id;
deba@1820
   395
klao@1909
   396
    Node source(const UEdge& edge) const {
deba@1910
   397
      return aNode(edge);
deba@1820
   398
    }
klao@1909
   399
    Node target(const UEdge& edge) const {
deba@1910
   400
      return bNode(edge);
deba@1820
   401
    }
deba@1820
   402
klao@1909
   403
    void firstInc(UEdge& edge, bool& direction, const Node& node) const {
deba@1910
   404
      if (Parent::aNode(node)) {
deba@1910
   405
	Parent::firstOut(edge, node);
deba@1820
   406
	direction = true;
deba@1820
   407
      } else {
deba@1910
   408
	Parent::firstIn(edge, node);
klao@1909
   409
	direction = static_cast<UEdge&>(edge) == INVALID;
deba@1820
   410
      }
deba@1820
   411
    }
klao@1909
   412
    void nextInc(UEdge& edge, bool& direction) const {
deba@1820
   413
      if (direction) {
deba@1910
   414
	Parent::nextOut(edge);
deba@1820
   415
      } else {
deba@1910
   416
	Parent::nextIn(edge);
deba@1820
   417
	if (edge == INVALID) direction = true;
deba@1820
   418
      }
deba@1820
   419
    }
deba@1820
   420
klao@1909
   421
    int maxUEdgeId() const {
deba@1820
   422
      return Parent::maxEdgeId();
deba@1820
   423
    }
deba@1820
   424
klao@1909
   425
    UEdge uEdgeFromId(int id) const {
deba@1820
   426
      return Parent::edgeFromId(id);
deba@1820
   427
    }
deba@1820
   428
klao@1909
   429
    class Edge : public UEdge {
deba@1910
   430
      friend class BpUGraphExtender;
deba@1820
   431
    protected:
deba@1820
   432
      bool forward;
deba@1820
   433
klao@1909
   434
      Edge(const UEdge& edge, bool _forward)
klao@1909
   435
	: UEdge(edge), forward(_forward) {}
deba@1820
   436
deba@1820
   437
    public:
deba@1820
   438
      Edge() {}
klao@1909
   439
      Edge (Invalid) : UEdge(INVALID), forward(true) {}
deba@1820
   440
      bool operator==(const Edge& i) const {
klao@1909
   441
	return UEdge::operator==(i) && forward == i.forward;
deba@1820
   442
      }
deba@1820
   443
      bool operator!=(const Edge& i) const {
klao@1909
   444
	return UEdge::operator!=(i) || forward != i.forward;
deba@1820
   445
      }
deba@1820
   446
      bool operator<(const Edge& i) const {
klao@1909
   447
	return UEdge::operator<(i) || 
klao@1909
   448
	  (!(i.forward<forward) && UEdge(*this)<UEdge(i));
deba@1820
   449
      }
deba@1820
   450
    };
deba@1820
   451
deba@1820
   452
    void first(Edge& edge) const {
klao@1909
   453
      Parent::first(static_cast<UEdge&>(edge));
deba@1820
   454
      edge.forward = true;
deba@1820
   455
    }
deba@1820
   456
deba@1820
   457
    void next(Edge& edge) const {
deba@1820
   458
      if (!edge.forward) {
klao@1909
   459
	Parent::next(static_cast<UEdge&>(edge));
deba@1820
   460
      }
deba@1820
   461
      edge.forward = !edge.forward;
deba@1820
   462
    }
deba@1820
   463
deba@1820
   464
    void firstOut(Edge& edge, const Node& node) const {
deba@1910
   465
      if (Parent::aNode(node)) {
deba@1910
   466
	Parent::firstOut(edge, node);
deba@1820
   467
	edge.forward = true;
deba@1820
   468
      } else {
deba@1910
   469
	Parent::firstIn(edge, node);
klao@1909
   470
	edge.forward = static_cast<UEdge&>(edge) == INVALID;
deba@1820
   471
      }
deba@1820
   472
    }
deba@1820
   473
    void nextOut(Edge& edge) const {
deba@1820
   474
      if (edge.forward) {
deba@1910
   475
	Parent::nextOut(edge);
deba@1820
   476
      } else {
deba@1910
   477
	Parent::nextIn(edge);
klao@1909
   478
        edge.forward = static_cast<UEdge&>(edge) == INVALID;
deba@1820
   479
      }
deba@1820
   480
    }
deba@1820
   481
deba@1820
   482
    void firstIn(Edge& edge, const Node& node) const {
deba@1910
   483
      if (Parent::bNode(node)) {
deba@1910
   484
	Parent::firstIn(edge, node);
deba@1820
   485
	edge.forward = true;	
deba@1820
   486
      } else {
deba@1910
   487
	Parent::firstOut(edge, node);
klao@1909
   488
	edge.forward = static_cast<UEdge&>(edge) == INVALID;
deba@1820
   489
      }
deba@1820
   490
    }
deba@1820
   491
    void nextIn(Edge& edge) const {
deba@1820
   492
      if (edge.forward) {
deba@1910
   493
	Parent::nextIn(edge);
deba@1820
   494
      } else {
deba@1910
   495
	Parent::nextOut(edge);
klao@1909
   496
	edge.forward = static_cast<UEdge&>(edge) == INVALID;
deba@1820
   497
      }
deba@1820
   498
    }
deba@1820
   499
deba@1820
   500
    Node source(const Edge& edge) const {
deba@1910
   501
      return edge.forward ? Parent::aNode(edge) : Parent::bNode(edge);
deba@1820
   502
    }
deba@1820
   503
    Node target(const Edge& edge) const {
deba@1910
   504
      return edge.forward ? Parent::bNode(edge) : Parent::aNode(edge);
deba@1820
   505
    }
deba@1820
   506
deba@1820
   507
    bool direction(const Edge& edge) const {
deba@1820
   508
      return edge.forward;
deba@1820
   509
    }
deba@1820
   510
klao@1909
   511
    Edge direct(const UEdge& edge, const Node& node) const {
deba@1820
   512
      return Edge(edge, node == Parent::source(edge));
deba@1820
   513
    }
deba@1820
   514
klao@1909
   515
    Edge direct(const UEdge& edge, bool direction) const {
deba@1820
   516
      return Edge(edge, direction);
deba@1820
   517
    }
deba@1820
   518
klao@1909
   519
    Node oppositeNode(const UEdge& edge, const Node& node) const {
deba@1820
   520
      return source(edge) == node ? 
deba@1820
   521
	target(edge) : source(edge);
deba@1820
   522
    }
deba@1820
   523
deba@1820
   524
    Edge oppositeEdge(const Edge& edge) const {
deba@1820
   525
      return Edge(edge, !edge.forward);
deba@1820
   526
    }
deba@1820
   527
deba@1820
   528
    int id(const Edge& edge) const {
deba@1820
   529
      return (Parent::id(edge) << 1) + (edge.forward ? 0 : 1);
deba@1820
   530
    }
deba@1820
   531
    Edge edgeFromId(int id) const {
klao@1909
   532
      return Edge(Parent::fromId(id >> 1, UEdge()), (id & 1) == 0);
deba@1820
   533
    }
deba@1820
   534
    int maxEdgeId() const {
klao@1909
   535
      return (Parent::maxId(UEdge()) << 1) + 1;
deba@1820
   536
    }
deba@1820
   537
deba@1910
   538
    class ANode : public Node {
deba@1910
   539
      friend class BpUGraphExtender;
deba@1820
   540
    public:
deba@1910
   541
      ANode() {}
deba@1910
   542
      ANode(const Node& node) : Node(node) {
deba@1910
   543
	LEMON_ASSERT(Parent::aNode(node) || node == INVALID, 
deba@1820
   544
		     typename Parent::NodeSetError());
deba@1820
   545
      }
deba@1910
   546
      ANode(Invalid) : Node(INVALID) {}
deba@1820
   547
    };
deba@1820
   548
deba@1910
   549
    void first(ANode& node) const {
deba@1910
   550
      Parent::firstANode(static_cast<Node&>(node));
deba@1820
   551
    }
deba@1910
   552
    void next(ANode& node) const {
deba@1910
   553
      Parent::nextANode(static_cast<Node&>(node));
deba@1820
   554
    }
deba@1820
   555
deba@1910
   556
    int id(const ANode& node) const {
deba@1910
   557
      return Parent::aNodeId(node);
deba@1820
   558
    }
deba@1820
   559
deba@1910
   560
    class BNode : public Node {
deba@1910
   561
      friend class BpUGraphExtender;
deba@1820
   562
    public:
deba@1910
   563
      BNode() {}
deba@1910
   564
      BNode(const Node& node) : Node(node) {
deba@1910
   565
	LEMON_ASSERT(Parent::bNode(node) || node == INVALID,
deba@1820
   566
		     typename Parent::NodeSetError());
deba@1820
   567
      }
deba@1910
   568
      BNode(Invalid) : Node(INVALID) {}
deba@1820
   569
    };
deba@1820
   570
deba@1910
   571
    void first(BNode& node) const {
deba@1910
   572
      Parent::firstBNode(static_cast<Node&>(node));
deba@1820
   573
    }
deba@1910
   574
    void next(BNode& node) const {
deba@1910
   575
      Parent::nextBNode(static_cast<Node&>(node));
deba@1820
   576
    }
deba@1820
   577
  
deba@1910
   578
    int id(const BNode& node) const {
deba@1910
   579
      return Parent::aNodeId(node);
deba@1820
   580
    }
deba@1820
   581
deba@1820
   582
deba@1820
   583
deba@1820
   584
    int maxId(Node) const {
deba@1820
   585
      return Parent::maxNodeId();
deba@1820
   586
    }
deba@1910
   587
    int maxId(BNode) const {
deba@1910
   588
      return Parent::maxBNodeId();
deba@1820
   589
    }
deba@1910
   590
    int maxId(ANode) const {
deba@1910
   591
      return Parent::maxANodeId();
deba@1820
   592
    }
deba@1820
   593
    int maxId(Edge) const {
deba@1820
   594
      return maxEdgeId();
deba@1820
   595
    }
klao@1909
   596
    int maxId(UEdge) const {
klao@1909
   597
      return maxUEdgeId();
deba@1820
   598
    }
deba@1820
   599
deba@1820
   600
deba@1820
   601
    Node fromId(int id, Node) const {
deba@1820
   602
      return Parent::nodeFromId(id);
deba@1820
   603
    }
deba@1910
   604
    ANode fromId(int id, ANode) const {
deba@1910
   605
      return Parent::fromANodeId(id);
deba@1820
   606
    }
deba@1910
   607
    BNode fromId(int id, BNode) const {
deba@1910
   608
      return Parent::fromBNodeId(id);
deba@1820
   609
    }
deba@1820
   610
    Edge fromId(int id, Edge) const {
deba@1820
   611
      return edgeFromId(id);
deba@1820
   612
    }
klao@1909
   613
    UEdge fromId(int id, UEdge) const {
klao@1909
   614
      return uEdgeFromId(id);
deba@1820
   615
    }
deba@1820
   616
deba@1820
   617
  };
deba@1820
   618
deba@1791
   619
}
deba@1791
   620
deba@1791
   621
#endif // LEMON_UNDIR_GRAPH_EXTENDER_H