lemon/bits/graph_extender.h
author alpar
Wed, 16 Nov 2005 13:19:05 +0000
changeset 1805 d284f81f02a5
child 1820 22099ef840d7
permissions -rw-r--r--
Iterable Bool maps can count the number of true and false values.
deba@1791
     1
/* -*- C++ -*-
deba@1791
     2
 * lemon/graph_extender.h - Part of LEMON, a generic C++ optimization library
deba@1791
     3
 *
deba@1791
     4
 * Copyright (C) 2005 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@1791
    22
deba@1791
    23
namespace lemon {
deba@1791
    24
deba@1791
    25
  template <typename _Base>
deba@1791
    26
  class GraphExtender : public _Base {
deba@1791
    27
  public:
deba@1791
    28
deba@1791
    29
    typedef _Base Parent;
deba@1791
    30
    typedef GraphExtender Graph;
deba@1791
    31
deba@1791
    32
    typedef typename Parent::Node Node;
deba@1791
    33
    typedef typename Parent::Edge Edge;
deba@1791
    34
deba@1791
    35
    int maxId(Node) const {
deba@1791
    36
      return Parent::maxNodeId();
deba@1791
    37
    }
deba@1791
    38
deba@1791
    39
    int maxId(Edge) const {
deba@1791
    40
      return Parent::maxEdgeId();
deba@1791
    41
    }
deba@1791
    42
deba@1791
    43
    Node fromId(int id, Node) const {
deba@1791
    44
      return Parent::nodeFromId(id);
deba@1791
    45
    }
deba@1791
    46
deba@1791
    47
    Edge fromId(int id, Edge) const {
deba@1791
    48
      return Parent::edgeFromId(id);
deba@1791
    49
    }
deba@1791
    50
deba@1791
    51
    Node oppositeNode(const Node &n, const Edge &e) const {
deba@1791
    52
      if (n == Parent::source(e))
deba@1791
    53
	return Parent::target(e);
deba@1791
    54
      else if(n==Parent::target(e))
deba@1791
    55
	return Parent::source(e);
deba@1791
    56
      else
deba@1791
    57
	return INVALID;
deba@1791
    58
    }
deba@1791
    59
deba@1791
    60
  };
deba@1791
    61
deba@1791
    62
  template <typename _Base>
deba@1791
    63
  class UndirGraphExtender : public _Base {
deba@1791
    64
    typedef _Base Parent;
deba@1791
    65
    typedef UndirGraphExtender Graph;
deba@1791
    66
deba@1791
    67
  public:
deba@1791
    68
deba@1791
    69
    typedef typename Parent::Edge UndirEdge;
deba@1791
    70
    typedef typename Parent::Node Node;
deba@1791
    71
deba@1791
    72
    class Edge : public UndirEdge {
deba@1791
    73
      friend class UndirGraphExtender;
deba@1791
    74
deba@1791
    75
    protected:
deba@1791
    76
      // FIXME: Marci use opposite logic in his graph adaptors. It would
deba@1791
    77
      // be reasonable to syncronize...
deba@1791
    78
      bool forward;
deba@1791
    79
deba@1791
    80
      Edge(const UndirEdge &ue, bool _forward) :
deba@1791
    81
        UndirEdge(ue), forward(_forward) {}
deba@1791
    82
deba@1791
    83
    public:
deba@1791
    84
      Edge() {}
deba@1791
    85
deba@1791
    86
      /// Invalid edge constructor
deba@1791
    87
      Edge(Invalid i) : UndirEdge(i), forward(true) {}
deba@1791
    88
deba@1791
    89
      bool operator==(const Edge &that) const {
deba@1791
    90
	return forward==that.forward && UndirEdge(*this)==UndirEdge(that);
deba@1791
    91
      }
deba@1791
    92
      bool operator!=(const Edge &that) const {
deba@1791
    93
	return forward!=that.forward || UndirEdge(*this)!=UndirEdge(that);
deba@1791
    94
      }
deba@1791
    95
      bool operator<(const Edge &that) const {
deba@1791
    96
	return forward<that.forward ||
deba@1791
    97
	  (!(that.forward<forward) && UndirEdge(*this)<UndirEdge(that));
deba@1791
    98
      }
deba@1791
    99
    };
deba@1791
   100
deba@1791
   101
deba@1791
   102
    /// \brief Edge of opposite direction.
deba@1791
   103
    ///
deba@1791
   104
    /// Returns the Edge of opposite direction.
deba@1791
   105
    Edge oppositeEdge(const Edge &e) const {
deba@1791
   106
      return Edge(e,!e.forward);
deba@1791
   107
    }
deba@1791
   108
deba@1791
   109
  public:
deba@1791
   110
    /// \todo Shouldn't the "source" of an undirected edge be called "aNode"
deba@1791
   111
    /// or something???
deba@1791
   112
    using Parent::source;
deba@1791
   113
deba@1791
   114
    /// Source of the given Edge.
deba@1791
   115
    Node source(const Edge &e) const {
deba@1791
   116
      return e.forward ? Parent::source(e) : Parent::target(e);
deba@1791
   117
    }
deba@1791
   118
deba@1791
   119
    /// \todo Shouldn't the "target" of an undirected edge be called "bNode"
deba@1791
   120
    /// or something???
deba@1791
   121
    using Parent::target;
deba@1791
   122
deba@1791
   123
    /// Target of the given Edge.
deba@1791
   124
    Node target(const Edge &e) const {
deba@1791
   125
      return e.forward ? Parent::target(e) : Parent::source(e);
deba@1791
   126
    }
deba@1791
   127
deba@1791
   128
    Node oppositeNode(const Node &n, const UndirEdge &e) const {
deba@1791
   129
      if( n == Parent::source(e))
deba@1791
   130
	return Parent::target(e);
deba@1791
   131
      else if( n == Parent::target(e))
deba@1791
   132
	return Parent::source(e);
deba@1791
   133
      else
deba@1791
   134
	return INVALID;
deba@1791
   135
    }
deba@1791
   136
deba@1791
   137
    /// \brief Directed edge from an undirected edge and a source node.
deba@1791
   138
    ///
deba@1791
   139
    /// Returns a (directed) Edge corresponding to the specified UndirEdge
deba@1791
   140
    /// and source Node.
deba@1791
   141
    ///
deba@1791
   142
    Edge direct(const UndirEdge &ue, const Node &s) const {
deba@1791
   143
      return Edge(ue, s == source(ue));
deba@1791
   144
    }
deba@1791
   145
deba@1791
   146
    /// \brief Directed edge from an undirected edge.
deba@1791
   147
    ///
deba@1791
   148
    /// Returns a directed edge corresponding to the specified UndirEdge.
deba@1791
   149
    /// If the given bool is true the given undirected edge and the
deba@1791
   150
    /// returned edge have the same source node.
deba@1791
   151
    Edge direct(const UndirEdge &ue, bool d) const {
deba@1791
   152
      return Edge(ue, d);
deba@1791
   153
    }
deba@1791
   154
deba@1791
   155
    /// Returns whether the given directed edge is same orientation as the
deba@1791
   156
    /// corresponding undirected edge.
deba@1791
   157
    ///
deba@1791
   158
    /// \todo reference to the corresponding point of the undirected graph
deba@1791
   159
    /// concept. "What does the direction of an undirected edge mean?"
deba@1791
   160
    bool direction(const Edge &e) const { return e.forward; }
deba@1791
   161
deba@1791
   162
deba@1791
   163
    using Parent::first;
deba@1791
   164
    void first(Edge &e) const {
deba@1791
   165
      Parent::first(e);
deba@1791
   166
      e.forward=true;
deba@1791
   167
    }
deba@1791
   168
deba@1791
   169
    using Parent::next;
deba@1791
   170
    void next(Edge &e) const {
deba@1791
   171
      if( e.forward ) {
deba@1791
   172
	e.forward = false;
deba@1791
   173
      }
deba@1791
   174
      else {
deba@1791
   175
	Parent::next(e);
deba@1791
   176
	e.forward = true;
deba@1791
   177
      }
deba@1791
   178
    }
deba@1791
   179
deba@1791
   180
  public:
deba@1791
   181
deba@1791
   182
    void firstOut(Edge &e, const Node &n) const {
deba@1791
   183
      Parent::firstIn(e,n);
deba@1791
   184
      if( UndirEdge(e) != INVALID ) {
deba@1791
   185
	e.forward = false;
deba@1791
   186
      }
deba@1791
   187
      else {
deba@1791
   188
	Parent::firstOut(e,n);
deba@1791
   189
	e.forward = true;
deba@1791
   190
      }
deba@1791
   191
    }
deba@1791
   192
    void nextOut(Edge &e) const {
deba@1791
   193
      if( ! e.forward ) {
deba@1791
   194
	Node n = Parent::target(e);
deba@1791
   195
	Parent::nextIn(e);
deba@1791
   196
	if( UndirEdge(e) == INVALID ) {
deba@1791
   197
	  Parent::firstOut(e, n);
deba@1791
   198
	  e.forward = true;
deba@1791
   199
	}
deba@1791
   200
      }
deba@1791
   201
      else {
deba@1791
   202
	Parent::nextOut(e);
deba@1791
   203
      }
deba@1791
   204
    }
deba@1791
   205
deba@1791
   206
    void firstIn(Edge &e, const Node &n) const {
deba@1791
   207
      Parent::firstOut(e,n);
deba@1791
   208
      if( UndirEdge(e) != INVALID ) {
deba@1791
   209
	e.forward = false;
deba@1791
   210
      }
deba@1791
   211
      else {
deba@1791
   212
	Parent::firstIn(e,n);
deba@1791
   213
	e.forward = true;
deba@1791
   214
      }
deba@1791
   215
    }
deba@1791
   216
    void nextIn(Edge &e) const {
deba@1791
   217
      if( ! e.forward ) {
deba@1791
   218
	Node n = Parent::source(e);
deba@1791
   219
	Parent::nextOut(e);
deba@1791
   220
	if( UndirEdge(e) == INVALID ) {
deba@1791
   221
	  Parent::firstIn(e, n);
deba@1791
   222
	  e.forward = true;
deba@1791
   223
	}
deba@1791
   224
      }
deba@1791
   225
      else {
deba@1791
   226
	Parent::nextIn(e);
deba@1791
   227
      }
deba@1791
   228
    }
deba@1791
   229
deba@1791
   230
    void firstInc(UndirEdge &e, const Node &n) const {
deba@1791
   231
      Parent::firstOut(e, n);
deba@1791
   232
      if (e != INVALID) return;
deba@1791
   233
      Parent::firstIn(e, n);
deba@1791
   234
    }
deba@1791
   235
    void nextInc(UndirEdge &e, const Node &n) const {
deba@1791
   236
      if (Parent::source(e) == n) {
deba@1791
   237
	Parent::nextOut(e);
deba@1791
   238
	if (e != INVALID) return;
deba@1791
   239
	Parent::firstIn(e, n);
deba@1791
   240
      } else {
deba@1791
   241
	Parent::nextIn(e);
deba@1791
   242
      }
deba@1791
   243
    }
deba@1791
   244
deba@1791
   245
    void firstInc(UndirEdge &e, bool &d, const Node &n) const {
deba@1791
   246
      d = true;
deba@1791
   247
      Parent::firstOut(e, n);
deba@1791
   248
      if (e != INVALID) return;
deba@1791
   249
      d = false;
deba@1791
   250
      Parent::firstIn(e, n);
deba@1791
   251
    }
deba@1791
   252
    void nextInc(UndirEdge &e, bool &d) const {
deba@1791
   253
      if (d) {
deba@1791
   254
	Node s = Parent::source(e);
deba@1791
   255
	Parent::nextOut(e);
deba@1791
   256
	if (e != INVALID) return;
deba@1791
   257
	d = false;
deba@1791
   258
	Parent::firstIn(e, s);
deba@1791
   259
      } else {
deba@1791
   260
	Parent::nextIn(e);
deba@1791
   261
      }
deba@1791
   262
    }
deba@1791
   263
deba@1791
   264
    // Miscellaneous stuff:
deba@1791
   265
deba@1791
   266
    /// \todo these methods (id, maxEdgeId) should be moved into separate
deba@1791
   267
    /// Extender
deba@1791
   268
deba@1791
   269
    // using Parent::id;
deba@1791
   270
    // Using "using" is not a good idea, cause it could be that there is
deba@1791
   271
    // no "id" in Parent...
deba@1791
   272
deba@1791
   273
    int id(const Node &n) const {
deba@1791
   274
      return Parent::id(n);
deba@1791
   275
    }
deba@1791
   276
deba@1791
   277
    int id(const UndirEdge &e) const {
deba@1791
   278
      return Parent::id(e);
deba@1791
   279
    }
deba@1791
   280
deba@1791
   281
    int id(const Edge &e) const {
deba@1791
   282
      return 2 * Parent::id(e) + int(e.forward);
deba@1791
   283
    }
deba@1791
   284
deba@1791
   285
    int maxNodeId() const {
deba@1791
   286
      return Parent::maxNodeId();
deba@1791
   287
    }
deba@1791
   288
deba@1791
   289
    int maxEdgeId() const {
deba@1791
   290
      return 2 * Parent::maxEdgeId() + 1;
deba@1791
   291
    }
deba@1791
   292
deba@1791
   293
    int maxUndirEdgeId() const {
deba@1791
   294
      return Parent::maxEdgeId();
deba@1791
   295
    }
deba@1791
   296
deba@1791
   297
    int maxId(Node) const {
deba@1791
   298
      return maxNodeId();
deba@1791
   299
    }
deba@1791
   300
deba@1791
   301
    int maxId(Edge) const {
deba@1791
   302
      return maxEdgeId();
deba@1791
   303
    }
deba@1791
   304
    int maxId(UndirEdge) const {
deba@1791
   305
      return maxUndirEdgeId();
deba@1791
   306
    }
deba@1791
   307
deba@1791
   308
    int edgeNum() const {
deba@1791
   309
      return 2 * Parent::edgeNum();
deba@1791
   310
    }
deba@1791
   311
deba@1791
   312
    int undirEdgeNum() const {
deba@1791
   313
      return Parent::edgeNum();
deba@1791
   314
    }
deba@1791
   315
deba@1791
   316
    Node nodeFromId(int id) const {
deba@1791
   317
      return Parent::nodeFromId(id);
deba@1791
   318
    }
deba@1791
   319
deba@1791
   320
    Edge edgeFromId(int id) const {
deba@1791
   321
      return direct(Parent::edgeFromId(id >> 1), bool(id & 1));
deba@1791
   322
    }
deba@1791
   323
deba@1791
   324
    UndirEdge undirEdgeFromId(int id) const {
deba@1791
   325
      return Parent::edgeFromId(id >> 1);
deba@1791
   326
    }
deba@1791
   327
deba@1791
   328
    Node fromId(int id, Node) const {
deba@1791
   329
      return nodeFromId(id);
deba@1791
   330
    }
deba@1791
   331
deba@1791
   332
    Edge fromId(int id, Edge) const {
deba@1791
   333
      return edgeFromId(id);
deba@1791
   334
    }
deba@1791
   335
deba@1791
   336
    UndirEdge fromId(int id, UndirEdge) const {
deba@1791
   337
      return undirEdgeFromId(id);
deba@1791
   338
    }
deba@1791
   339
deba@1791
   340
deba@1791
   341
    Edge findEdge(Node source, Node target, Edge prev) const {
deba@1791
   342
      if (prev == INVALID) {
deba@1791
   343
	UndirEdge edge = Parent::findEdge(source, target);
deba@1791
   344
	if (edge != INVALID) return direct(edge, true);
deba@1791
   345
	edge = Parent::findEdge(target, source);
deba@1791
   346
	if (edge != INVALID) return direct(edge, false);
deba@1791
   347
      } else if (direction(prev)) {
deba@1791
   348
	UndirEdge edge = Parent::findEdge(source, target, prev);
deba@1791
   349
	if (edge != INVALID) return direct(edge, true);
deba@1791
   350
	edge = Parent::findEdge(target, source);
deba@1791
   351
	if (edge != INVALID) return direct(edge, false);	
deba@1791
   352
      } else {
deba@1791
   353
	UndirEdge edge = Parent::findEdge(target, source, prev);
deba@1791
   354
	if (edge != INVALID) return direct(edge, false);	      
deba@1791
   355
      }
deba@1791
   356
      return INVALID;
deba@1791
   357
    }
deba@1791
   358
deba@1791
   359
    UndirEdge findUndirEdge(Node source, Node target, UndirEdge prev) const {
deba@1791
   360
      if (prev == INVALID) {
deba@1791
   361
	UndirEdge edge = Parent::findEdge(source, target);
deba@1791
   362
	if (edge != INVALID) return edge;
deba@1791
   363
	edge = Parent::findEdge(target, source);
deba@1791
   364
	if (edge != INVALID) return edge;
deba@1791
   365
      } else if (Parent::source(prev) == source) {
deba@1791
   366
	UndirEdge edge = Parent::findEdge(source, target, prev);
deba@1791
   367
	if (edge != INVALID) return edge;
deba@1791
   368
	edge = Parent::findEdge(target, source);
deba@1791
   369
	if (edge != INVALID) return edge;	
deba@1791
   370
      } else {
deba@1791
   371
	UndirEdge edge = Parent::findEdge(target, source, prev);
deba@1791
   372
	if (edge != INVALID) return edge;	      
deba@1791
   373
      }
deba@1791
   374
      return INVALID;
deba@1791
   375
    }
deba@1791
   376
deba@1791
   377
  };
deba@1791
   378
deba@1791
   379
}
deba@1791
   380
deba@1791
   381
#endif // LEMON_UNDIR_GRAPH_EXTENDER_H