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