lemon/smart_graph.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 2190 dd887831e9c1
child 2256 b22dfb6c5ff3
permissions -rw-r--r--
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

The tests have been modified to the current implementation
alpar@906
     1
/* -*- C++ -*-
alpar@906
     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@1359
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@906
     8
 *
alpar@906
     9
 * Permission to use, modify and distribute this software is granted
alpar@906
    10
 * provided that this copyright notice appears in all copies. For
alpar@906
    11
 * precise terms see the accompanying LICENSE file.
alpar@906
    12
 *
alpar@906
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@906
    14
 * express or implied, and with no claim as to its suitability for any
alpar@906
    15
 * purpose.
alpar@906
    16
 *
alpar@906
    17
 */
alpar@105
    18
alpar@921
    19
#ifndef LEMON_SMART_GRAPH_H
alpar@921
    20
#define LEMON_SMART_GRAPH_H
alpar@104
    21
klao@491
    22
///\ingroup graphs
alpar@242
    23
///\file
deba@2116
    24
///\brief SmartGraph and SmartUGraph classes.
alpar@242
    25
alpar@104
    26
#include <vector>
alpar@104
    27
deba@1993
    28
#include <lemon/bits/invalid.h>
alpar@157
    29
deba@2116
    30
#include <lemon/bits/base_extender.h>
deba@1791
    31
#include <lemon/bits/graph_extender.h>
klao@1034
    32
deba@1993
    33
#include <lemon/bits/utility.h>
deba@2116
    34
#include <lemon/error.h>
deba@782
    35
deba@1979
    36
#include <lemon/bits/graph_extender.h>
deba@1979
    37
alpar@921
    38
namespace lemon {
alpar@104
    39
alpar@973
    40
  class SmartGraph;
alpar@969
    41
  ///Base of SmartGraph
alpar@969
    42
alpar@969
    43
  ///Base of SmartGraph
alpar@969
    44
  ///
klao@946
    45
  class SmartGraphBase {
deba@2190
    46
  protected:
alpar@104
    47
alpar@104
    48
    struct NodeT 
alpar@104
    49
    {
deba@2190
    50
      int first_in, first_out;      
deba@2190
    51
      NodeT() {}
alpar@104
    52
    };
alpar@104
    53
    struct EdgeT 
alpar@104
    54
    {
alpar@986
    55
      int target, source, next_in, next_out;      
deba@2190
    56
      EdgeT() {}  
alpar@104
    57
    };
alpar@104
    58
alpar@104
    59
    std::vector<NodeT> nodes;
alpar@129
    60
alpar@104
    61
    std::vector<EdgeT> edges;
alpar@104
    62
    
alpar@185
    63
    
alpar@104
    64
  public:
deba@782
    65
klao@946
    66
    typedef SmartGraphBase Graph;
alpar@104
    67
alpar@164
    68
    class Node;
alpar@164
    69
    class Edge;
alpar@108
    70
alpar@104
    71
    
alpar@104
    72
  public:
alpar@104
    73
klao@946
    74
    SmartGraphBase() : nodes(), edges() { }
deba@1718
    75
    SmartGraphBase(const SmartGraphBase &_g) 
deba@1718
    76
      : nodes(_g.nodes), edges(_g.edges) { }
alpar@104
    77
    
klao@977
    78
    typedef True NodeNumTag;
klao@977
    79
    typedef True EdgeNumTag;
klao@977
    80
alpar@813
    81
    int nodeNum() const { return nodes.size(); }
alpar@813
    82
    int edgeNum() const { return edges.size(); }
alpar@104
    83
deba@1791
    84
    int maxNodeId() const { return nodes.size()-1; }
deba@1791
    85
    int maxEdgeId() const { return edges.size()-1; }
alpar@108
    86
alpar@2128
    87
    Node addNode() {
deba@2190
    88
      int n = nodes.size();     
deba@2190
    89
      nodes.push_back(NodeT());
deba@2190
    90
      nodes[n].first_in = -1;
deba@2190
    91
      nodes[n].first_out = -1;
deba@2190
    92
      return Node(n);
alpar@2128
    93
    }
alpar@2128
    94
    
alpar@2128
    95
    Edge addEdge(Node u, Node v) {
deba@2190
    96
      int n = edges.size(); 
deba@2190
    97
      edges.push_back(EdgeT());
deba@2190
    98
      edges[n].source = u.id; 
deba@2190
    99
      edges[n].target = v.id;
deba@2190
   100
      edges[n].next_out = nodes[u.id].first_out;
deba@2190
   101
      edges[n].next_in = nodes[v.id].first_in;
deba@2190
   102
      nodes[u.id].first_out = nodes[v.id].first_in = n;
alpar@2128
   103
deba@2190
   104
      return Edge(n);
alpar@2128
   105
    }
alpar@2128
   106
deba@2190
   107
    void clear() {
deba@2190
   108
      edges.clear();
deba@2190
   109
      nodes.clear();
deba@2190
   110
    }
alpar@2128
   111
deba@2190
   112
    Node source(Edge e) const { return Node(edges[e.id].source); }
deba@2190
   113
    Node target(Edge e) const { return Node(edges[e.id].target); }
alpar@104
   114
deba@2190
   115
    static int id(Node v) { return v.id; }
deba@2190
   116
    static int id(Edge e) { return e.id; }
alpar@104
   117
deba@1791
   118
    static Node nodeFromId(int id) { return Node(id);}
deba@1791
   119
    static Edge edgeFromId(int id) { return Edge(id);}
deba@1106
   120
alpar@164
   121
    class Node {
klao@946
   122
      friend class SmartGraphBase;
alpar@973
   123
      friend class SmartGraph;
alpar@104
   124
alpar@104
   125
    protected:
deba@2190
   126
      int id;
deba@2190
   127
      explicit Node(int _id) : id(_id) {}
alpar@104
   128
    public:
alpar@164
   129
      Node() {}
deba@2190
   130
      Node (Invalid) : id(-1) {}
deba@2190
   131
      bool operator==(const Node i) const {return id == i.id;}
deba@2190
   132
      bool operator!=(const Node i) const {return id != i.id;}
deba@2190
   133
      bool operator<(const Node i) const {return id < i.id;}
alpar@104
   134
    };
alpar@104
   135
    
alpar@104
   136
alpar@164
   137
    class Edge {
klao@946
   138
      friend class SmartGraphBase;
alpar@973
   139
      friend class SmartGraph;
alpar@185
   140
alpar@104
   141
    protected:
deba@2190
   142
      int id;
deba@2190
   143
      explicit Edge(int _id) : id(_id) {}
alpar@706
   144
    public:
alpar@164
   145
      Edge() { }
deba@2190
   146
      Edge (Invalid) : id(-1) {}
deba@2190
   147
      bool operator==(const Edge i) const {return id == i.id;}
deba@2190
   148
      bool operator!=(const Edge i) const {return id != i.id;}
deba@2190
   149
      bool operator<(const Edge i) const {return id < i.id;}
klao@946
   150
    };
alpar@905
   151
klao@946
   152
    void first(Node& node) const {
deba@2190
   153
      node.id = nodes.size() - 1;
klao@946
   154
    }
klao@946
   155
klao@946
   156
    static void next(Node& node) {
deba@2190
   157
      --node.id;
klao@946
   158
    }
klao@946
   159
klao@946
   160
    void first(Edge& edge) const {
deba@2190
   161
      edge.id = edges.size() - 1;
klao@946
   162
    }
klao@946
   163
klao@946
   164
    static void next(Edge& edge) {
deba@2190
   165
      --edge.id;
klao@946
   166
    }
klao@946
   167
klao@946
   168
    void firstOut(Edge& edge, const Node& node) const {
deba@2190
   169
      edge.id = nodes[node.id].first_out;
klao@946
   170
    }
klao@946
   171
klao@946
   172
    void nextOut(Edge& edge) const {
deba@2190
   173
      edge.id = edges[edge.id].next_out;
klao@946
   174
    }
klao@946
   175
klao@946
   176
    void firstIn(Edge& edge, const Node& node) const {
deba@2190
   177
      edge.id = nodes[node.id].first_in;
klao@946
   178
    }
alpar@104
   179
    
klao@946
   180
    void nextIn(Edge& edge) const {
deba@2190
   181
      edge.id = edges[edge.id].next_in;
klao@946
   182
    }
alpar@105
   183
alpar@104
   184
  };
alpar@185
   185
deba@1979
   186
  typedef GraphExtender<SmartGraphBase> ExtendedSmartGraphBase;
deba@937
   187
deba@1791
   188
  /// \ingroup graphs
alpar@1161
   189
alpar@950
   190
  ///A smart graph class.
deba@937
   191
alpar@950
   192
  ///This is a simple and fast graph implementation.
alpar@950
   193
  ///It is also quite memory efficient, but at the price
alpar@974
   194
  ///that <b> it does support only limited (only stack-like)
alpar@974
   195
  ///node and edge deletions</b>.
alpar@950
   196
  ///It conforms to 
alpar@2123
   197
  ///the \ref concept::Graph "Graph concept".
deba@2111
   198
  ///\sa concept::Graph.
alpar@950
   199
  ///
alpar@950
   200
  ///\author Alpar Juttner
deba@1669
   201
  class SmartGraph : public ExtendedSmartGraphBase {
alpar@969
   202
  public:
deba@1979
   203
deba@1979
   204
    typedef ExtendedSmartGraphBase Parent;
deba@1979
   205
deba@2190
   206
  private:
alpar@973
   207
alpar@2128
   208
    ///SmartGraph is \e not copy constructible. Use GraphCopy() instead.
alpar@2128
   209
alpar@2128
   210
    ///SmartGraph is \e not copy constructible. Use GraphCopy() instead.
alpar@2128
   211
    ///
deba@2190
   212
    SmartGraph(const SmartGraph &) : ExtendedSmartGraphBase() {};
alpar@2132
   213
    ///\brief Assignment of SmartGraph to another one is \e not allowed.
alpar@2128
   214
    ///Use GraphCopy() instead.
alpar@2128
   215
alpar@2132
   216
    ///Assignment of SmartGraph to another one is \e not allowed.
alpar@2128
   217
    ///Use GraphCopy() instead.
alpar@2128
   218
    void operator=(const SmartGraph &) {}
alpar@1011
   219
alpar@1011
   220
  public:
alpar@2128
   221
    
alpar@2128
   222
    /// Constructor
alpar@2128
   223
    
alpar@2128
   224
    /// Constructor.
alpar@2128
   225
    ///
alpar@2128
   226
    SmartGraph() {};
alpar@2128
   227
    
alpar@2128
   228
    ///Add a new node to the graph.
alpar@2128
   229
    
alpar@2128
   230
    /// \return the new node.
alpar@2128
   231
    ///
alpar@2128
   232
    Node addNode() { return Parent::addNode(); }
alpar@2128
   233
    
alpar@2128
   234
    ///Add a new edge to the graph.
alpar@2128
   235
    
alpar@2128
   236
    ///Add a new edge to the graph with source node \c s
alpar@2128
   237
    ///and target node \c t.
alpar@2128
   238
    ///\return the new edge.
alpar@2128
   239
    Edge addEdge(const Node& s, const Node& t) { 
alpar@2128
   240
      return Parent::addEdge(s, t); 
alpar@2128
   241
    }
alpar@2128
   242
deba@2190
   243
    ///Clear the graph.
alpar@2128
   244
    
deba@2190
   245
    ///Erase all the nodes and edges from the graph.
deba@2190
   246
    ///
alpar@2128
   247
    void clear() {
deba@2190
   248
      Parent::clear();
alpar@2128
   249
    }
alpar@1284
   250
alpar@1284
   251
    ///Split a node.
alpar@1284
   252
    
alpar@1284
   253
    ///This function splits a node. First a new node is added to the graph,
alpar@1284
   254
    ///then the source of each outgoing edge of \c n is moved to this new node.
alpar@1284
   255
    ///If \c connect is \c true (this is the default value), then a new edge
alpar@1284
   256
    ///from \c n to the newly created node is also added.
alpar@1284
   257
    ///\return The newly created node.
alpar@1284
   258
    ///
alpar@1284
   259
    ///\note The <tt>Edge</tt>s
alpar@1284
   260
    ///referencing a moved edge remain
alpar@1284
   261
    ///valid. However <tt>InEdge</tt>'s and <tt>OutEdge</tt>'s
alpar@1284
   262
    ///may be invalidated.
alpar@1770
   263
    ///\warning This functionality cannot be used together with the Snapshot
alpar@1284
   264
    ///feature.
alpar@1284
   265
    ///\todo It could be implemented in a bit faster way.
alpar@2128
   266
    Node split(Node n, bool connect = true)
alpar@1284
   267
    {
alpar@2128
   268
      Node b = addNode();
deba@2190
   269
      nodes[b.id].first_out=nodes[n.id].first_out;
deba@2190
   270
      nodes[n.id].first_out=-1;
deba@2190
   271
      for(int i=nodes[b.id].first_out;i!=-1;i++) edges[i].source=b.id;
alpar@2128
   272
      if(connect) addEdge(n,b);
deba@1718
   273
      return b;
alpar@1284
   274
    }
alpar@1284
   275
deba@2190
   276
  public:
deba@2190
   277
    
deba@2190
   278
    class Snapshot;
deba@2190
   279
deba@2190
   280
  protected:
deba@2190
   281
deba@2190
   282
    void restoreSnapshot(const Snapshot &s)
deba@2190
   283
    {
deba@2190
   284
      while(s.edge_num<edges.size()) {
deba@2190
   285
        Edge edge = edgeFromId(edges.size()-1);
deba@2190
   286
	Parent::getNotifier(Edge()).erase(edge);
deba@2190
   287
	nodes[edges.back().source].first_out=edges.back().next_out;
deba@2190
   288
	nodes[edges.back().target].first_in=edges.back().next_in;
deba@2190
   289
	edges.pop_back();
deba@2190
   290
      }
deba@2190
   291
      while(s.node_num<nodes.size()) {
deba@2190
   292
        Node node = nodeFromId(nodes.size()-1);
deba@2190
   293
	Parent::getNotifier(Node()).erase(node);
deba@2190
   294
	nodes.pop_back();
deba@2190
   295
      }
deba@2190
   296
    }    
deba@2190
   297
deba@2190
   298
  public:
deba@2190
   299
alpar@1011
   300
    ///Class to make a snapshot of the graph and to restrore to it later.
alpar@1011
   301
alpar@1011
   302
    ///Class to make a snapshot of the graph and to restrore to it later.
alpar@1011
   303
    ///
alpar@1011
   304
    ///The newly added nodes and edges can be removed using the
alpar@1011
   305
    ///restore() function.
alpar@1011
   306
    ///\note After you restore a state, you cannot restore
alpar@1011
   307
    ///a later state, in other word you cannot add again the edges deleted
alpar@2132
   308
    ///by restore() using another one Snapshot instance.
alpar@1011
   309
    ///
deba@2190
   310
    ///\warning If you do not use correctly the snapshot that can cause
deba@2190
   311
    ///either broken program, invalid state of the graph, valid but
deba@2190
   312
    ///not the restored graph or no change. Because the runtime performance
deba@2190
   313
    ///the validity of the snapshot is not stored.
alpar@1770
   314
    class Snapshot 
alpar@1011
   315
    {
alpar@1011
   316
      SmartGraph *g;
alpar@1011
   317
    protected:
alpar@1011
   318
      friend class SmartGraph;
alpar@1011
   319
      unsigned int node_num;
alpar@1011
   320
      unsigned int edge_num;
alpar@1011
   321
    public:
zsuzska@1274
   322
      ///Default constructor.
alpar@1011
   323
      
zsuzska@1274
   324
      ///Default constructor.
alpar@1011
   325
      ///To actually make a snapshot you must call save().
alpar@1011
   326
      ///
alpar@1770
   327
      Snapshot() : g(0) {}
alpar@1011
   328
      ///Constructor that immediately makes a snapshot
alpar@1011
   329
      
alpar@1011
   330
      ///This constructor immediately makes a snapshot of the graph.
alpar@1011
   331
      ///\param _g The graph we make a snapshot of.
alpar@1770
   332
      Snapshot(SmartGraph &_g) :g(&_g) {
alpar@1011
   333
	node_num=g->nodes.size();
alpar@1011
   334
	edge_num=g->edges.size();
alpar@1011
   335
      }
alpar@1011
   336
alpar@1011
   337
      ///Make a snapshot.
alpar@1011
   338
alpar@1011
   339
      ///Make a snapshot of the graph.
alpar@1011
   340
      ///
alpar@1011
   341
      ///This function can be called more than once. In case of a repeated
alpar@1011
   342
      ///call, the previous snapshot gets lost.
alpar@1011
   343
      ///\param _g The graph we make the snapshot of.
alpar@1011
   344
      void save(SmartGraph &_g) 
alpar@1011
   345
      {
alpar@1011
   346
	g=&_g;
alpar@1011
   347
	node_num=g->nodes.size();
alpar@1011
   348
	edge_num=g->edges.size();
alpar@1011
   349
      }
alpar@1011
   350
alpar@1011
   351
      ///Undo the changes until a snapshot.
alpar@1011
   352
      
alpar@1011
   353
      ///Undo the changes until a snapshot created by save().
alpar@1011
   354
      ///
alpar@1011
   355
      ///\note After you restored a state, you cannot restore
alpar@1011
   356
      ///a later state, in other word you cannot add again the edges deleted
alpar@1011
   357
      ///by restore().
alpar@1011
   358
      void restore()
alpar@1011
   359
      {
alpar@1770
   360
	g->restoreSnapshot(*this);
alpar@1011
   361
      }
alpar@1011
   362
    };
alpar@973
   363
  };
klao@1034
   364
klao@1034
   365
deba@2116
   366
  /**************** Undirected List Graph ****************/
deba@2116
   367
deba@2116
   368
  typedef UGraphExtender<UndirGraphExtender<SmartGraphBase> >
deba@2116
   369
  ExtendedSmartUGraphBase;
deba@2116
   370
deba@2116
   371
  /// \ingroup graphs
deba@2116
   372
  ///
deba@2116
   373
  /// \brief A smart undirected graph class.
deba@2116
   374
  ///
deba@2116
   375
  /// This is a simple and fast undirected graph implementation.
deba@2116
   376
  /// It is also quite memory efficient, but at the price
deba@2116
   377
  /// that <b> it does support only limited (only stack-like)
deba@2116
   378
  /// node and edge deletions</b>.
deba@2116
   379
  /// Except from this it conforms to 
alpar@2123
   380
  /// the \ref concept::UGraph "UGraph concept".
deba@2116
   381
  /// \sa concept::UGraph.
deba@2116
   382
  ///
deba@2116
   383
  /// \todo Snapshot hasn't been implemented yet.
deba@2116
   384
  ///
deba@2116
   385
  class SmartUGraph : public ExtendedSmartUGraphBase {
alpar@2128
   386
  private:
deba@2190
   387
alpar@2128
   388
    ///SmartUGraph is \e not copy constructible. Use UGraphCopy() instead.
alpar@2128
   389
alpar@2128
   390
    ///SmartUGraph is \e not copy constructible. Use UGraphCopy() instead.
alpar@2128
   391
    ///
alpar@2128
   392
    SmartUGraph(const SmartUGraph &) : ExtendedSmartUGraphBase() {};
deba@2190
   393
alpar@2132
   394
    ///\brief Assignment of SmartUGraph to another one is \e not allowed.
alpar@2128
   395
    ///Use UGraphCopy() instead.
alpar@2128
   396
alpar@2132
   397
    ///Assignment of SmartUGraph to another one is \e not allowed.
alpar@2128
   398
    ///Use UGraphCopy() instead.
alpar@2128
   399
    void operator=(const SmartUGraph &) {}
deba@2190
   400
alpar@2128
   401
  public:
deba@2190
   402
deba@2190
   403
    typedef ExtendedSmartUGraphBase Parent;
deba@2190
   404
alpar@2128
   405
    /// Constructor
alpar@2128
   406
    
alpar@2128
   407
    /// Constructor.
alpar@2128
   408
    ///
alpar@2128
   409
    SmartUGraph() {}
deba@2190
   410
deba@2190
   411
    ///Add a new node to the graph.
deba@2190
   412
    
deba@2190
   413
    /// \return the new node.
deba@2190
   414
    ///
deba@2190
   415
    Node addNode() { return Parent::addNode(); }
deba@2190
   416
    
deba@2190
   417
    ///Add a new undirected edge to the graph.
deba@2190
   418
    
deba@2190
   419
    ///Add a new undirected edge to the graph with node \c s
deba@2190
   420
    ///and \c t.
deba@2190
   421
    ///\return the new undirected edge.
deba@2190
   422
    UEdge addEdge(const Node& s, const Node& t) { 
deba@2190
   423
      return Parent::addEdge(s, t); 
deba@2190
   424
    }
deba@2190
   425
deba@2190
   426
    ///Clear the graph.
deba@2190
   427
    
deba@2190
   428
    ///Erase all the nodes and edges from the graph.
deba@2190
   429
    ///
deba@2190
   430
    void clear() {
deba@2190
   431
      Parent::clear();
deba@2190
   432
    }
deba@2190
   433
deba@2190
   434
  public:
deba@2190
   435
    
deba@2190
   436
    class Snapshot;
deba@2190
   437
deba@2190
   438
  protected:
deba@2190
   439
deba@2190
   440
deba@2190
   441
    void restoreSnapshot(const Snapshot &s)
deba@2190
   442
    {
deba@2190
   443
      while(s.edge_num<edges.size()) {
deba@2190
   444
        UEdge edge = uEdgeFromId(edges.size()-1);
deba@2190
   445
	Parent::getNotifier(UEdge()).erase(edge);
deba@2190
   446
        std::vector<Edge> dir;
deba@2190
   447
        dir.push_back(Parent::direct(edge, true));
deba@2190
   448
        dir.push_back(Parent::direct(edge, false));
deba@2190
   449
	Parent::getNotifier(Edge()).erase(dir);
deba@2190
   450
	nodes[edges.back().source].first_out=edges.back().next_out;
deba@2190
   451
	nodes[edges.back().target].first_in=edges.back().next_in;
deba@2190
   452
	edges.pop_back();
deba@2190
   453
      }
deba@2190
   454
      while(s.node_num<nodes.size()) {
deba@2190
   455
        Node node = nodeFromId(nodes.size()-1);
deba@2190
   456
	Parent::getNotifier(Node()).erase(node);
deba@2190
   457
	nodes.pop_back();
deba@2190
   458
      }
deba@2190
   459
    }    
deba@2190
   460
deba@2190
   461
  public:
deba@2190
   462
deba@2190
   463
    ///Class to make a snapshot of the graph and to restrore to it later.
deba@2190
   464
deba@2190
   465
    ///Class to make a snapshot of the graph and to restrore to it later.
deba@2190
   466
    ///
deba@2190
   467
    ///The newly added nodes and edges can be removed using the
deba@2190
   468
    ///restore() function.
deba@2190
   469
    ///
deba@2190
   470
    ///\note After you restore a state, you cannot restore
deba@2190
   471
    ///a later state, in other word you cannot add again the edges deleted
deba@2190
   472
    ///by restore() using another one Snapshot instance.
deba@2190
   473
    ///
deba@2190
   474
    ///\warning If you do not use correctly the snapshot that can cause
deba@2190
   475
    ///either broken program, invalid state of the graph, valid but
deba@2190
   476
    ///not the restored graph or no change. Because the runtime performance
deba@2190
   477
    ///the validity of the snapshot is not stored.
deba@2190
   478
    class Snapshot 
deba@2190
   479
    {
deba@2190
   480
      SmartUGraph *g;
deba@2190
   481
    protected:
deba@2190
   482
      friend class SmartUGraph;
deba@2190
   483
      unsigned int node_num;
deba@2190
   484
      unsigned int edge_num;
deba@2190
   485
    public:
deba@2190
   486
      ///Default constructor.
deba@2190
   487
      
deba@2190
   488
      ///Default constructor.
deba@2190
   489
      ///To actually make a snapshot you must call save().
deba@2190
   490
      ///
deba@2190
   491
      Snapshot() : g(0) {}
deba@2190
   492
      ///Constructor that immediately makes a snapshot
deba@2190
   493
      
deba@2190
   494
      ///This constructor immediately makes a snapshot of the graph.
deba@2190
   495
      ///\param _g The graph we make a snapshot of.
deba@2190
   496
      Snapshot(SmartUGraph &_g) :g(&_g) {
deba@2190
   497
	node_num=g->nodes.size();
deba@2190
   498
	edge_num=g->edges.size();
deba@2190
   499
      }
deba@2190
   500
deba@2190
   501
      ///Make a snapshot.
deba@2190
   502
deba@2190
   503
      ///Make a snapshot of the graph.
deba@2190
   504
      ///
deba@2190
   505
      ///This function can be called more than once. In case of a repeated
deba@2190
   506
      ///call, the previous snapshot gets lost.
deba@2190
   507
      ///\param _g The graph we make the snapshot of.
deba@2190
   508
      void save(SmartUGraph &_g) 
deba@2190
   509
      {
deba@2190
   510
	g=&_g;
deba@2190
   511
	node_num=g->nodes.size();
deba@2190
   512
	edge_num=g->edges.size();
deba@2190
   513
      }
deba@2190
   514
deba@2190
   515
      ///Undo the changes until a snapshot.
deba@2190
   516
      
deba@2190
   517
      ///Undo the changes until a snapshot created by save().
deba@2190
   518
      ///
deba@2190
   519
      ///\note After you restored a state, you cannot restore
deba@2190
   520
      ///a later state, in other word you cannot add again the edges deleted
deba@2190
   521
      ///by restore().
deba@2190
   522
      void restore()
deba@2190
   523
      {
deba@2190
   524
	g->restoreSnapshot(*this);
deba@2190
   525
      }
deba@2190
   526
    };
deba@2116
   527
  };
deba@2116
   528
deba@2116
   529
deba@2116
   530
  class SmartBpUGraphBase {
deba@2116
   531
  public:
deba@2116
   532
deba@2116
   533
    class NodeSetError : public LogicError {
deba@2162
   534
    public:
alpar@2151
   535
      virtual const char* what() const throw() { 
deba@2116
   536
	return "lemon::SmartBpUGraph::NodeSetError";
deba@2116
   537
      }
deba@2116
   538
    };
deba@2116
   539
deba@2116
   540
  protected:
deba@2116
   541
deba@2116
   542
    struct NodeT {
deba@2116
   543
      int first;
deba@2116
   544
      NodeT() {}
deba@2116
   545
      NodeT(int _first) : first(_first) {}
deba@2116
   546
    };
deba@2116
   547
deba@2116
   548
    struct UEdgeT {
deba@2116
   549
      int aNode, next_out;
deba@2116
   550
      int bNode, next_in;
deba@2116
   551
    };
deba@2116
   552
deba@2116
   553
    std::vector<NodeT> aNodes;
deba@2116
   554
    std::vector<NodeT> bNodes;
deba@2116
   555
deba@2116
   556
    std::vector<UEdgeT> edges;
deba@2116
   557
deba@2116
   558
  public:
deba@2116
   559
  
deba@2116
   560
    class Node {
deba@2116
   561
      friend class SmartBpUGraphBase;
deba@2116
   562
    protected:
deba@2116
   563
      int id;
deba@2116
   564
deba@2190
   565
      explicit Node(int _id) : id(_id) {}
deba@2116
   566
    public:
deba@2116
   567
      Node() {}
deba@2190
   568
      Node(Invalid) : id(-1) {}
deba@2116
   569
      bool operator==(const Node i) const {return id==i.id;}
deba@2116
   570
      bool operator!=(const Node i) const {return id!=i.id;}
deba@2116
   571
      bool operator<(const Node i) const {return id<i.id;}
deba@2116
   572
    };
deba@2116
   573
deba@2116
   574
    class UEdge {
deba@2116
   575
      friend class SmartBpUGraphBase;
deba@2116
   576
    protected:
deba@2116
   577
      int id;
deba@2116
   578
deba@2190
   579
      UEdge(int _id) : id(_id) {}
deba@2116
   580
    public:
deba@2116
   581
      UEdge() {}
deba@2190
   582
      UEdge(Invalid) : id(-1) {}
deba@2116
   583
      bool operator==(const UEdge i) const {return id==i.id;}
deba@2116
   584
      bool operator!=(const UEdge i) const {return id!=i.id;}
deba@2116
   585
      bool operator<(const UEdge i) const {return id<i.id;}
deba@2116
   586
    };
deba@2116
   587
deba@2116
   588
    void firstANode(Node& node) const {
deba@2116
   589
      node.id = 2 * aNodes.size() - 2;
deba@2116
   590
      if (node.id < 0) node.id = -1; 
deba@2116
   591
    }
deba@2116
   592
    void nextANode(Node& node) const {
deba@2116
   593
      node.id -= 2;
deba@2116
   594
      if (node.id < 0) node.id = -1; 
deba@2116
   595
    }
deba@2116
   596
deba@2116
   597
    void firstBNode(Node& node) const {
deba@2116
   598
      node.id = 2 * bNodes.size() - 1;
deba@2116
   599
    }
deba@2116
   600
    void nextBNode(Node& node) const {
deba@2116
   601
      node.id -= 2;
deba@2116
   602
    }
deba@2116
   603
deba@2116
   604
    void first(Node& node) const {
deba@2116
   605
      if (aNodes.size() > 0) {
deba@2116
   606
	node.id = 2 * aNodes.size() - 2;
deba@2116
   607
      } else {
deba@2116
   608
	node.id = 2 * bNodes.size() - 1;
deba@2116
   609
      }
deba@2116
   610
    }
deba@2116
   611
    void next(Node& node) const {
deba@2116
   612
      node.id -= 2;
deba@2116
   613
      if (node.id == -2) {
deba@2116
   614
	node.id = 2 * bNodes.size() - 1;
deba@2116
   615
      }
deba@2116
   616
    }
deba@2116
   617
  
deba@2116
   618
    void first(UEdge& edge) const {
deba@2116
   619
      edge.id = edges.size() - 1;
deba@2116
   620
    }
deba@2116
   621
    void next(UEdge& edge) const {
deba@2116
   622
      --edge.id;
deba@2116
   623
    }
deba@2116
   624
deba@2116
   625
    void firstFromANode(UEdge& edge, const Node& node) const {
deba@2116
   626
      LEMON_ASSERT((node.id & 1) == 0, NodeSetError());
deba@2116
   627
      edge.id = aNodes[node.id >> 1].first;
deba@2116
   628
    }
deba@2116
   629
    void nextFromANode(UEdge& edge) const {
deba@2116
   630
      edge.id = edges[edge.id].next_out;
deba@2116
   631
    }
deba@2116
   632
deba@2116
   633
    void firstFromBNode(UEdge& edge, const Node& node) const {
deba@2116
   634
      LEMON_ASSERT((node.id & 1) == 1, NodeSetError());
deba@2116
   635
      edge.id = bNodes[node.id >> 1].first;
deba@2116
   636
    }
deba@2116
   637
    void nextFromBNode(UEdge& edge) const {
deba@2116
   638
      edge.id = edges[edge.id].next_in;
deba@2116
   639
    }
deba@2116
   640
deba@2116
   641
    static int id(const Node& node) {
deba@2116
   642
      return node.id;
deba@2116
   643
    }
deba@2116
   644
    static Node nodeFromId(int id) {
deba@2116
   645
      return Node(id);
deba@2116
   646
    }
deba@2116
   647
    int maxNodeId() const {
deba@2116
   648
      return aNodes.size() > bNodes.size() ?
deba@2116
   649
	aNodes.size() * 2 - 2 : bNodes.size() * 2 - 1;
deba@2116
   650
    }
deba@2116
   651
  
deba@2116
   652
    static int id(const UEdge& edge) {
deba@2116
   653
      return edge.id;
deba@2116
   654
    }
deba@2116
   655
    static UEdge uEdgeFromId(int id) {
deba@2116
   656
      return UEdge(id);
deba@2116
   657
    }
deba@2116
   658
    int maxUEdgeId() const {
deba@2116
   659
      return edges.size();
deba@2116
   660
    }
deba@2116
   661
  
deba@2116
   662
    static int aNodeId(const Node& node) {
deba@2116
   663
      return node.id >> 1;
deba@2116
   664
    }
deba@2231
   665
    static Node nodeFromANodeId(int id) {
deba@2116
   666
      return Node(id << 1);
deba@2116
   667
    }
deba@2116
   668
    int maxANodeId() const {
deba@2116
   669
      return aNodes.size();
deba@2116
   670
    }
deba@2116
   671
deba@2116
   672
    static int bNodeId(const Node& node) {
deba@2116
   673
      return node.id >> 1;
deba@2116
   674
    }
deba@2231
   675
    static Node nodeFromBNodeId(int id) {
deba@2116
   676
      return Node((id << 1) + 1);
deba@2116
   677
    }
deba@2116
   678
    int maxBNodeId() const {
deba@2116
   679
      return bNodes.size();
deba@2116
   680
    }
deba@2116
   681
deba@2116
   682
    Node aNode(const UEdge& edge) const {
deba@2116
   683
      return Node(edges[edge.id].aNode);
deba@2116
   684
    }
deba@2116
   685
    Node bNode(const UEdge& edge) const {
deba@2116
   686
      return Node(edges[edge.id].bNode);
deba@2116
   687
    }
deba@2116
   688
deba@2116
   689
    static bool aNode(const Node& node) {
deba@2116
   690
      return (node.id & 1) == 0;
deba@2116
   691
    }
deba@2116
   692
deba@2116
   693
    static bool bNode(const Node& node) {
deba@2116
   694
      return (node.id & 1) == 1;
deba@2116
   695
    }
deba@2116
   696
deba@2116
   697
    Node addANode() {
deba@2116
   698
      NodeT nodeT;
deba@2116
   699
      nodeT.first = -1;
deba@2116
   700
      aNodes.push_back(nodeT);
deba@2116
   701
      return Node(aNodes.size() * 2 - 2);
deba@2116
   702
    }
deba@2116
   703
deba@2116
   704
    Node addBNode() {
deba@2116
   705
      NodeT nodeT;
deba@2116
   706
      nodeT.first = -1;
deba@2116
   707
      bNodes.push_back(nodeT);
deba@2116
   708
      return Node(bNodes.size() * 2 - 1);
deba@2116
   709
    }
deba@2116
   710
deba@2116
   711
    UEdge addEdge(const Node& source, const Node& target) {
deba@2116
   712
      LEMON_ASSERT(((source.id ^ target.id) & 1) == 1, NodeSetError());
deba@2116
   713
      UEdgeT edgeT;
deba@2116
   714
      if ((source.id & 1) == 0) {
deba@2116
   715
	edgeT.aNode = source.id;
deba@2116
   716
	edgeT.bNode = target.id;
deba@2116
   717
      } else {
deba@2116
   718
	edgeT.aNode = target.id;
deba@2116
   719
	edgeT.bNode = source.id;
deba@2116
   720
      }
deba@2116
   721
      edgeT.next_out = aNodes[edgeT.aNode >> 1].first;
deba@2116
   722
      aNodes[edgeT.aNode >> 1].first = edges.size();
deba@2116
   723
      edgeT.next_in = bNodes[edgeT.bNode >> 1].first;
deba@2116
   724
      bNodes[edgeT.bNode >> 1].first = edges.size();
deba@2116
   725
      edges.push_back(edgeT);
deba@2116
   726
      return UEdge(edges.size() - 1);
deba@2116
   727
    }
deba@2116
   728
deba@2116
   729
    void clear() {
deba@2116
   730
      aNodes.clear();
deba@2116
   731
      bNodes.clear();
deba@2116
   732
      edges.clear();
deba@2116
   733
    }
deba@2116
   734
deba@2116
   735
    typedef True NodeNumTag;
deba@2116
   736
    int nodeNum() const { return aNodes.size() + bNodes.size(); }
deba@2116
   737
    int aNodeNum() const { return aNodes.size(); }
deba@2116
   738
    int bNodeNum() const { return bNodes.size(); }
deba@2116
   739
deba@2116
   740
    typedef True EdgeNumTag;
deba@2116
   741
    int uEdgeNum() const { return edges.size(); }
deba@2116
   742
deba@2116
   743
  };
deba@2116
   744
deba@2116
   745
deba@2231
   746
  typedef BpUGraphExtender<BidirBpUGraphExtender<SmartBpUGraphBase> >
deba@2231
   747
  ExtendedSmartBpUGraphBase;
deba@2116
   748
deba@2116
   749
  /// \ingroup graphs
deba@2116
   750
  ///
deba@2116
   751
  /// \brief A smart bipartite undirected graph class.
deba@2116
   752
  ///
deba@2116
   753
  /// This is a simple and fast bipartite undirected graph implementation.
deba@2116
   754
  /// It is also quite memory efficient, but at the price
deba@2116
   755
  /// that <b> it does not support node and edge deletions</b>.
deba@2116
   756
  /// Except from this it conforms to 
alpar@2123
   757
  /// the \ref concept::BpUGraph "BpUGraph concept".
deba@2116
   758
  /// \sa concept::BpUGraph.
deba@2116
   759
  ///
deba@2190
   760
  class SmartBpUGraph : public ExtendedSmartBpUGraphBase {
deba@2190
   761
  private:
deba@2190
   762
deba@2190
   763
    /// \brief SmartBpUGraph is \e not copy constructible.
deba@2190
   764
    ///
deba@2190
   765
    ///SmartBpUGraph is \e not copy constructible.
deba@2190
   766
    SmartBpUGraph(const SmartBpUGraph &) : ExtendedSmartBpUGraphBase() {};
deba@2190
   767
deba@2190
   768
    /// \brief Assignment of SmartBpUGraph to another one is \e not
deba@2190
   769
    /// allowed.
deba@2190
   770
    ///
deba@2190
   771
    /// Assignment of SmartBpUGraph to another one is \e not allowed.
deba@2190
   772
    void operator=(const SmartBpUGraph &) {}
deba@2190
   773
deba@2190
   774
  public:
deba@2190
   775
deba@2190
   776
    typedef ExtendedSmartBpUGraphBase Parent;
deba@2190
   777
deba@2190
   778
    ///Constructor
deba@2190
   779
    
deba@2190
   780
    ///Constructor.
deba@2190
   781
    ///
deba@2190
   782
    SmartBpUGraph() : ExtendedSmartBpUGraphBase() {}
deba@2190
   783
deba@2190
   784
    ///Add a new ANode to the graph.
deba@2190
   785
    
deba@2190
   786
    /// \return the new node.
deba@2190
   787
    ///
deba@2190
   788
    Node addANode() { return Parent::addANode(); }
deba@2190
   789
deba@2190
   790
    ///Add a new BNode to the graph.
deba@2190
   791
    
deba@2190
   792
    /// \return the new node.
deba@2190
   793
    ///
deba@2190
   794
    Node addBNode() { return Parent::addBNode(); }
deba@2190
   795
    
deba@2190
   796
    ///Add a new undirected edge to the graph.
deba@2190
   797
    
deba@2190
   798
    ///Add a new undirected edge to the graph with node \c s
deba@2190
   799
    ///and \c t.
deba@2190
   800
    ///\return the new undirected edge.
deba@2190
   801
    UEdge addEdge(const Node& s, const Node& t) { 
deba@2190
   802
      return Parent::addEdge(s, t); 
deba@2190
   803
    }
deba@2190
   804
deba@2190
   805
    ///Clear the graph.
deba@2190
   806
    
deba@2190
   807
    ///Erase all the nodes and edges from the graph.
deba@2190
   808
    ///
deba@2190
   809
    void clear() {
deba@2190
   810
      Parent::clear();
deba@2190
   811
    }
deba@2190
   812
    
deba@2190
   813
  public:
deba@2190
   814
deba@2190
   815
    class Snapshot;
deba@2190
   816
deba@2190
   817
  protected:
deba@2190
   818
    
deba@2190
   819
    void restoreSnapshot(const Snapshot &s)
deba@2190
   820
    {
deba@2190
   821
      while(s.edge_num<edges.size()) {
deba@2190
   822
        UEdge edge = uEdgeFromId(edges.size()-1);
deba@2190
   823
	Parent::getNotifier(UEdge()).erase(edge);
deba@2190
   824
        std::vector<Edge> dir;
deba@2190
   825
        dir.push_back(Parent::direct(edge, true));
deba@2190
   826
        dir.push_back(Parent::direct(edge, false));
deba@2190
   827
	Parent::getNotifier(Edge()).erase(dir);
deba@2190
   828
	aNodes[edges.back().aNode >> 1].first=edges.back().next_out;
deba@2190
   829
	bNodes[edges.back().bNode >> 1].first=edges.back().next_in;
deba@2190
   830
	edges.pop_back();
deba@2190
   831
      }
deba@2190
   832
      while(s.anode_num<aNodes.size()) {
deba@2231
   833
        Node node = nodeFromANodeId(aNodes.size() - 1);
deba@2190
   834
	Parent::getNotifier(ANode()).erase(node);
deba@2190
   835
	Parent::getNotifier(Node()).erase(node);
deba@2190
   836
	aNodes.pop_back();
deba@2190
   837
      }
deba@2190
   838
      while(s.bnode_num<bNodes.size()) {
deba@2231
   839
        Node node = nodeFromBNodeId(bNodes.size() - 1);
deba@2190
   840
	Parent::getNotifier(BNode()).erase(node);
deba@2190
   841
	Parent::getNotifier(Node()).erase(node);
deba@2190
   842
	bNodes.pop_back();
deba@2190
   843
      }
deba@2190
   844
    }    
deba@2190
   845
deba@2190
   846
  public:
deba@2190
   847
deba@2190
   848
    ///Class to make a snapshot of the graph and to restrore to it later.
deba@2190
   849
deba@2190
   850
    ///Class to make a snapshot of the graph and to restrore to it later.
deba@2190
   851
    ///
deba@2190
   852
    ///The newly added nodes and edges can be removed using the
deba@2190
   853
    ///restore() function.
deba@2190
   854
    ///
deba@2190
   855
    ///\note After you restore a state, you cannot restore
deba@2190
   856
    ///a later state, in other word you cannot add again the edges deleted
deba@2190
   857
    ///by restore() using another one Snapshot instance.
deba@2190
   858
    ///
deba@2190
   859
    ///\warning If you do not use correctly the snapshot that can cause
deba@2190
   860
    ///either broken program, invalid state of the graph, valid but
deba@2190
   861
    ///not the restored graph or no change. Because the runtime performance
deba@2190
   862
    ///the validity of the snapshot is not stored.
deba@2190
   863
    class Snapshot 
deba@2190
   864
    {
deba@2190
   865
      SmartBpUGraph *g;
deba@2190
   866
    protected:
deba@2190
   867
      friend class SmartBpUGraph;
deba@2190
   868
      unsigned int anode_num;
deba@2190
   869
      unsigned int bnode_num;
deba@2190
   870
      unsigned int edge_num;
deba@2190
   871
    public:
deba@2190
   872
      ///Default constructor.
deba@2190
   873
      
deba@2190
   874
      ///Default constructor.
deba@2190
   875
      ///To actually make a snapshot you must call save().
deba@2190
   876
      ///
deba@2190
   877
      Snapshot() : g(0) {}
deba@2190
   878
deba@2190
   879
      ///Constructor that immediately makes a snapshot
deba@2190
   880
      
deba@2190
   881
      ///This constructor immediately makes a snapshot of the graph.
deba@2190
   882
      ///\param _g The graph we make a snapshot of.
deba@2190
   883
      Snapshot(SmartBpUGraph &_g) : g(&_g) {
deba@2190
   884
	anode_num=g->aNodes.size();
deba@2190
   885
	bnode_num=g->bNodes.size();
deba@2190
   886
	edge_num=g->edges.size();
deba@2190
   887
      }
deba@2190
   888
deba@2190
   889
      ///Make a snapshot.
deba@2190
   890
deba@2190
   891
      ///Make a snapshot of the graph.
deba@2190
   892
      ///
deba@2190
   893
      ///This function can be called more than once. In case of a repeated
deba@2190
   894
      ///call, the previous snapshot gets lost.
deba@2190
   895
      ///\param _g The graph we make the snapshot of.
deba@2190
   896
      void save(SmartBpUGraph &_g) 
deba@2190
   897
      {
deba@2190
   898
	g=&_g;
deba@2190
   899
	anode_num=g->aNodes.size();
deba@2190
   900
	bnode_num=g->bNodes.size();
deba@2190
   901
	edge_num=g->edges.size();
deba@2190
   902
      }
deba@2190
   903
deba@2190
   904
      ///Undo the changes until a snapshot.
deba@2190
   905
      
deba@2190
   906
      ///Undo the changes until a snapshot created by save().
deba@2190
   907
      ///
deba@2190
   908
      ///\note After you restored a state, you cannot restore
deba@2190
   909
      ///a later state, in other word you cannot add again the edges deleted
deba@2190
   910
      ///by restore().
deba@2190
   911
      void restore()
deba@2190
   912
      {
deba@2190
   913
	g->restoreSnapshot(*this);
deba@2190
   914
      }
deba@2190
   915
    };
deba@2190
   916
  };
deba@2116
   917
deba@2116
   918
  
deba@2116
   919
  /// @}  
alpar@921
   920
} //namespace lemon
alpar@104
   921
alpar@157
   922
alpar@921
   923
#endif //LEMON_SMART_GRAPH_H