lemon/smart_graph.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 936 ddd3c0d3d9bf
parent 787 c2230649a493
child 1019 4c89e925cfe2
permissions -rw-r--r--
Implement the scaling Price Refinement heuristic in CostScaling (#417)
instead of Early Termination.

These two heuristics are similar, but the newer one is faster
and not only makes it possible to skip some epsilon phases, but
it can improve the performance of the other phases, as well.
     1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library.
     4  *
     5  * Copyright (C) 2003-2010
     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 SmartDigraph and SmartGraph classes.
    25 
    26 #include <vector>
    27 
    28 #include <lemon/core.h>
    29 #include <lemon/error.h>
    30 #include <lemon/bits/graph_extender.h>
    31 
    32 namespace lemon {
    33 
    34   class SmartDigraph;
    35 
    36   class SmartDigraphBase {
    37   protected:
    38 
    39     struct NodeT
    40     {
    41       int first_in, first_out;
    42       NodeT() {}
    43     };
    44     struct ArcT
    45     {
    46       int target, source, next_in, next_out;
    47       ArcT() {}
    48     };
    49 
    50     std::vector<NodeT> nodes;
    51     std::vector<ArcT> arcs;
    52 
    53   public:
    54 
    55     typedef SmartDigraphBase Digraph;
    56 
    57     class Node;
    58     class Arc;
    59 
    60   public:
    61 
    62     SmartDigraphBase() : nodes(), arcs() { }
    63     SmartDigraphBase(const SmartDigraphBase &_g)
    64       : nodes(_g.nodes), arcs(_g.arcs) { }
    65 
    66     typedef True NodeNumTag;
    67     typedef True ArcNumTag;
    68 
    69     int nodeNum() const { return nodes.size(); }
    70     int arcNum() const { return arcs.size(); }
    71 
    72     int maxNodeId() const { return nodes.size()-1; }
    73     int maxArcId() const { return arcs.size()-1; }
    74 
    75     Node addNode() {
    76       int n = nodes.size();
    77       nodes.push_back(NodeT());
    78       nodes[n].first_in = -1;
    79       nodes[n].first_out = -1;
    80       return Node(n);
    81     }
    82 
    83     Arc addArc(Node u, Node v) {
    84       int n = arcs.size();
    85       arcs.push_back(ArcT());
    86       arcs[n].source = u._id;
    87       arcs[n].target = v._id;
    88       arcs[n].next_out = nodes[u._id].first_out;
    89       arcs[n].next_in = nodes[v._id].first_in;
    90       nodes[u._id].first_out = nodes[v._id].first_in = n;
    91 
    92       return Arc(n);
    93     }
    94 
    95     void clear() {
    96       arcs.clear();
    97       nodes.clear();
    98     }
    99 
   100     Node source(Arc a) const { return Node(arcs[a._id].source); }
   101     Node target(Arc a) const { return Node(arcs[a._id].target); }
   102 
   103     static int id(Node v) { return v._id; }
   104     static int id(Arc a) { return a._id; }
   105 
   106     static Node nodeFromId(int id) { return Node(id);}
   107     static Arc arcFromId(int id) { return Arc(id);}
   108 
   109     bool valid(Node n) const {
   110       return n._id >= 0 && n._id < static_cast<int>(nodes.size());
   111     }
   112     bool valid(Arc a) const {
   113       return a._id >= 0 && a._id < static_cast<int>(arcs.size());
   114     }
   115 
   116     class Node {
   117       friend class SmartDigraphBase;
   118       friend class SmartDigraph;
   119 
   120     protected:
   121       int _id;
   122       explicit Node(int id) : _id(id) {}
   123     public:
   124       Node() {}
   125       Node (Invalid) : _id(-1) {}
   126       bool operator==(const Node i) const {return _id == i._id;}
   127       bool operator!=(const Node i) const {return _id != i._id;}
   128       bool operator<(const Node i) const {return _id < i._id;}
   129     };
   130 
   131 
   132     class Arc {
   133       friend class SmartDigraphBase;
   134       friend class SmartDigraph;
   135 
   136     protected:
   137       int _id;
   138       explicit Arc(int id) : _id(id) {}
   139     public:
   140       Arc() { }
   141       Arc (Invalid) : _id(-1) {}
   142       bool operator==(const Arc i) const {return _id == i._id;}
   143       bool operator!=(const Arc i) const {return _id != i._id;}
   144       bool operator<(const Arc i) const {return _id < i._id;}
   145     };
   146 
   147     void first(Node& node) const {
   148       node._id = nodes.size() - 1;
   149     }
   150 
   151     static void next(Node& node) {
   152       --node._id;
   153     }
   154 
   155     void first(Arc& arc) const {
   156       arc._id = arcs.size() - 1;
   157     }
   158 
   159     static void next(Arc& arc) {
   160       --arc._id;
   161     }
   162 
   163     void firstOut(Arc& arc, const Node& node) const {
   164       arc._id = nodes[node._id].first_out;
   165     }
   166 
   167     void nextOut(Arc& arc) const {
   168       arc._id = arcs[arc._id].next_out;
   169     }
   170 
   171     void firstIn(Arc& arc, const Node& node) const {
   172       arc._id = nodes[node._id].first_in;
   173     }
   174 
   175     void nextIn(Arc& arc) const {
   176       arc._id = arcs[arc._id].next_in;
   177     }
   178 
   179   };
   180 
   181   typedef DigraphExtender<SmartDigraphBase> ExtendedSmartDigraphBase;
   182 
   183   ///\ingroup graphs
   184   ///
   185   ///\brief A smart directed graph class.
   186   ///
   187   ///\ref SmartDigraph is a simple and fast digraph implementation.
   188   ///It is also quite memory efficient but at the price
   189   ///that it does not support node and arc deletion
   190   ///(except for the Snapshot feature).
   191   ///
   192   ///This type fully conforms to the \ref concepts::Digraph "Digraph concept"
   193   ///and it also provides some additional functionalities.
   194   ///Most of its member functions and nested classes are documented
   195   ///only in the concept class.
   196   ///
   197   ///This class provides constant time counting for nodes and arcs.
   198   ///
   199   ///\sa concepts::Digraph
   200   ///\sa SmartGraph
   201   class SmartDigraph : public ExtendedSmartDigraphBase {
   202     typedef ExtendedSmartDigraphBase Parent;
   203 
   204   private:
   205     /// Digraphs are \e not copy constructible. Use DigraphCopy instead.
   206     SmartDigraph(const SmartDigraph &) : ExtendedSmartDigraphBase() {};
   207     /// \brief Assignment of a digraph to another one is \e not allowed.
   208     /// Use DigraphCopy instead.
   209     void operator=(const SmartDigraph &) {}
   210 
   211   public:
   212 
   213     /// Constructor
   214 
   215     /// Constructor.
   216     ///
   217     SmartDigraph() {};
   218 
   219     ///Add a new node to the digraph.
   220 
   221     ///This function adds a new node to the digraph.
   222     ///\return The new node.
   223     Node addNode() { return Parent::addNode(); }
   224 
   225     ///Add a new arc to the digraph.
   226 
   227     ///This function adds a new arc to the digraph with source node \c s
   228     ///and target node \c t.
   229     ///\return The new arc.
   230     Arc addArc(Node s, Node t) {
   231       return Parent::addArc(s, t);
   232     }
   233 
   234     /// \brief Node validity check
   235     ///
   236     /// This function gives back \c true if the given node is valid,
   237     /// i.e. it is a real node of the digraph.
   238     ///
   239     /// \warning A removed node (using Snapshot) could become valid again
   240     /// if new nodes are added to the digraph.
   241     bool valid(Node n) const { return Parent::valid(n); }
   242 
   243     /// \brief Arc validity check
   244     ///
   245     /// This function gives back \c true if the given arc is valid,
   246     /// i.e. it is a real arc of the digraph.
   247     ///
   248     /// \warning A removed arc (using Snapshot) could become valid again
   249     /// if new arcs are added to the graph.
   250     bool valid(Arc a) const { return Parent::valid(a); }
   251 
   252     ///Split a node.
   253 
   254     ///This function splits the given node. First, a new node is added
   255     ///to the digraph, then the source of each outgoing arc of node \c n
   256     ///is moved to this new node.
   257     ///If the second parameter \c connect is \c true (this is the default
   258     ///value), then a new arc from node \c n to the newly created node
   259     ///is also added.
   260     ///\return The newly created node.
   261     ///
   262     ///\note All iterators remain valid.
   263     ///
   264     ///\warning This functionality cannot be used together with the Snapshot
   265     ///feature.
   266     Node split(Node n, bool connect = true)
   267     {
   268       Node b = addNode();
   269       nodes[b._id].first_out=nodes[n._id].first_out;
   270       nodes[n._id].first_out=-1;
   271       for(int i=nodes[b._id].first_out; i!=-1; i=arcs[i].next_out) {
   272         arcs[i].source=b._id;
   273       }
   274       if(connect) addArc(n,b);
   275       return b;
   276     }
   277 
   278     ///Clear the digraph.
   279 
   280     ///This function erases all nodes and arcs from the digraph.
   281     ///
   282     void clear() {
   283       Parent::clear();
   284     }
   285 
   286     /// Reserve memory for nodes.
   287 
   288     /// Using this function, it is possible to avoid superfluous memory
   289     /// allocation: if you know that the digraph you want to build will
   290     /// be large (e.g. it will contain millions of nodes and/or arcs),
   291     /// then it is worth reserving space for this amount before starting
   292     /// to build the digraph.
   293     /// \sa reserveArc()
   294     void reserveNode(int n) { nodes.reserve(n); };
   295 
   296     /// Reserve memory for arcs.
   297 
   298     /// Using this function, it is possible to avoid superfluous memory
   299     /// allocation: if you know that the digraph you want to build will
   300     /// be large (e.g. it will contain millions of nodes and/or arcs),
   301     /// then it is worth reserving space for this amount before starting
   302     /// to build the digraph.
   303     /// \sa reserveNode()
   304     void reserveArc(int m) { arcs.reserve(m); };
   305 
   306   public:
   307 
   308     class Snapshot;
   309 
   310   protected:
   311 
   312     void restoreSnapshot(const Snapshot &s)
   313     {
   314       while(s.arc_num<arcs.size()) {
   315         Arc arc = arcFromId(arcs.size()-1);
   316         Parent::notifier(Arc()).erase(arc);
   317         nodes[arcs.back().source].first_out=arcs.back().next_out;
   318         nodes[arcs.back().target].first_in=arcs.back().next_in;
   319         arcs.pop_back();
   320       }
   321       while(s.node_num<nodes.size()) {
   322         Node node = nodeFromId(nodes.size()-1);
   323         Parent::notifier(Node()).erase(node);
   324         nodes.pop_back();
   325       }
   326     }
   327 
   328   public:
   329 
   330     ///Class to make a snapshot of the digraph and to restore it later.
   331 
   332     ///Class to make a snapshot of the digraph and to restore it later.
   333     ///
   334     ///The newly added nodes and arcs can be removed using the
   335     ///restore() function. This is the only way for deleting nodes and/or
   336     ///arcs from a SmartDigraph structure.
   337     ///
   338     ///\note After a state is restored, you cannot restore a later state,
   339     ///i.e. you cannot add the removed nodes and arcs again using
   340     ///another Snapshot instance.
   341     ///
   342     ///\warning Node splitting cannot be restored.
   343     ///\warning The validity of the snapshot is not stored due to
   344     ///performance reasons. If you do not use the snapshot correctly,
   345     ///it can cause broken program, invalid or not restored state of
   346     ///the digraph or no change.
   347     class Snapshot
   348     {
   349       SmartDigraph *_graph;
   350     protected:
   351       friend class SmartDigraph;
   352       unsigned int node_num;
   353       unsigned int arc_num;
   354     public:
   355       ///Default constructor.
   356 
   357       ///Default constructor.
   358       ///You have to call save() to actually make a snapshot.
   359       Snapshot() : _graph(0) {}
   360       ///Constructor that immediately makes a snapshot
   361 
   362       ///This constructor immediately makes a snapshot of the given digraph.
   363       ///
   364       Snapshot(SmartDigraph &gr) : _graph(&gr) {
   365         node_num=_graph->nodes.size();
   366         arc_num=_graph->arcs.size();
   367       }
   368 
   369       ///Make a snapshot.
   370 
   371       ///This function makes a snapshot of the given digraph.
   372       ///It can be called more than once. In case of a repeated
   373       ///call, the previous snapshot gets lost.
   374       void save(SmartDigraph &gr) {
   375         _graph=&gr;
   376         node_num=_graph->nodes.size();
   377         arc_num=_graph->arcs.size();
   378       }
   379 
   380       ///Undo the changes until a snapshot.
   381 
   382       ///This function undos the changes until the last snapshot
   383       ///created by save() or Snapshot(SmartDigraph&).
   384       void restore()
   385       {
   386         _graph->restoreSnapshot(*this);
   387       }
   388     };
   389   };
   390 
   391 
   392   class SmartGraphBase {
   393 
   394   protected:
   395 
   396     struct NodeT {
   397       int first_out;
   398     };
   399 
   400     struct ArcT {
   401       int target;
   402       int next_out;
   403     };
   404 
   405     std::vector<NodeT> nodes;
   406     std::vector<ArcT> arcs;
   407 
   408     int first_free_arc;
   409 
   410   public:
   411 
   412     typedef SmartGraphBase Graph;
   413 
   414     class Node;
   415     class Arc;
   416     class Edge;
   417 
   418     class Node {
   419       friend class SmartGraphBase;
   420     protected:
   421 
   422       int _id;
   423       explicit Node(int id) { _id = id;}
   424 
   425     public:
   426       Node() {}
   427       Node (Invalid) { _id = -1; }
   428       bool operator==(const Node& node) const {return _id == node._id;}
   429       bool operator!=(const Node& node) const {return _id != node._id;}
   430       bool operator<(const Node& node) const {return _id < node._id;}
   431     };
   432 
   433     class Edge {
   434       friend class SmartGraphBase;
   435     protected:
   436 
   437       int _id;
   438       explicit Edge(int id) { _id = id;}
   439 
   440     public:
   441       Edge() {}
   442       Edge (Invalid) { _id = -1; }
   443       bool operator==(const Edge& arc) const {return _id == arc._id;}
   444       bool operator!=(const Edge& arc) const {return _id != arc._id;}
   445       bool operator<(const Edge& arc) const {return _id < arc._id;}
   446     };
   447 
   448     class Arc {
   449       friend class SmartGraphBase;
   450     protected:
   451 
   452       int _id;
   453       explicit Arc(int id) { _id = id;}
   454 
   455     public:
   456       operator Edge() const {
   457         return _id != -1 ? edgeFromId(_id / 2) : INVALID;
   458       }
   459 
   460       Arc() {}
   461       Arc (Invalid) { _id = -1; }
   462       bool operator==(const Arc& arc) const {return _id == arc._id;}
   463       bool operator!=(const Arc& arc) const {return _id != arc._id;}
   464       bool operator<(const Arc& arc) const {return _id < arc._id;}
   465     };
   466 
   467 
   468 
   469     SmartGraphBase()
   470       : nodes(), arcs() {}
   471 
   472     typedef True NodeNumTag;
   473     typedef True EdgeNumTag;
   474     typedef True ArcNumTag;
   475 
   476     int nodeNum() const { return nodes.size(); }
   477     int edgeNum() const { return arcs.size() / 2; }
   478     int arcNum() const { return arcs.size(); }
   479 
   480     int maxNodeId() const { return nodes.size()-1; }
   481     int maxEdgeId() const { return arcs.size() / 2 - 1; }
   482     int maxArcId() const { return arcs.size()-1; }
   483 
   484     Node source(Arc e) const { return Node(arcs[e._id ^ 1].target); }
   485     Node target(Arc e) const { return Node(arcs[e._id].target); }
   486 
   487     Node u(Edge e) const { return Node(arcs[2 * e._id].target); }
   488     Node v(Edge e) const { return Node(arcs[2 * e._id + 1].target); }
   489 
   490     static bool direction(Arc e) {
   491       return (e._id & 1) == 1;
   492     }
   493 
   494     static Arc direct(Edge e, bool d) {
   495       return Arc(e._id * 2 + (d ? 1 : 0));
   496     }
   497 
   498     void first(Node& node) const {
   499       node._id = nodes.size() - 1;
   500     }
   501 
   502     static void next(Node& node) {
   503       --node._id;
   504     }
   505 
   506     void first(Arc& arc) const {
   507       arc._id = arcs.size() - 1;
   508     }
   509 
   510     static void next(Arc& arc) {
   511       --arc._id;
   512     }
   513 
   514     void first(Edge& arc) const {
   515       arc._id = arcs.size() / 2 - 1;
   516     }
   517 
   518     static void next(Edge& arc) {
   519       --arc._id;
   520     }
   521 
   522     void firstOut(Arc &arc, const Node& v) const {
   523       arc._id = nodes[v._id].first_out;
   524     }
   525     void nextOut(Arc &arc) const {
   526       arc._id = arcs[arc._id].next_out;
   527     }
   528 
   529     void firstIn(Arc &arc, const Node& v) const {
   530       arc._id = ((nodes[v._id].first_out) ^ 1);
   531       if (arc._id == -2) arc._id = -1;
   532     }
   533     void nextIn(Arc &arc) const {
   534       arc._id = ((arcs[arc._id ^ 1].next_out) ^ 1);
   535       if (arc._id == -2) arc._id = -1;
   536     }
   537 
   538     void firstInc(Edge &arc, bool& d, const Node& v) const {
   539       int de = nodes[v._id].first_out;
   540       if (de != -1) {
   541         arc._id = de / 2;
   542         d = ((de & 1) == 1);
   543       } else {
   544         arc._id = -1;
   545         d = true;
   546       }
   547     }
   548     void nextInc(Edge &arc, bool& d) const {
   549       int de = (arcs[(arc._id * 2) | (d ? 1 : 0)].next_out);
   550       if (de != -1) {
   551         arc._id = de / 2;
   552         d = ((de & 1) == 1);
   553       } else {
   554         arc._id = -1;
   555         d = true;
   556       }
   557     }
   558 
   559     static int id(Node v) { return v._id; }
   560     static int id(Arc e) { return e._id; }
   561     static int id(Edge e) { return e._id; }
   562 
   563     static Node nodeFromId(int id) { return Node(id);}
   564     static Arc arcFromId(int id) { return Arc(id);}
   565     static Edge edgeFromId(int id) { return Edge(id);}
   566 
   567     bool valid(Node n) const {
   568       return n._id >= 0 && n._id < static_cast<int>(nodes.size());
   569     }
   570     bool valid(Arc a) const {
   571       return a._id >= 0 && a._id < static_cast<int>(arcs.size());
   572     }
   573     bool valid(Edge e) const {
   574       return e._id >= 0 && 2 * e._id < static_cast<int>(arcs.size());
   575     }
   576 
   577     Node addNode() {
   578       int n = nodes.size();
   579       nodes.push_back(NodeT());
   580       nodes[n].first_out = -1;
   581 
   582       return Node(n);
   583     }
   584 
   585     Edge addEdge(Node u, Node v) {
   586       int n = arcs.size();
   587       arcs.push_back(ArcT());
   588       arcs.push_back(ArcT());
   589 
   590       arcs[n].target = u._id;
   591       arcs[n | 1].target = v._id;
   592 
   593       arcs[n].next_out = nodes[v._id].first_out;
   594       nodes[v._id].first_out = n;
   595 
   596       arcs[n | 1].next_out = nodes[u._id].first_out;
   597       nodes[u._id].first_out = (n | 1);
   598 
   599       return Edge(n / 2);
   600     }
   601 
   602     void clear() {
   603       arcs.clear();
   604       nodes.clear();
   605     }
   606 
   607   };
   608 
   609   typedef GraphExtender<SmartGraphBase> ExtendedSmartGraphBase;
   610 
   611   /// \ingroup graphs
   612   ///
   613   /// \brief A smart undirected graph class.
   614   ///
   615   /// \ref SmartGraph is a simple and fast graph implementation.
   616   /// It is also quite memory efficient but at the price
   617   /// that it does not support node and edge deletion
   618   /// (except for the Snapshot feature).
   619   ///
   620   /// This type fully conforms to the \ref concepts::Graph "Graph concept"
   621   /// and it also provides some additional functionalities.
   622   /// Most of its member functions and nested classes are documented
   623   /// only in the concept class.
   624   ///
   625   /// This class provides constant time counting for nodes, edges and arcs.
   626   ///
   627   /// \sa concepts::Graph
   628   /// \sa SmartDigraph
   629   class SmartGraph : public ExtendedSmartGraphBase {
   630     typedef ExtendedSmartGraphBase Parent;
   631 
   632   private:
   633     /// Graphs are \e not copy constructible. Use GraphCopy instead.
   634     SmartGraph(const SmartGraph &) : ExtendedSmartGraphBase() {};
   635     /// \brief Assignment of a graph to another one is \e not allowed.
   636     /// Use GraphCopy instead.
   637     void operator=(const SmartGraph &) {}
   638 
   639   public:
   640 
   641     /// Constructor
   642 
   643     /// Constructor.
   644     ///
   645     SmartGraph() {}
   646 
   647     /// \brief Add a new node to the graph.
   648     ///
   649     /// This function adds a new node to the graph.
   650     /// \return The new node.
   651     Node addNode() { return Parent::addNode(); }
   652 
   653     /// \brief Add a new edge to the graph.
   654     ///
   655     /// This function adds a new edge to the graph between nodes
   656     /// \c u and \c v with inherent orientation from node \c u to
   657     /// node \c v.
   658     /// \return The new edge.
   659     Edge addEdge(Node u, Node v) {
   660       return Parent::addEdge(u, v);
   661     }
   662 
   663     /// \brief Node validity check
   664     ///
   665     /// This function gives back \c true if the given node is valid,
   666     /// i.e. it is a real node of the graph.
   667     ///
   668     /// \warning A removed node (using Snapshot) could become valid again
   669     /// if new nodes are added to the graph.
   670     bool valid(Node n) const { return Parent::valid(n); }
   671 
   672     /// \brief Edge validity check
   673     ///
   674     /// This function gives back \c true if the given edge is valid,
   675     /// i.e. it is a real edge of the graph.
   676     ///
   677     /// \warning A removed edge (using Snapshot) could become valid again
   678     /// if new edges are added to the graph.
   679     bool valid(Edge e) const { return Parent::valid(e); }
   680 
   681     /// \brief Arc validity check
   682     ///
   683     /// This function gives back \c true if the given arc is valid,
   684     /// i.e. it is a real arc of the graph.
   685     ///
   686     /// \warning A removed arc (using Snapshot) could become valid again
   687     /// if new edges are added to the graph.
   688     bool valid(Arc a) const { return Parent::valid(a); }
   689 
   690     ///Clear the graph.
   691 
   692     ///This function erases all nodes and arcs from the graph.
   693     ///
   694     void clear() {
   695       Parent::clear();
   696     }
   697 
   698     /// Reserve memory for nodes.
   699 
   700     /// Using this function, it is possible to avoid superfluous memory
   701     /// allocation: if you know that the graph you want to build will
   702     /// be large (e.g. it will contain millions of nodes and/or edges),
   703     /// then it is worth reserving space for this amount before starting
   704     /// to build the graph.
   705     /// \sa reserveEdge()
   706     void reserveNode(int n) { nodes.reserve(n); };
   707 
   708     /// Reserve memory for edges.
   709 
   710     /// Using this function, it is possible to avoid superfluous memory
   711     /// allocation: if you know that the graph you want to build will
   712     /// be large (e.g. it will contain millions of nodes and/or edges),
   713     /// then it is worth reserving space for this amount before starting
   714     /// to build the graph.
   715     /// \sa reserveNode()
   716     void reserveEdge(int m) { arcs.reserve(2 * m); };
   717 
   718   public:
   719 
   720     class Snapshot;
   721 
   722   protected:
   723 
   724     void saveSnapshot(Snapshot &s)
   725     {
   726       s._graph = this;
   727       s.node_num = nodes.size();
   728       s.arc_num = arcs.size();
   729     }
   730 
   731     void restoreSnapshot(const Snapshot &s)
   732     {
   733       while(s.arc_num<arcs.size()) {
   734         int n=arcs.size()-1;
   735         Edge arc=edgeFromId(n/2);
   736         Parent::notifier(Edge()).erase(arc);
   737         std::vector<Arc> dir;
   738         dir.push_back(arcFromId(n));
   739         dir.push_back(arcFromId(n-1));
   740         Parent::notifier(Arc()).erase(dir);
   741         nodes[arcs[n-1].target].first_out=arcs[n].next_out;
   742         nodes[arcs[n].target].first_out=arcs[n-1].next_out;
   743         arcs.pop_back();
   744         arcs.pop_back();
   745       }
   746       while(s.node_num<nodes.size()) {
   747         int n=nodes.size()-1;
   748         Node node = nodeFromId(n);
   749         Parent::notifier(Node()).erase(node);
   750         nodes.pop_back();
   751       }
   752     }
   753 
   754   public:
   755 
   756     ///Class to make a snapshot of the graph and to restore it later.
   757 
   758     ///Class to make a snapshot of the graph and to restore it later.
   759     ///
   760     ///The newly added nodes and edges can be removed using the
   761     ///restore() function. This is the only way for deleting nodes and/or
   762     ///edges from a SmartGraph structure.
   763     ///
   764     ///\note After a state is restored, you cannot restore a later state,
   765     ///i.e. you cannot add the removed nodes and edges again using
   766     ///another Snapshot instance.
   767     ///
   768     ///\warning The validity of the snapshot is not stored due to
   769     ///performance reasons. If you do not use the snapshot correctly,
   770     ///it can cause broken program, invalid or not restored state of
   771     ///the graph or no change.
   772     class Snapshot
   773     {
   774       SmartGraph *_graph;
   775     protected:
   776       friend class SmartGraph;
   777       unsigned int node_num;
   778       unsigned int arc_num;
   779     public:
   780       ///Default constructor.
   781 
   782       ///Default constructor.
   783       ///You have to call save() to actually make a snapshot.
   784       Snapshot() : _graph(0) {}
   785       ///Constructor that immediately makes a snapshot
   786 
   787       /// This constructor immediately makes a snapshot of the given graph.
   788       ///
   789       Snapshot(SmartGraph &gr) {
   790         gr.saveSnapshot(*this);
   791       }
   792 
   793       ///Make a snapshot.
   794 
   795       ///This function makes a snapshot of the given graph.
   796       ///It can be called more than once. In case of a repeated
   797       ///call, the previous snapshot gets lost.
   798       void save(SmartGraph &gr)
   799       {
   800         gr.saveSnapshot(*this);
   801       }
   802 
   803       ///Undo the changes until the last snapshot.
   804 
   805       ///This function undos the changes until the last snapshot
   806       ///created by save() or Snapshot(SmartGraph&).
   807       void restore()
   808       {
   809         _graph->restoreSnapshot(*this);
   810       }
   811     };
   812   };
   813 
   814 } //namespace lemon
   815 
   816 
   817 #endif //LEMON_SMART_GRAPH_H