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