lemon/bits/iterable_graph_extender.h
author deba
Mon, 13 Feb 2006 09:42:53 +0000
changeset 1967 5d81ba873b90
parent 1934 272fa8a0b680
permissions -rw-r--r--
New algorithm:
MaxCardinalitySearch
MinimalCut // in UGraph
alpar@1956
     1
/* -*- C++ -*-
alpar@1956
     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).
alpar@1956
     8
 *
alpar@1956
     9
 * Permission to use, modify and distribute this software is granted
alpar@1956
    10
 * provided that this copyright notice appears in all copies. For
alpar@1956
    11
 * precise terms see the accompanying LICENSE file.
alpar@1956
    12
 *
alpar@1956
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@1956
    14
 * express or implied, and with no claim as to its suitability for any
alpar@1956
    15
 * purpose.
alpar@1956
    16
 *
alpar@1956
    17
 */
alpar@1956
    18
klao@946
    19
#ifndef LEMON_ITERABLE_GRAPH_EXTENDER_H
klao@946
    20
#define LEMON_ITERABLE_GRAPH_EXTENDER_H
klao@946
    21
klao@946
    22
#include <lemon/invalid.h>
alpar@1448
    23
#include <lemon/utility.h>
klao@946
    24
klao@946
    25
namespace lemon {
klao@946
    26
  
klao@946
    27
  template <typename _Base>
klao@946
    28
  class IterableGraphExtender : public _Base {
klao@962
    29
  public:
klao@946
    30
alpar@1448
    31
    /// Indicates that the graph is undirected.
alpar@1448
    32
alpar@1448
    33
    ///\todo Better name?
alpar@1448
    34
    ///
alpar@1448
    35
    ///\bug Should it be here?
klao@1909
    36
    typedef False UTag;
alpar@1448
    37
klao@946
    38
    typedef _Base Parent;
klao@946
    39
    typedef IterableGraphExtender<_Base> Graph;
klao@946
    40
klao@946
    41
    typedef typename Parent::Node Node;
klao@946
    42
    typedef typename Parent::Edge Edge;
klao@946
    43
klao@946
    44
klao@946
    45
    class NodeIt : public Node { 
klao@946
    46
      const Graph* graph;
klao@946
    47
    public:
klao@946
    48
klao@946
    49
      NodeIt() {}
klao@946
    50
klao@946
    51
      NodeIt(Invalid i) : Node(i) { }
klao@946
    52
klao@962
    53
      explicit NodeIt(const Graph& _graph) : graph(&_graph) {
klao@946
    54
	_graph.first(*static_cast<Node*>(this));
klao@946
    55
      }
klao@946
    56
klao@946
    57
      NodeIt(const Graph& _graph, const Node& node) 
klao@946
    58
	: Node(node), graph(&_graph) {}
klao@946
    59
klao@946
    60
      NodeIt& operator++() { 
klao@946
    61
	graph->next(*this);
klao@946
    62
	return *this; 
klao@946
    63
      }
klao@946
    64
klao@946
    65
    };
klao@946
    66
klao@946
    67
klao@946
    68
    class EdgeIt : public Edge { 
klao@946
    69
      const Graph* graph;
klao@946
    70
    public:
klao@946
    71
klao@946
    72
      EdgeIt() { }
klao@946
    73
klao@946
    74
      EdgeIt(Invalid i) : Edge(i) { }
klao@946
    75
klao@962
    76
      explicit EdgeIt(const Graph& _graph) : graph(&_graph) {
klao@946
    77
	_graph.first(*static_cast<Edge*>(this));
klao@946
    78
      }
klao@946
    79
klao@946
    80
      EdgeIt(const Graph& _graph, const Edge& e) : 
klao@946
    81
	Edge(e), graph(&_graph) { }
klao@946
    82
klao@946
    83
      EdgeIt& operator++() { 
klao@946
    84
	graph->next(*this);
klao@946
    85
	return *this; 
klao@946
    86
      }
klao@946
    87
klao@946
    88
    };
klao@946
    89
klao@946
    90
klao@946
    91
    class OutEdgeIt : public Edge { 
klao@946
    92
      const Graph* graph;
klao@946
    93
    public:
klao@946
    94
klao@946
    95
      OutEdgeIt() { }
klao@946
    96
klao@946
    97
      OutEdgeIt(Invalid i) : Edge(i) { }
klao@946
    98
klao@946
    99
      OutEdgeIt(const Graph& _graph, const Node& node) 
klao@962
   100
	: graph(&_graph) {
klao@946
   101
	_graph.firstOut(*this, node);
klao@946
   102
      }
klao@946
   103
klao@946
   104
      OutEdgeIt(const Graph& _graph, const Edge& edge) 
klao@946
   105
	: Edge(edge), graph(&_graph) {}
klao@946
   106
klao@946
   107
      OutEdgeIt& operator++() { 
klao@946
   108
	graph->nextOut(*this);
klao@946
   109
	return *this; 
klao@946
   110
      }
klao@946
   111
klao@946
   112
    };
klao@946
   113
klao@946
   114
klao@946
   115
    class InEdgeIt : public Edge { 
klao@946
   116
      const Graph* graph;
klao@946
   117
    public:
klao@946
   118
klao@946
   119
      InEdgeIt() { }
klao@946
   120
klao@946
   121
      InEdgeIt(Invalid i) : Edge(i) { }
klao@946
   122
klao@946
   123
      InEdgeIt(const Graph& _graph, const Node& node) 
klao@962
   124
	: graph(&_graph) {
klao@946
   125
	_graph.firstIn(*this, node);
klao@946
   126
      }
klao@946
   127
klao@946
   128
      InEdgeIt(const Graph& _graph, const Edge& edge) : 
klao@946
   129
	Edge(edge), graph(&_graph) {}
klao@946
   130
klao@946
   131
      InEdgeIt& operator++() { 
klao@946
   132
	graph->nextIn(*this);
klao@946
   133
	return *this; 
klao@946
   134
      }
klao@946
   135
klao@946
   136
    };
klao@946
   137
deba@1627
   138
    /// \brief Base node of the iterator
klao@1158
   139
    ///
klao@1158
   140
    /// Returns the base node (ie. the source in this case) of the iterator
klao@1158
   141
    Node baseNode(const OutEdgeIt &e) const {
deba@1564
   142
      return Parent::source((Edge)e);
klao@1158
   143
    }
deba@1627
   144
    /// \brief Running node of the iterator
klao@1158
   145
    ///
klao@1158
   146
    /// Returns the running node (ie. the target in this case) of the
klao@1158
   147
    /// iterator
klao@1158
   148
    Node runningNode(const OutEdgeIt &e) const {
deba@1564
   149
      return Parent::target((Edge)e);
klao@1158
   150
    }
klao@1158
   151
deba@1627
   152
    /// \brief Base node of the iterator
klao@1158
   153
    ///
klao@1158
   154
    /// Returns the base node (ie. the target in this case) of the iterator
klao@1158
   155
    Node baseNode(const InEdgeIt &e) const {
deba@1564
   156
      return Parent::target((Edge)e);
klao@1158
   157
    }
deba@1627
   158
    /// \brief Running node of the iterator
klao@1158
   159
    ///
klao@1158
   160
    /// Returns the running node (ie. the source in this case) of the
klao@1158
   161
    /// iterator
klao@1158
   162
    Node runningNode(const InEdgeIt &e) const {
deba@1564
   163
      return Parent::source((Edge)e);
klao@1158
   164
    }
klao@1158
   165
klao@946
   166
    using Parent::first;
klao@946
   167
deba@1627
   168
    /// \brief The opposite node on the given edge.
deba@1627
   169
    ///
deba@1627
   170
    /// Gives back the opposite on the given edge.
deba@1627
   171
    Node oppositeNode(const Node& n, const Edge& e) const {
deba@1627
   172
      if (Parent::source(e) == n) {
deba@1627
   173
	return Parent::target(e);
deba@1627
   174
      } else {
deba@1627
   175
	return Parent::source(e);
deba@1627
   176
      }
deba@1627
   177
    }
deba@1627
   178
klao@946
   179
  private:
klao@946
   180
klao@1230
   181
    // void first(NodeIt &) const;
klao@1230
   182
    // void first(EdgeIt &) const;
klao@1230
   183
    // void first(OutEdgeIt &) const;
klao@1230
   184
    // void first(InEdgeIt &) const;
klao@946
   185
klao@946
   186
  };
klao@1158
   187
klao@1158
   188
klao@1158
   189
klao@1158
   190
klao@1158
   191
klao@946
   192
  
klao@962
   193
  template <typename _Base>
klao@1909
   194
  class IterableUGraphExtender : public IterableGraphExtender<_Base> {
klao@962
   195
  public:
klao@962
   196
alpar@1448
   197
    /// Indicates that the graph is undirected.
alpar@1448
   198
alpar@1448
   199
    ///\todo Better name?
alpar@1448
   200
    ///
alpar@1448
   201
    ///\bug Should it be here?
alpar@1448
   202
    ///\bug Should be tested in the concept checker whether it is defined
alpar@1448
   203
    ///correctly.
klao@1909
   204
    typedef True UTag;
alpar@1448
   205
klao@962
   206
    typedef IterableGraphExtender<_Base> Parent;
klao@1909
   207
    typedef IterableUGraphExtender<_Base> Graph;
klao@1021
   208
    typedef typename Parent::Node Node;
deba@1627
   209
    typedef typename Parent::Edge Edge;
klao@1909
   210
    typedef typename Parent::UEdge UEdge;
klao@962
   211
klao@1909
   212
    class UEdgeIt : public Parent::UEdge { 
klao@962
   213
      const Graph* graph;
klao@962
   214
    public:
klao@962
   215
klao@1909
   216
      UEdgeIt() { }
klao@962
   217
klao@1909
   218
      UEdgeIt(Invalid i) : UEdge(i) { }
klao@962
   219
klao@1909
   220
      explicit UEdgeIt(const Graph& _graph) : graph(&_graph) {
klao@1909
   221
	_graph.first(*static_cast<UEdge*>(this));
klao@962
   222
      }
klao@962
   223
klao@1909
   224
      UEdgeIt(const Graph& _graph, const UEdge& e) : 
klao@1909
   225
	UEdge(e), graph(&_graph) { }
klao@962
   226
klao@1909
   227
      UEdgeIt& operator++() { 
klao@962
   228
	graph->next(*this);
klao@962
   229
	return *this; 
klao@962
   230
      }
klao@962
   231
klao@962
   232
    };
klao@962
   233
klao@1909
   234
    class IncEdgeIt : public Parent::UEdge { 
klao@1021
   235
      const Graph* graph;
deba@1704
   236
      bool direction;
klao@1909
   237
      friend class IterableUGraphExtender;
klao@1021
   238
    public:
klao@1021
   239
klao@1030
   240
      IncEdgeIt() { }
klao@1021
   241
klao@1909
   242
      IncEdgeIt(Invalid i) : UEdge(i), direction(false) { }
klao@1021
   243
deba@1704
   244
      IncEdgeIt(const Graph& _graph, const Node &n) : graph(&_graph) {
deba@1704
   245
	_graph.firstInc(*this, direction, n);
klao@1021
   246
      }
klao@1021
   247
klao@1909
   248
      IncEdgeIt(const Graph& _graph, const UEdge &ue, const Node &n)
klao@1909
   249
	: graph(&_graph), UEdge(ue) {
deba@1704
   250
	direction = (_graph.source(ue) == n);
klao@1158
   251
      }
klao@1021
   252
klao@1030
   253
      IncEdgeIt& operator++() {
deba@1704
   254
	graph->nextInc(*this, direction);
klao@1021
   255
	return *this; 
klao@1021
   256
      }
klao@1021
   257
    };
klao@1021
   258
klao@1158
   259
    using Parent::baseNode;
klao@1158
   260
    using Parent::runningNode;
klao@1158
   261
klao@1158
   262
    /// Base node of the iterator
klao@1158
   263
    ///
klao@1158
   264
    /// Returns the base node of the iterator
klao@1158
   265
    Node baseNode(const IncEdgeIt &e) const {
deba@1704
   266
      return e.direction ? source(e) : target(e);
klao@1021
   267
    }
klao@1158
   268
    /// Running node of the iterator
klao@1158
   269
    ///
klao@1158
   270
    /// Returns the running node of the iterator
klao@1158
   271
    Node runningNode(const IncEdgeIt &e) const {
deba@1704
   272
      return e.direction ? target(e) : source(e);
klao@1021
   273
    }
klao@1021
   274
deba@1627
   275
    /// \brief The opposite node on the given undirected edge.
deba@1627
   276
    ///
deba@1627
   277
    /// Gives back the opposite on the given undirected edge.
klao@1909
   278
    Node oppositeNode(const Node& n, const UEdge& e) const {
deba@1627
   279
      if (Parent::source(e) == n) {
deba@1627
   280
	return Parent::target(e);
deba@1627
   281
      } else {
deba@1627
   282
	return Parent::source(e);
deba@1627
   283
      }
deba@1627
   284
    }
deba@1627
   285
klao@962
   286
  };
deba@1820
   287
deba@1820
   288
deba@1820
   289
  template <typename _Base>
deba@1910
   290
  class IterableBpUGraphExtender : public _Base {
deba@1820
   291
  public:
deba@1820
   292
    typedef _Base Parent;
deba@1910
   293
    typedef IterableBpUGraphExtender Graph;
deba@1820
   294
   
deba@1820
   295
    typedef typename Parent::Node Node;
deba@1910
   296
    typedef typename Parent::ANode ANode;
deba@1910
   297
    typedef typename Parent::BNode BNode;
deba@1820
   298
    typedef typename Parent::Edge Edge;
klao@1909
   299
    typedef typename Parent::UEdge UEdge;
deba@1820
   300
  
deba@1820
   301
    class NodeIt : public Node { 
deba@1820
   302
      const Graph* graph;
deba@1820
   303
    public:
deba@1820
   304
    
deba@1820
   305
      NodeIt() { }
deba@1820
   306
    
deba@1820
   307
      NodeIt(Invalid i) : Node(INVALID) { }
deba@1820
   308
    
deba@1820
   309
      explicit NodeIt(const Graph& _graph) : graph(&_graph) {
deba@1820
   310
	graph->first(static_cast<Node&>(*this));
deba@1820
   311
      }
deba@1820
   312
deba@1820
   313
      NodeIt(const Graph& _graph, const Node& node) 
deba@1820
   314
	: Node(node), graph(&_graph) { }
deba@1820
   315
    
deba@1820
   316
      NodeIt& operator++() { 
deba@1820
   317
	graph->next(*this);
deba@1820
   318
	return *this; 
deba@1820
   319
      }
deba@1820
   320
deba@1820
   321
    };
deba@1820
   322
deba@1934
   323
    class ANodeIt : public Node { 
deba@1910
   324
      friend class IterableBpUGraphExtender;
deba@1820
   325
      const Graph* graph;
deba@1820
   326
    public:
deba@1820
   327
    
deba@1910
   328
      ANodeIt() { }
deba@1820
   329
    
deba@1910
   330
      ANodeIt(Invalid i) : Node(INVALID) { }
deba@1820
   331
    
deba@1910
   332
      explicit ANodeIt(const Graph& _graph) : graph(&_graph) {
deba@1910
   333
	graph->firstANode(static_cast<Node&>(*this));
deba@1820
   334
      }
deba@1820
   335
deba@1910
   336
      ANodeIt(const Graph& _graph, const Node& node) 
deba@1820
   337
	: Node(node), graph(&_graph) {}
deba@1820
   338
    
deba@1910
   339
      ANodeIt& operator++() { 
deba@1910
   340
	graph->nextANode(*this);
deba@1820
   341
	return *this; 
deba@1820
   342
      }
deba@1820
   343
    };
deba@1820
   344
deba@1934
   345
    class BNodeIt : public Node { 
deba@1910
   346
      friend class IterableBpUGraphExtender;
deba@1820
   347
      const Graph* graph;
deba@1820
   348
    public:
deba@1820
   349
    
deba@1910
   350
      BNodeIt() { }
deba@1820
   351
    
deba@1910
   352
      BNodeIt(Invalid i) : Node(INVALID) { }
deba@1820
   353
    
deba@1910
   354
      explicit BNodeIt(const Graph& _graph) : graph(&_graph) {
deba@1910
   355
	graph->firstBNode(static_cast<Node&>(*this));
deba@1820
   356
      }
deba@1820
   357
deba@1910
   358
      BNodeIt(const Graph& _graph, const Node& node) 
deba@1820
   359
	: Node(node), graph(&_graph) {}
deba@1820
   360
    
deba@1910
   361
      BNodeIt& operator++() { 
deba@1910
   362
	graph->nextBNode(*this);
deba@1820
   363
	return *this; 
deba@1820
   364
      }
deba@1820
   365
    };
deba@1820
   366
deba@1820
   367
    class EdgeIt : public Edge { 
deba@1910
   368
      friend class IterableBpUGraphExtender;
deba@1820
   369
      const Graph* graph;
deba@1820
   370
    public:
deba@1820
   371
    
deba@1820
   372
      EdgeIt() { }
deba@1820
   373
    
deba@1820
   374
      EdgeIt(Invalid i) : Edge(INVALID) { }
deba@1820
   375
    
deba@1820
   376
      explicit EdgeIt(const Graph& _graph) : graph(&_graph) {
deba@1820
   377
	graph->first(static_cast<Edge&>(*this));
deba@1820
   378
      }
deba@1820
   379
deba@1820
   380
      EdgeIt(const Graph& _graph, const Edge& edge) 
deba@1820
   381
	: Edge(edge), graph(&_graph) { }
deba@1820
   382
    
deba@1820
   383
      EdgeIt& operator++() { 
deba@1820
   384
	graph->next(*this);
deba@1820
   385
	return *this; 
deba@1820
   386
      }
deba@1820
   387
deba@1820
   388
    };
deba@1820
   389
klao@1909
   390
    class UEdgeIt : public UEdge { 
deba@1910
   391
      friend class IterableBpUGraphExtender;
deba@1820
   392
      const Graph* graph;
deba@1820
   393
    public:
deba@1820
   394
    
klao@1909
   395
      UEdgeIt() { }
deba@1820
   396
    
klao@1909
   397
      UEdgeIt(Invalid i) : UEdge(INVALID) { }
deba@1820
   398
    
klao@1909
   399
      explicit UEdgeIt(const Graph& _graph) : graph(&_graph) {
klao@1909
   400
	graph->first(static_cast<UEdge&>(*this));
deba@1820
   401
      }
deba@1820
   402
klao@1909
   403
      UEdgeIt(const Graph& _graph, const UEdge& edge) 
klao@1909
   404
	: UEdge(edge), graph(&_graph) { }
deba@1820
   405
    
klao@1909
   406
      UEdgeIt& operator++() { 
deba@1820
   407
	graph->next(*this);
deba@1820
   408
	return *this; 
deba@1820
   409
      }
deba@1820
   410
    };
deba@1820
   411
deba@1820
   412
    class OutEdgeIt : public Edge { 
deba@1910
   413
      friend class IterableBpUGraphExtender;
deba@1820
   414
      const Graph* graph;
deba@1820
   415
    public:
deba@1820
   416
    
deba@1820
   417
      OutEdgeIt() { }
deba@1820
   418
    
deba@1820
   419
      OutEdgeIt(Invalid i) : Edge(i) { }
deba@1820
   420
    
deba@1820
   421
      OutEdgeIt(const Graph& _graph, const Node& node) 
deba@1820
   422
	: graph(&_graph) {
deba@1820
   423
	graph->firstOut(*this, node);
deba@1820
   424
      }
deba@1820
   425
    
deba@1820
   426
      OutEdgeIt(const Graph& _graph, const Edge& edge) 
deba@1820
   427
	: Edge(edge), graph(&_graph) {}
deba@1820
   428
    
deba@1820
   429
      OutEdgeIt& operator++() { 
deba@1820
   430
	graph->nextOut(*this);
deba@1820
   431
	return *this; 
deba@1820
   432
      }
deba@1820
   433
deba@1820
   434
    };
deba@1820
   435
deba@1820
   436
deba@1820
   437
    class InEdgeIt : public Edge { 
deba@1910
   438
      friend class IterableBpUGraphExtender;
deba@1820
   439
      const Graph* graph;
deba@1820
   440
    public:
deba@1820
   441
    
deba@1820
   442
      InEdgeIt() { }
deba@1820
   443
    
deba@1820
   444
      InEdgeIt(Invalid i) : Edge(i) { }
deba@1820
   445
    
deba@1820
   446
      InEdgeIt(const Graph& _graph, const Node& node) 
deba@1820
   447
	: graph(&_graph) {
deba@1820
   448
	graph->firstIn(*this, node);
deba@1820
   449
      }
deba@1820
   450
    
deba@1820
   451
      InEdgeIt(const Graph& _graph, const Edge& edge) : 
deba@1820
   452
	Edge(edge), graph(&_graph) {}
deba@1820
   453
    
deba@1820
   454
      InEdgeIt& operator++() { 
deba@1820
   455
	graph->nextIn(*this);
deba@1820
   456
	return *this; 
deba@1820
   457
      }
deba@1820
   458
deba@1820
   459
    };
deba@1820
   460
  
deba@1820
   461
    /// \brief Base node of the iterator
deba@1820
   462
    ///
deba@1820
   463
    /// Returns the base node (ie. the source in this case) of the iterator
deba@1820
   464
    Node baseNode(const OutEdgeIt &e) const {
deba@1820
   465
      return Parent::source((Edge&)e);
deba@1820
   466
    }
deba@1820
   467
    /// \brief Running node of the iterator
deba@1820
   468
    ///
deba@1820
   469
    /// Returns the running node (ie. the target in this case) of the
deba@1820
   470
    /// iterator
deba@1820
   471
    Node runningNode(const OutEdgeIt &e) const {
deba@1820
   472
      return Parent::target((Edge&)e);
deba@1820
   473
    }
deba@1820
   474
  
deba@1820
   475
    /// \brief Base node of the iterator
deba@1820
   476
    ///
deba@1820
   477
    /// Returns the base node (ie. the target in this case) of the iterator
deba@1820
   478
    Node baseNode(const InEdgeIt &e) const {
deba@1820
   479
      return Parent::target((Edge&)e);
deba@1820
   480
    }
deba@1820
   481
    /// \brief Running node of the iterator
deba@1820
   482
    ///
deba@1820
   483
    /// Returns the running node (ie. the source in this case) of the
deba@1820
   484
    /// iterator
deba@1820
   485
    Node runningNode(const InEdgeIt &e) const {
deba@1820
   486
      return Parent::source((Edge&)e);
deba@1820
   487
    }
deba@1820
   488
  
klao@1909
   489
    class IncEdgeIt : public Parent::UEdge { 
deba@1910
   490
      friend class IterableBpUGraphExtender;
deba@1820
   491
      const Graph* graph;
deba@1820
   492
      bool direction;
deba@1820
   493
    public:
deba@1820
   494
    
deba@1820
   495
      IncEdgeIt() { }
deba@1820
   496
    
klao@1909
   497
      IncEdgeIt(Invalid i) : UEdge(i), direction(true) { }
deba@1820
   498
    
deba@1820
   499
      IncEdgeIt(const Graph& _graph, const Node &n) : graph(&_graph) {
deba@1820
   500
	graph->firstInc(*this, direction, n);
deba@1820
   501
      }
deba@1820
   502
klao@1909
   503
      IncEdgeIt(const Graph& _graph, const UEdge &ue, const Node &n)
klao@1909
   504
	: graph(&_graph), UEdge(ue) {
deba@1820
   505
	direction = (graph->source(ue) == n);
deba@1820
   506
      }
deba@1820
   507
deba@1820
   508
      IncEdgeIt& operator++() {
deba@1820
   509
	graph->nextInc(*this, direction);
deba@1820
   510
	return *this; 
deba@1820
   511
      }
deba@1820
   512
    };
deba@1820
   513
  
deba@1820
   514
deba@1820
   515
    /// Base node of the iterator
deba@1820
   516
    ///
deba@1820
   517
    /// Returns the base node of the iterator
deba@1820
   518
    Node baseNode(const IncEdgeIt &e) const {
deba@1820
   519
      return e.direction ? source(e) : target(e);
deba@1820
   520
    }
deba@1820
   521
deba@1820
   522
    /// Running node of the iterator
deba@1820
   523
    ///
deba@1820
   524
    /// Returns the running node of the iterator
deba@1820
   525
    Node runningNode(const IncEdgeIt &e) const {
deba@1820
   526
      return e.direction ? target(e) : source(e);
deba@1820
   527
    }
deba@1820
   528
  
deba@1820
   529
  };
deba@1820
   530
klao@946
   531
}
klao@946
   532
klao@946
   533
#endif // LEMON_GRAPH_EXTENDER_H