src/hugo/smart_graph.h
author alpar
Tue, 28 Sep 2004 07:00:58 +0000
changeset 911 89a4fbb99cad
parent 906 17f31d280385
child 916 c0734a8c282c
permissions -rw-r--r--
Fix many doxygen command bugs.
alpar@906
     1
/* -*- C++ -*-
alpar@906
     2
 * src/hugo/smart_graph.h - Part of HUGOlib, a generic C++ optimization library
alpar@906
     3
 *
alpar@906
     4
 * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@906
     5
 * (Egervary Combinatorial Optimization Research Group, EGRES).
alpar@906
     6
 *
alpar@906
     7
 * Permission to use, modify and distribute this software is granted
alpar@906
     8
 * provided that this copyright notice appears in all copies. For
alpar@906
     9
 * precise terms see the accompanying LICENSE file.
alpar@906
    10
 *
alpar@906
    11
 * This software is provided "AS IS" with no warranty of any kind,
alpar@906
    12
 * express or implied, and with no claim as to its suitability for any
alpar@906
    13
 * purpose.
alpar@906
    14
 *
alpar@906
    15
 */
alpar@105
    16
alpar@185
    17
#ifndef HUGO_SMART_GRAPH_H
alpar@185
    18
#define HUGO_SMART_GRAPH_H
alpar@104
    19
klao@491
    20
///\ingroup graphs
alpar@242
    21
///\file
alpar@242
    22
///\brief SmartGraph and SymSmartGraph classes.
alpar@242
    23
alpar@104
    24
#include <vector>
deba@782
    25
#include <climits>
alpar@104
    26
ladanyi@542
    27
#include <hugo/invalid.h>
alpar@157
    28
deba@897
    29
#include <hugo/array_map.h>
deba@782
    30
#include <hugo/map_registry.h>
deba@782
    31
deba@782
    32
#include <hugo/map_defines.h>
deba@782
    33
alpar@105
    34
namespace hugo {
alpar@104
    35
alpar@407
    36
/// \addtogroup graphs
alpar@407
    37
/// @{
deba@782
    38
//  class SymSmartGraph;
alpar@185
    39
alpar@186
    40
  ///A smart graph class.
alpar@186
    41
alpar@186
    42
  ///This is a simple and fast graph implementation.
alpar@186
    43
  ///It is also quite memory efficient, but at the price
alpar@186
    44
  ///that <b> it does not support node and edge deletion</b>.
alpar@880
    45
  ///It conforms to 
alpar@880
    46
  ///the \ref skeleton::ExtendableGraph "ExtendableGraph" concept.
alpar@880
    47
  ///\sa skeleton::ExtendableGraph.
alpar@402
    48
  ///
alpar@402
    49
  ///\todo Some member functions could be \c static.
alpar@753
    50
  ///
alpar@753
    51
  ///\todo A possibly useful functionality: a function saveState() would
alpar@753
    52
  ///give back a data sturcture X and then the function restoreState(X)
alpar@753
    53
  ///would remove the nodes and edges added after the call of saveState().
alpar@753
    54
  ///Of course it should be used as a stack. (Maybe X is not necessary.)
alpar@753
    55
  ///
alpar@456
    56
  ///\author Alpar Juttner
alpar@104
    57
  class SmartGraph {
alpar@104
    58
alpar@104
    59
    struct NodeT 
alpar@104
    60
    {
alpar@104
    61
      int first_in,first_out;      
alpar@157
    62
      NodeT() : first_in(-1), first_out(-1) {}
alpar@104
    63
    };
alpar@104
    64
    struct EdgeT 
alpar@104
    65
    {
alpar@104
    66
      int head, tail, next_in, next_out;      
alpar@104
    67
      //FIXME: is this necessary?
alpar@157
    68
      EdgeT() : next_in(-1), next_out(-1) {}  
alpar@104
    69
    };
alpar@104
    70
alpar@104
    71
    std::vector<NodeT> nodes;
alpar@129
    72
alpar@104
    73
    std::vector<EdgeT> edges;
alpar@104
    74
    
alpar@185
    75
    
alpar@104
    76
  public:
deba@782
    77
deba@782
    78
    typedef SmartGraph Graph;
alpar@104
    79
alpar@164
    80
    class Node;
alpar@164
    81
    class Edge;
alpar@108
    82
alpar@164
    83
    class NodeIt;
alpar@164
    84
    class EdgeIt;
alpar@104
    85
    class OutEdgeIt;
alpar@104
    86
    class InEdgeIt;
alpar@104
    87
    
alpar@904
    88
    // Create map registries.
deba@782
    89
    CREATE_MAP_REGISTRIES;
alpar@904
    90
    // Create node and edge maps.
deba@897
    91
    CREATE_MAPS(ArrayMap);
alpar@104
    92
    
alpar@104
    93
  public:
alpar@104
    94
alpar@104
    95
    SmartGraph() : nodes(), edges() { }
alpar@136
    96
    SmartGraph(const SmartGraph &_g) : nodes(_g.nodes), edges(_g.edges) { }
alpar@104
    97
    
alpar@813
    98
    ///Number of nodes.
alpar@813
    99
    int nodeNum() const { return nodes.size(); }
alpar@813
   100
    ///Number of edges.
alpar@813
   101
    int edgeNum() const { return edges.size(); }
alpar@104
   102
alpar@813
   103
    /// Maximum node ID.
alpar@813
   104
    
alpar@813
   105
    /// Maximum node ID.
alpar@813
   106
    ///\sa id(Node)
alpar@813
   107
    int maxNodeId() const { return nodes.size()-1; }
alpar@813
   108
    /// Maximum edge ID.
alpar@813
   109
    
alpar@813
   110
    /// Maximum edge ID.
alpar@813
   111
    ///\sa id(Edge)
alpar@813
   112
    int maxEdgeId() const { return edges.size()-1; }
alpar@108
   113
alpar@164
   114
    Node tail(Edge e) const { return edges[e.n].tail; }
alpar@164
   115
    Node head(Edge e) const { return edges[e.n].head; }
alpar@104
   116
alpar@164
   117
    NodeIt& first(NodeIt& v) const { 
alpar@164
   118
      v=NodeIt(*this); return v; }
alpar@164
   119
    EdgeIt& first(EdgeIt& e) const { 
alpar@164
   120
      e=EdgeIt(*this); return e; }
alpar@164
   121
    OutEdgeIt& first(OutEdgeIt& e, const Node v) const { 
alpar@104
   122
      e=OutEdgeIt(*this,v); return e; }
alpar@164
   123
    InEdgeIt& first(InEdgeIt& e, const Node v) const { 
alpar@104
   124
      e=InEdgeIt(*this,v); return e; }
alpar@104
   125
alpar@813
   126
    /// Node ID.
alpar@813
   127
    
alpar@813
   128
    /// The ID of a valid Node is a nonnegative integer not greater than
alpar@813
   129
    /// \ref maxNodeId(). The range of the ID's is not surely continuous
alpar@813
   130
    /// and the greatest node ID can be actually less then \ref maxNodeId().
alpar@813
   131
    ///
alpar@813
   132
    /// The ID of the \ref INVALID node is -1.
alpar@813
   133
    ///\return The ID of the node \c v. 
alpar@713
   134
    static int id(Node v) { return v.n; }
alpar@813
   135
    /// Edge ID.
alpar@813
   136
    
alpar@813
   137
    /// The ID of a valid Edge is a nonnegative integer not greater than
alpar@813
   138
    /// \ref maxEdgeId(). The range of the ID's is not surely continuous
alpar@813
   139
    /// and the greatest edge ID can be actually less then \ref maxEdgeId().
alpar@813
   140
    ///
alpar@813
   141
    /// The ID of the \ref INVALID edge is -1.
alpar@813
   142
    ///\return The ID of the edge \c e. 
alpar@713
   143
    static int id(Edge e) { return e.n; }
alpar@104
   144
alpar@164
   145
    Node addNode() {
alpar@164
   146
      Node n; n.n=nodes.size();
alpar@104
   147
      nodes.push_back(NodeT()); //FIXME: Hmmm...
alpar@108
   148
deba@782
   149
      
deba@782
   150
      node_maps.add(n);
alpar@104
   151
      return n;
alpar@104
   152
    }
alpar@108
   153
    
alpar@164
   154
    Edge addEdge(Node u, Node v) {
alpar@164
   155
      Edge e; e.n=edges.size(); edges.push_back(EdgeT()); //FIXME: Hmmm...
alpar@104
   156
      edges[e.n].tail=u.n; edges[e.n].head=v.n;
alpar@104
   157
      edges[e.n].next_out=nodes[u.n].first_out;
alpar@104
   158
      edges[e.n].next_in=nodes[v.n].first_in;
alpar@104
   159
      nodes[u.n].first_out=nodes[v.n].first_in=e.n;
alpar@108
   160
deba@782
   161
      edge_maps.add(e);
alpar@108
   162
alpar@104
   163
      return e;
alpar@104
   164
    }
alpar@104
   165
alpar@774
   166
    /// Finds an edge between two nodes.
alpar@774
   167
alpar@774
   168
    /// Finds an edge from node \c u to node \c v.
alpar@774
   169
    ///
alpar@774
   170
    /// If \c prev is \ref INVALID (this is the default value), then
alpar@774
   171
    /// It finds the first edge from \c u to \c v. Otherwise it looks for
alpar@774
   172
    /// the next edge from \c u to \c v after \c prev.
alpar@774
   173
    /// \return The found edge or INVALID if there is no such an edge.
alpar@774
   174
    Edge findEdge(Node u,Node v, Edge prev = INVALID) 
alpar@774
   175
    {
alpar@774
   176
      int e = (prev.n==-1)? nodes[u.n].first_out : edges[prev.n].next_out;
alpar@774
   177
      while(e!=-1 && edges[e].tail!=v.n) e = edges[e].next_out;
alpar@774
   178
      prev.n=e;
alpar@774
   179
      return prev;
alpar@774
   180
    }
alpar@774
   181
    
deba@782
   182
    void clear() {
deba@782
   183
      edge_maps.clear();
deba@782
   184
      edges.clear();
deba@782
   185
      node_maps.clear();
deba@782
   186
      nodes.clear();
deba@782
   187
    }
alpar@104
   188
alpar@164
   189
    class Node {
alpar@104
   190
      friend class SmartGraph;
alpar@104
   191
      template <typename T> friend class NodeMap;
alpar@104
   192
      
alpar@164
   193
      friend class Edge;
alpar@104
   194
      friend class OutEdgeIt;
alpar@104
   195
      friend class InEdgeIt;
alpar@164
   196
      friend class SymEdge;
alpar@104
   197
alpar@104
   198
    protected:
alpar@104
   199
      int n;
alpar@722
   200
      friend int SmartGraph::id(Node v); 
alpar@164
   201
      Node(int nn) {n=nn;}
alpar@104
   202
    public:
alpar@164
   203
      Node() {}
alpar@503
   204
      Node (Invalid) { n=-1; }
alpar@164
   205
      bool operator==(const Node i) const {return n==i.n;}
alpar@164
   206
      bool operator!=(const Node i) const {return n!=i.n;}
alpar@164
   207
      bool operator<(const Node i) const {return n<i.n;}
alpar@774
   208
      //      ///Validity check
alpar@774
   209
      //      operator bool() { return n!=-1; }
alpar@104
   210
    };
alpar@104
   211
    
alpar@164
   212
    class NodeIt : public Node {
alpar@774
   213
      const SmartGraph *G;
alpar@104
   214
      friend class SmartGraph;
alpar@104
   215
    public:
alpar@402
   216
      NodeIt() : Node() { }
alpar@774
   217
      NodeIt(const SmartGraph& _G,Node n) : Node(n), G(&_G) { }
alpar@402
   218
      NodeIt(Invalid i) : Node(i) { }
alpar@774
   219
      NodeIt(const SmartGraph& _G) : Node(_G.nodes.size()?0:-1), G(&_G) { }
alpar@774
   220
      NodeIt &operator++() {
alpar@774
   221
	n=(n+2)%(G->nodes.size()+1)-1; 
alpar@774
   222
	return *this; 
alpar@774
   223
      }
alpar@774
   224
//       ///Validity check
alpar@774
   225
//       operator bool() { return Node::operator bool(); }      
alpar@104
   226
    };
alpar@104
   227
alpar@164
   228
    class Edge {
alpar@104
   229
      friend class SmartGraph;
alpar@104
   230
      template <typename T> friend class EdgeMap;
alpar@185
   231
alpar@905
   232
      friend class SymSmartGraph;
alpar@104
   233
      
alpar@164
   234
      friend class Node;
alpar@104
   235
      friend class NodeIt;
alpar@104
   236
    protected:
alpar@104
   237
      int n;
alpar@722
   238
      friend int SmartGraph::id(Edge e);
alpar@905
   239
      Edge(int nn) {n=nn;}
alpar@706
   240
    public:
alpar@706
   241
      /// An Edge with id \c n.
alpar@706
   242
alpar@164
   243
      Edge() { }
marci@174
   244
      Edge (Invalid) { n=-1; }
alpar@164
   245
      bool operator==(const Edge i) const {return n==i.n;}
alpar@164
   246
      bool operator!=(const Edge i) const {return n!=i.n;}
alpar@164
   247
      bool operator<(const Edge i) const {return n<i.n;}
alpar@774
   248
//       ///Validity check
alpar@774
   249
//       operator bool() { return n!=-1; }
alpar@905
   250
alpar@905
   251
      ///Set the edge to that have ID \c ID.
alpar@905
   252
      void setToId(int id) { n=id; }
alpar@774
   253
   };
alpar@104
   254
    
alpar@164
   255
    class EdgeIt : public Edge {
alpar@774
   256
      const SmartGraph *G;
alpar@104
   257
      friend class SmartGraph;
alpar@104
   258
    public:
alpar@774
   259
      EdgeIt(const SmartGraph& _G) : Edge(_G.edges.size()-1), G(&_G) { }
alpar@774
   260
      EdgeIt(const SmartGraph& _G, Edge e) : Edge(e), G(&_G) { }
alpar@164
   261
      EdgeIt (Invalid i) : Edge(i) { }
alpar@164
   262
      EdgeIt() : Edge() { }
alpar@774
   263
      EdgeIt &operator++() { --n; return *this; }
alpar@774
   264
//       ///Validity check
alpar@774
   265
//       operator bool() { return Edge::operator bool(); }      
alpar@104
   266
    };
alpar@104
   267
    
alpar@164
   268
    class OutEdgeIt : public Edge {
alpar@774
   269
      const SmartGraph *G;
alpar@104
   270
      friend class SmartGraph;
alpar@104
   271
    public: 
alpar@164
   272
      OutEdgeIt() : Edge() { }
alpar@774
   273
      OutEdgeIt(const SmartGraph& _G, Edge e) : Edge(e), G(&_G) { }
alpar@164
   274
      OutEdgeIt (Invalid i) : Edge(i) { }
alpar@157
   275
alpar@774
   276
      OutEdgeIt(const SmartGraph& _G,const Node v)
alpar@774
   277
	: Edge(_G.nodes[v.n].first_out), G(&_G) {}
alpar@774
   278
      OutEdgeIt &operator++() { n=G->edges[n].next_out; return *this; }
alpar@774
   279
//       ///Validity check
alpar@774
   280
//       operator bool() { return Edge::operator bool(); }      
alpar@104
   281
    };
alpar@104
   282
    
alpar@164
   283
    class InEdgeIt : public Edge {
alpar@774
   284
      const SmartGraph *G;
alpar@104
   285
      friend class SmartGraph;
alpar@104
   286
    public: 
alpar@164
   287
      InEdgeIt() : Edge() { }
alpar@774
   288
      InEdgeIt(const SmartGraph& _G, Edge e) : Edge(e), G(&_G) { }
alpar@164
   289
      InEdgeIt (Invalid i) : Edge(i) { }
alpar@774
   290
      InEdgeIt(const SmartGraph& _G,Node v)
alpar@774
   291
	: Edge(_G.nodes[v.n].first_in), G(&_G) { }
alpar@774
   292
      InEdgeIt &operator++() { n=G->edges[n].next_in; return *this; }
alpar@774
   293
//       ///Validity check
alpar@774
   294
//       operator bool() { return Edge::operator bool(); }      
alpar@104
   295
    };
alpar@105
   296
alpar@104
   297
  };
alpar@185
   298
deba@909
   299
deba@909
   300
deba@909
   301
  class SymSmartGraph : public SmartGraph {
deba@909
   302
    typedef SmartGraph Parent;
deba@909
   303
  public:
deba@909
   304
deba@909
   305
    typedef SymSmartGraph Graph;
deba@909
   306
deba@909
   307
    typedef SmartGraph::Node Node;
deba@909
   308
    typedef SmartGraph::NodeIt NodeIt;
deba@909
   309
deba@909
   310
    class SymEdge;
deba@909
   311
    class SymEdgeIt;
deba@909
   312
deba@909
   313
    class Edge;
deba@909
   314
    class EdgeIt;
deba@909
   315
    class OutEdgeIt;
deba@909
   316
    class InEdgeIt;
deba@909
   317
deba@909
   318
    template <typename Value>
deba@909
   319
    class NodeMap : public Parent::NodeMap<Value> {      
deba@909
   320
    public:
deba@909
   321
      NodeMap(const SymSmartGraph& g) 
deba@909
   322
	: SymSmartGraph::Parent::NodeMap<Value>(g) {}
deba@909
   323
      NodeMap(const SymSmartGraph& g, Value v) 
deba@909
   324
	: SymSmartGraph::Parent::NodeMap<Value>(g, v) {}
deba@909
   325
      template<typename TT> 
deba@909
   326
      NodeMap(const NodeMap<TT>& copy) 
deba@909
   327
	: SymSmartGraph::Parent::NodeMap<Value>(copy) { }            
deba@909
   328
    };
deba@909
   329
deba@909
   330
    template <typename Value>
deba@909
   331
    class SymEdgeMap : public Parent::EdgeMap<Value> {
deba@909
   332
    public:
deba@909
   333
      typedef SymEdge KeyType;
deba@909
   334
deba@909
   335
      SymEdgeMap(const SymSmartGraph& g) 
deba@909
   336
	: SymSmartGraph::Parent::EdgeMap<Value>(g) {}
deba@909
   337
      SymEdgeMap(const SymSmartGraph& g, Value v) 
deba@909
   338
	: SymSmartGraph::Parent::EdgeMap<Value>(g, v) {}
deba@909
   339
      template<typename TT> 
deba@909
   340
      SymEdgeMap(const SymEdgeMap<TT>& copy) 
deba@909
   341
	: SymSmartGraph::Parent::EdgeMap<Value>(copy) { }
deba@909
   342
      
deba@909
   343
    };
deba@909
   344
deba@909
   345
    // Create edge map registry.
deba@909
   346
    CREATE_EDGE_MAP_REGISTRY;
deba@909
   347
    // Create edge maps.
deba@909
   348
    CREATE_EDGE_MAP(ArrayMap);
deba@909
   349
deba@909
   350
    class Edge {
deba@909
   351
      friend class SymSmartGraph;
deba@909
   352
      friend class SymSmartGraph::EdgeIt;
deba@909
   353
      friend class SymSmartGraph::OutEdgeIt;
deba@909
   354
      friend class SymSmartGraph::InEdgeIt;
deba@909
   355
      
deba@909
   356
    protected:
deba@909
   357
      int id;
deba@909
   358
deba@909
   359
      Edge(int pid) { id = pid; }
deba@909
   360
deba@909
   361
    public:
deba@909
   362
      /// An Edge with id \c n.
deba@909
   363
deba@909
   364
      Edge() { }
deba@909
   365
      Edge (Invalid) { id = -1; }
deba@909
   366
deba@909
   367
      operator SymEdge(){ return SymEdge(id >> 1);}
deba@909
   368
      
deba@909
   369
      bool operator==(const Edge i) const {return id == i.id;}
deba@909
   370
      bool operator!=(const Edge i) const {return id != i.id;}
deba@909
   371
      bool operator<(const Edge i) const {return id < i.id;}
deba@909
   372
      //      ///Validity check
deba@909
   373
      //      operator bool() { return n!=-1; }
deba@909
   374
    };
deba@909
   375
deba@909
   376
    class SymEdge : public SmartGraph::Edge {
deba@909
   377
      friend class SymSmartGraph;
deba@909
   378
      friend class SymSmartGraph::Edge;
deba@909
   379
      typedef SmartGraph::Edge Parent;
deba@909
   380
deba@909
   381
    protected:      
deba@909
   382
      SymEdge(int pid) : Parent(pid) {}
deba@909
   383
    public:
deba@909
   384
deba@909
   385
      SymEdge() { }
deba@909
   386
      SymEdge(const SmartGraph::Edge& i) : Parent(i) {} 
deba@909
   387
      SymEdge (Invalid) : Parent(INVALID) {}
deba@909
   388
deba@909
   389
    };
deba@909
   390
deba@909
   391
    class OutEdgeIt {
deba@909
   392
      Parent::OutEdgeIt out;
deba@909
   393
      Parent::InEdgeIt in;      
deba@909
   394
    public: 
deba@909
   395
      OutEdgeIt() {}
deba@909
   396
      OutEdgeIt(const SymSmartGraph& g, Edge e) { 
deba@909
   397
	if (e.id & 1 == 0) {	
deba@909
   398
	  out = Parent::OutEdgeIt(g, SymEdge(e));
deba@909
   399
	  in = Parent::InEdgeIt(g, g.tail(e));
deba@909
   400
	} else {
deba@909
   401
	  out = Parent::OutEdgeIt(INVALID);
deba@909
   402
	  in = Parent::InEdgeIt(g, SymEdge(e));
deba@909
   403
	}
deba@909
   404
      }
deba@909
   405
      OutEdgeIt (Invalid i) : out(INVALID), in(INVALID) { }
deba@909
   406
deba@909
   407
      OutEdgeIt(const SymSmartGraph& g, const Node v)
deba@909
   408
	: out(g, v), in(g, v) {}
deba@909
   409
      OutEdgeIt &operator++() { 
deba@909
   410
	if (out != INVALID) {
deba@909
   411
	  ++out;
deba@909
   412
	} else {
deba@909
   413
	  ++in;
deba@909
   414
	}
deba@909
   415
	return *this; 
deba@909
   416
      }
deba@909
   417
deba@909
   418
      operator Edge() const {
deba@909
   419
	if (out == INVALID && in == INVALID) return INVALID;
deba@909
   420
	return out != INVALID ? forward(out) : backward(in);
deba@909
   421
      }
deba@909
   422
deba@909
   423
      bool operator==(const Edge i) const {return Edge(*this) == i;}
deba@909
   424
      bool operator!=(const Edge i) const {return Edge(*this) != i;}
deba@909
   425
      bool operator<(const Edge i) const {return Edge(*this) < i;}
deba@909
   426
    };
deba@909
   427
deba@909
   428
    class InEdgeIt {
deba@909
   429
      Parent::OutEdgeIt out;
deba@909
   430
      Parent::InEdgeIt in;      
deba@909
   431
    public: 
deba@909
   432
      InEdgeIt() {}
deba@909
   433
      InEdgeIt(const SymSmartGraph& g, Edge e) { 
deba@909
   434
	if (e.id & 1 == 0) {	
deba@909
   435
	  out = Parent::OutEdgeIt(g, SymEdge(e));
deba@909
   436
	  in = Parent::InEdgeIt(g, g.tail(e));
deba@909
   437
	} else {
deba@909
   438
	  out = Parent::OutEdgeIt(INVALID);
deba@909
   439
	  in = Parent::InEdgeIt(g, SymEdge(e));
deba@909
   440
	}
deba@909
   441
      }
deba@909
   442
      InEdgeIt (Invalid i) : out(INVALID), in(INVALID) { }
deba@909
   443
deba@909
   444
      InEdgeIt(const SymSmartGraph& g, const Node v)
deba@909
   445
	: out(g, v), in(g, v) {}
deba@909
   446
deba@909
   447
      InEdgeIt &operator++() { 
deba@909
   448
	if (out != INVALID) {
deba@909
   449
	  ++out;
deba@909
   450
	} else {
deba@909
   451
	  ++in;
deba@909
   452
	}
deba@909
   453
	return *this; 
deba@909
   454
      }
deba@909
   455
deba@909
   456
      operator Edge() const {
deba@909
   457
	if (out == INVALID && in == INVALID) return INVALID;
deba@909
   458
	return out != INVALID ? backward(out) : forward(in);
deba@909
   459
      }
deba@909
   460
deba@909
   461
      bool operator==(const Edge i) const {return Edge(*this) == i;}
deba@909
   462
      bool operator!=(const Edge i) const {return Edge(*this) != i;}
deba@909
   463
      bool operator<(const Edge i) const {return Edge(*this) < i;}
deba@909
   464
    };
deba@909
   465
deba@909
   466
    class SymEdgeIt : public Parent::EdgeIt {
deba@909
   467
deba@909
   468
    public:
deba@909
   469
      SymEdgeIt() {}
deba@909
   470
deba@909
   471
      SymEdgeIt(const SymSmartGraph& g) 
deba@909
   472
	: SymSmartGraph::Parent::EdgeIt(g) {}
deba@909
   473
deba@909
   474
      SymEdgeIt(const SymSmartGraph& g, SymEdge e) 
deba@909
   475
	: SymSmartGraph::Parent::EdgeIt(g, e) {}
deba@909
   476
deba@909
   477
      SymEdgeIt(Invalid i) 
deba@909
   478
	: SymSmartGraph::Parent::EdgeIt(INVALID) {}
deba@909
   479
deba@909
   480
      SymEdgeIt& operator++() {
deba@909
   481
	SymSmartGraph::Parent::EdgeIt::operator++();
deba@909
   482
	return *this;
deba@909
   483
      }
deba@909
   484
deba@909
   485
      operator SymEdge() const {
deba@909
   486
	return SymEdge
deba@909
   487
	  (static_cast<const SymSmartGraph::Parent::EdgeIt&>(*this));
deba@909
   488
      }
deba@909
   489
      bool operator==(const SymEdge i) const {return SymEdge(*this) == i;}
deba@909
   490
      bool operator!=(const SymEdge i) const {return SymEdge(*this) != i;}
deba@909
   491
      bool operator<(const SymEdge i) const {return SymEdge(*this) < i;}
deba@909
   492
    };
deba@909
   493
deba@909
   494
    class EdgeIt {
deba@909
   495
      SymEdgeIt it;
deba@909
   496
      bool fw;
deba@909
   497
    public:
deba@909
   498
      EdgeIt(const SymSmartGraph& g) : it(g), fw(true) {}
deba@909
   499
      EdgeIt (Invalid i) : it(i) { }
deba@909
   500
      EdgeIt(const SymSmartGraph& g, Edge e) 
deba@909
   501
	: it(g, SymEdge(e)), fw(id(e) & 1 == 0) { }
deba@909
   502
      EdgeIt() { }
deba@909
   503
      EdgeIt& operator++() {
deba@909
   504
	fw = !fw;
deba@909
   505
	if (fw) ++it;
deba@909
   506
	return *this;
deba@909
   507
      }
deba@909
   508
      operator Edge() const {
deba@909
   509
	if (it == INVALID) return INVALID;
deba@909
   510
	return fw ? forward(it) : backward(it);
deba@909
   511
      }
deba@909
   512
      bool operator==(const Edge i) const {return Edge(*this) == i;}
deba@909
   513
      bool operator!=(const Edge i) const {return Edge(*this) != i;}
deba@909
   514
      bool operator<(const Edge i) const {return Edge(*this) < i;}
deba@909
   515
deba@909
   516
    };
deba@909
   517
deba@909
   518
    ///Number of nodes.
deba@909
   519
    int nodeNum() const { return Parent::nodeNum(); }
deba@909
   520
    ///Number of edges.
deba@909
   521
    int edgeNum() const { return 2*Parent::edgeNum(); }
deba@909
   522
    ///Number of symmetric edges.
deba@909
   523
    int symEdgeNum() const { return Parent::edgeNum(); }
deba@909
   524
deba@909
   525
    /// Maximum node ID.
deba@909
   526
    
deba@909
   527
    /// Maximum node ID.
deba@909
   528
    ///\sa id(Node)
deba@909
   529
    int maxNodeId() const { return Parent::maxNodeId(); } 
deba@909
   530
    /// Maximum edge ID.
deba@909
   531
    
deba@909
   532
    /// Maximum edge ID.
deba@909
   533
    ///\sa id(Edge)
deba@909
   534
    int maxEdgeId() const { return 2*Parent::maxEdgeId(); }
deba@909
   535
    /// Maximum symmetric edge ID.
deba@909
   536
    
deba@909
   537
    /// Maximum symmetric edge ID.
deba@909
   538
    ///\sa id(SymEdge)
deba@909
   539
    int maxSymEdgeId() const { return Parent::maxEdgeId(); }
deba@909
   540
deba@909
   541
deba@909
   542
    Node tail(Edge e) const { 
deba@909
   543
      return e.id & 1 == 0 ? 
deba@909
   544
	Parent::tail(SymEdge(e)) : Parent::head(SymEdge(e)); 
deba@909
   545
    }
deba@909
   546
deba@909
   547
    Node head(Edge e) const { 
deba@909
   548
      return e.id & 1 == 0 ? 
deba@909
   549
	Parent::head(SymEdge(e)) : Parent::tail(SymEdge(e)); 
deba@909
   550
    }
deba@909
   551
deba@909
   552
    Node tail(SymEdge e) const { 
deba@909
   553
      return Parent::tail(e); 
deba@909
   554
    }
deba@909
   555
deba@909
   556
    Node head(SymEdge e) const { 
deba@909
   557
      return Parent::head(e); 
deba@909
   558
    }
deba@909
   559
deba@909
   560
    NodeIt& first(NodeIt& v) const { 
deba@909
   561
      v=NodeIt(*this); return v; }
deba@909
   562
    EdgeIt& first(EdgeIt& e) const { 
deba@909
   563
      e=EdgeIt(*this); return e; }
deba@909
   564
    SymEdgeIt& first(SymEdgeIt& e) const {
deba@909
   565
      e=SymEdgeIt(*this); return e; }
deba@909
   566
    OutEdgeIt& first(OutEdgeIt& e, const Node v) const { 
deba@909
   567
      e=OutEdgeIt(*this,v); return e; }
deba@909
   568
    InEdgeIt& first(InEdgeIt& e, const Node v) const { 
deba@909
   569
      e=InEdgeIt(*this,v); return e; }
deba@909
   570
deba@909
   571
    /// Node ID.
deba@909
   572
    
deba@909
   573
    /// The ID of a valid Node is a nonnegative integer not greater than
deba@909
   574
    /// \ref maxNodeId(). The range of the ID's is not surely continuous
deba@909
   575
    /// and the greatest node ID can be actually less then \ref maxNodeId().
deba@909
   576
    ///
deba@909
   577
    /// The ID of the \ref INVALID node is -1.
deba@909
   578
    ///\return The ID of the node \c v. 
deba@909
   579
    static int id(Node v) { return Parent::id(v); }
deba@909
   580
    /// Edge ID.
deba@909
   581
    
deba@909
   582
    /// The ID of a valid Edge is a nonnegative integer not greater than
deba@909
   583
    /// \ref maxEdgeId(). The range of the ID's is not surely continuous
deba@909
   584
    /// and the greatest edge ID can be actually less then \ref maxEdgeId().
deba@909
   585
    ///
deba@909
   586
    /// The ID of the \ref INVALID edge is -1.
deba@909
   587
    ///\return The ID of the edge \c e. 
deba@909
   588
    static int id(Edge e) { return e.id; }
deba@909
   589
deba@909
   590
    /// The ID of a valid SymEdge is a nonnegative integer not greater than
deba@909
   591
    /// \ref maxSymEdgeId(). The range of the ID's is not surely continuous
deba@909
   592
    /// and the greatest edge ID can be actually less then \ref maxSymEdgeId().
deba@909
   593
    ///
deba@909
   594
    /// The ID of the \ref INVALID symmetric edge is -1.
deba@909
   595
    ///\return The ID of the edge \c e. 
deba@909
   596
    static int id(SymEdge e) { return Parent::id(e); }
deba@909
   597
deba@909
   598
    /// Adds a new node to the graph.
deba@909
   599
deba@909
   600
    /// \warning It adds the new node to the front of the list.
deba@909
   601
    /// (i.e. the lastly added node becomes the first.)
deba@909
   602
    Node addNode() {
deba@909
   603
      return Parent::addNode();
deba@909
   604
    }
deba@909
   605
    
deba@909
   606
    SymEdge addEdge(Node u, Node v) {
deba@909
   607
      SymEdge se = Parent::addEdge(u, v);
deba@909
   608
      edge_maps.add(forward(se));
deba@909
   609
      edge_maps.add(backward(se));
deba@909
   610
      return se;
deba@909
   611
    }
deba@909
   612
    
deba@909
   613
    /// Finds an edge between two nodes.
deba@909
   614
deba@909
   615
    /// Finds an edge from node \c u to node \c v.
deba@909
   616
    ///
deba@909
   617
    /// If \c prev is \ref INVALID (this is the default value), then
deba@909
   618
    /// It finds the first edge from \c u to \c v. Otherwise it looks for
deba@909
   619
    /// the next edge from \c u to \c v after \c prev.
deba@909
   620
    /// \return The found edge or INVALID if there is no such an edge.
deba@909
   621
    Edge findEdge(Node u, Node v, Edge prev = INVALID) 
deba@909
   622
    {     
deba@909
   623
      if (prev == INVALID || id(prev) & 1 == 0) {
deba@909
   624
	SymEdge se = Parent::findEdge(u, v, SymEdge(prev));
deba@909
   625
	if (se != INVALID) return forward(se);
deba@909
   626
      } else {
deba@909
   627
	SymEdge se = Parent::findEdge(v, u, SymEdge(prev));
deba@909
   628
	if (se != INVALID) return backward(se);	
deba@909
   629
      }
deba@909
   630
      return INVALID;
deba@909
   631
    }
deba@909
   632
deba@909
   633
    /// Finds an symmetric edge between two nodes.
deba@909
   634
deba@909
   635
    /// Finds an symmetric edge from node \c u to node \c v.
deba@909
   636
    ///
deba@909
   637
    /// If \c prev is \ref INVALID (this is the default value), then
deba@909
   638
    /// It finds the first edge from \c u to \c v. Otherwise it looks for
deba@909
   639
    /// the next edge from \c u to \c v after \c prev.
deba@909
   640
    /// \return The found edge or INVALID if there is no such an edge.
deba@909
   641
deba@909
   642
//     SymEdge findEdge(Node u, Node v, SymEdge prev = INVALID) 
deba@909
   643
//     {     
deba@909
   644
//       if (prev == INVALID || id(prev) & 1 == 0) {
deba@909
   645
// 	SymEdge se = Parent::findEdge(u, v, SymEdge(prev));
deba@909
   646
// 	if (se != INVALID) return se;
deba@909
   647
//       } else {
deba@909
   648
// 	SymEdge se = Parent::findEdge(v, u, SymEdge(prev));
deba@909
   649
// 	if (se != INVALID) return se;	
deba@909
   650
//       }
deba@909
   651
//       return INVALID;
deba@909
   652
//     }
deba@909
   653
    
deba@909
   654
  public:
deba@909
   655
deba@909
   656
    void clear() {
deba@909
   657
      edge_maps.clear();
deba@909
   658
      Parent::clear();
deba@909
   659
    }
deba@909
   660
deba@909
   661
    static Edge opposite(Edge e) {
deba@909
   662
      return Edge(id(e) ^ 1);
deba@909
   663
    }
deba@909
   664
deba@909
   665
    static Edge forward(SymEdge e) {
deba@909
   666
      return Edge(id(e) << 1);
deba@909
   667
    }
deba@909
   668
deba@909
   669
    static Edge backward(SymEdge e) {
deba@909
   670
      return Edge((id(e) << 1) & 1);
deba@909
   671
    }
deba@909
   672
deba@909
   673
  };
alpar@185
   674
  ///Graph for bidirectional edges.
alpar@185
   675
alpar@185
   676
  ///The purpose of this graph structure is to handle graphs
alpar@185
   677
  ///having bidirectional edges. Here the function \c addEdge(u,v) adds a pair
alpar@186
   678
  ///of oppositely directed edges.
alpar@186
   679
  ///There is a new edge map type called
alpar@186
   680
  ///\ref SymSmartGraph::SymEdgeMap "SymEdgeMap"
alpar@186
   681
  ///that complements this
alpar@186
   682
  ///feature by
alpar@186
   683
  ///storing shared values for the edge pairs. The usual
alpar@880
   684
  ///\ref Graph::EdgeMap "EdgeMap"
alpar@186
   685
  ///can be used
alpar@185
   686
  ///as well.
alpar@185
   687
  ///
alpar@186
   688
  ///The oppositely directed edge can also be obtained easily
alpar@186
   689
  ///using \ref opposite.
alpar@186
   690
  ///\warning It shares the similarity with \ref SmartGraph that
alpar@186
   691
  ///it is not possible to delete edges or nodes from the graph.
alpar@880
   692
  //\sa SmartGraph.
alpar@185
   693
deba@909
   694
  /*  class SymSmartGraph : public SmartGraph
alpar@185
   695
  {
alpar@185
   696
  public:
deba@782
   697
    typedef SymSmartGraph Graph;
deba@782
   698
alpar@904
   699
    // Create symmetric map registry.
deba@782
   700
    CREATE_SYM_EDGE_MAP_REGISTRY;
alpar@904
   701
    // Create symmetric edge map.
deba@897
   702
    CREATE_SYM_EDGE_MAP(ArrayMap);
deba@822
   703
alpar@186
   704
alpar@185
   705
    SymSmartGraph() : SmartGraph() { }
alpar@185
   706
    SymSmartGraph(const SmartGraph &_g) : SmartGraph(_g) { }
alpar@398
   707
    ///Adds a pair of oppositely directed edges to the graph.
alpar@185
   708
    Edge addEdge(Node u, Node v)
alpar@185
   709
    {
alpar@185
   710
      Edge e = SmartGraph::addEdge(u,v);
deba@798
   711
      Edge f = SmartGraph::addEdge(v,u);
deba@798
   712
      sym_edge_maps.add(e);
deba@798
   713
      sym_edge_maps.add(f);
alpar@185
   714
      return e;
alpar@185
   715
    }
alpar@185
   716
alpar@186
   717
    ///The oppositely directed edge.
alpar@186
   718
alpar@186
   719
    ///Returns the oppositely directed
alpar@186
   720
    ///pair of the edge \c e.
alpar@713
   721
    static Edge opposite(Edge e)
alpar@185
   722
    {
alpar@185
   723
      Edge f;
alpar@905
   724
      f.n = e.n - 2*(e.n%2) + 1;
alpar@185
   725
      return f;
alpar@185
   726
    }
alpar@185
   727
    
alpar@185
   728
deba@909
   729
    };*/
alpar@185
   730
  
alpar@407
   731
  /// @}  
alpar@105
   732
} //namespace hugo
alpar@104
   733
alpar@157
   734
alpar@157
   735
alpar@157
   736
alpar@590
   737
#endif //HUGO_SMART_GRAPH_H