[Lemon-commits] [lemon_svn] deba: r2914 - hugo/trunk/lemon

Lemon SVN svn at lemon.cs.elte.hu
Mon Nov 6 21:51:13 CET 2006


Author: deba
Date: Mon Sep  4 13:08:32 2006
New Revision: 2914

Modified:
   hugo/trunk/lemon/list_graph.h

Log:
Bug fix in ListBpUGraph

Snapshot improvments



Modified: hugo/trunk/lemon/list_graph.h
==============================================================================
--- hugo/trunk/lemon/list_graph.h	(original)
+++ hugo/trunk/lemon/list_graph.h	Mon Sep  4 13:08:32 2006
@@ -502,18 +502,9 @@
     /// The newly added nodes and edges can be removed using the
     /// restore() function.
     ///
-    /// \warning Edge and node deletions cannot be restored.
+    /// \warning Edge and node deletions cannot be restored. This
+    /// events invalidate the snapshot. 
     class Snapshot {
-    public:
-      
-      class UnsupportedOperation : public LogicError {
-      public:
-	virtual const char* what() const throw() {
-	  return "lemon::ListGraph::Snapshot::UnsupportedOperation";
-	}
-      };
-            
-
     protected:
 
       typedef Parent::NodeNotifier NodeNotifier;
@@ -543,7 +534,7 @@
         }
         virtual void erase(const std::vector<Node>& nodes) {
           for (int i = 0; i < (int)nodes.size(); ++i) {
-            if (!snapshot.eraseNode(nodes[i])) break;
+            snapshot.eraseNode(nodes[i]);
           }
         }
         virtual void build() {
@@ -561,7 +552,7 @@
           NodeNotifier* notifier = getNotifier();
           Node node;
           for (notifier->first(node); node != INVALID; notifier->next(node)) {
-            if (!snapshot.eraseNode(node)) break;
+            snapshot.eraseNode(node);
           }
         }
 
@@ -593,7 +584,7 @@
         }
         virtual void erase(const std::vector<Edge>& edges) {
           for (int i = 0; i < (int)edges.size(); ++i) {
-            if (!snapshot.eraseEdge(edges[i])) break;
+            snapshot.eraseEdge(edges[i]);
           }
         }
         virtual void build() {
@@ -611,7 +602,7 @@
           EdgeNotifier* notifier = getNotifier();
           Edge edge;
           for (notifier->first(edge); edge != INVALID; notifier->next(edge)) {
-            if (!snapshot.eraseEdge(edge)) break;
+            snapshot.eraseEdge(edge);
           }
         }
 
@@ -630,30 +621,30 @@
       void addNode(const Node& node) {
         added_nodes.push_front(node);        
       }
-      bool eraseNode(const Node& node) {
+      void eraseNode(const Node& node) {
         std::list<Node>::iterator it = 
           std::find(added_nodes.begin(), added_nodes.end(), node);
         if (it == added_nodes.end()) {
           clear();
-          return false;
+          edge_observer_proxy.detach();
+          throw NodeNotifier::ImmediateDetach();
         } else {
           added_nodes.erase(it);
-          return true;
         }
       }
 
       void addEdge(const Edge& edge) {
         added_edges.push_front(edge);        
       }
-      bool eraseEdge(const Edge& edge) {
+      void eraseEdge(const Edge& edge) {
         std::list<Edge>::iterator it = 
           std::find(added_edges.begin(), added_edges.end(), edge);
         if (it == added_edges.end()) {
           clear();
-          return false;
+          node_observer_proxy.detach(); 
+          throw EdgeNotifier::ImmediateDetach();
         } else {
           added_edges.erase(it);
-          return true;
         }        
       }
 
@@ -668,8 +659,11 @@
 	edge_observer_proxy.detach();
       }
 
+      bool attached() const {
+        return node_observer_proxy.attached();
+      }
+
       void clear() {
-        detach();
         added_nodes.clear();
         added_edges.clear();        
       }
@@ -702,7 +696,10 @@
       /// call, the previous snapshot gets lost.
       /// \param _graph The graph we make the snapshot of.
       void save(ListGraph &_graph) {
-        clear();
+        if (attached()) {
+          detach();
+          clear();
+        }
         attach(_graph);
       }
       
@@ -711,21 +708,22 @@
       /// Undo the changes until the last snapshot created by save().
       void restore() {
 	detach();
-	while(!added_edges.empty()) {
-	  graph->erase(added_edges.front());
-	  added_edges.pop_front();
+	for(std::list<Edge>::iterator it = added_edges.begin(); 
+            it != added_edges.end(); ++it) {
+	  graph->erase(*it);
 	}
- 	while(!added_nodes.empty()) {
-	  graph->erase(added_nodes.front());
-	  added_nodes.pop_front();
+	for(std::list<Node>::iterator it = added_nodes.begin(); 
+            it != added_nodes.end(); ++it) {
+	  graph->erase(*it);
 	}
+        clear();
       }
 
       /// \brief Gives back true when the snapshot is valid.
       ///
       /// Gives back true when the snapshot is valid.
       bool valid() const {
-        return node_observer_proxy.attached();
+        return attached();
       }
     };
     
@@ -859,6 +857,241 @@
       }
       erase(b);
     }
+
+
+    /// \brief Class to make a snapshot of the graph and restore
+    /// to it later.
+    ///
+    /// Class to make a snapshot of the graph and to restore it
+    /// later.
+    ///
+    /// The newly added nodes and undirected edges can be removed
+    /// using the restore() function.
+    ///
+    /// \warning Edge and node deletions cannot be restored. This
+    /// events invalidate the snapshot. 
+    class Snapshot {
+    protected:
+
+      typedef Parent::NodeNotifier NodeNotifier;
+
+      class NodeObserverProxy : public NodeNotifier::ObserverBase {
+      public:
+
+        NodeObserverProxy(Snapshot& _snapshot)
+          : snapshot(_snapshot) {}
+
+        using NodeNotifier::ObserverBase::attach;
+        using NodeNotifier::ObserverBase::detach;
+        using NodeNotifier::ObserverBase::attached;
+        
+      protected:
+        
+        virtual void add(const Node& node) {
+          snapshot.addNode(node);
+        }
+        virtual void add(const std::vector<Node>& nodes) {
+          for (int i = nodes.size() - 1; i >= 0; ++i) {
+            snapshot.addNode(nodes[i]);
+          }
+        }
+        virtual void erase(const Node& node) {
+          snapshot.eraseNode(node);
+        }
+        virtual void erase(const std::vector<Node>& nodes) {
+          for (int i = 0; i < (int)nodes.size(); ++i) {
+            snapshot.eraseNode(nodes[i]);
+          }
+        }
+        virtual void build() {
+          NodeNotifier* notifier = getNotifier();
+          Node node;
+          std::vector<Node> nodes;
+          for (notifier->first(node); node != INVALID; notifier->next(node)) {
+            nodes.push_back(node);
+          }
+          for (int i = nodes.size() - 1; i >= 0; --i) {
+            snapshot.addNode(nodes[i]);
+          }
+        }
+        virtual void clear() {
+          NodeNotifier* notifier = getNotifier();
+          Node node;
+          for (notifier->first(node); node != INVALID; notifier->next(node)) {
+            snapshot.eraseNode(node);
+          }
+        }
+
+        Snapshot& snapshot;
+      };
+
+      class UEdgeObserverProxy : public UEdgeNotifier::ObserverBase {
+      public:
+
+        UEdgeObserverProxy(Snapshot& _snapshot)
+          : snapshot(_snapshot) {}
+
+        using UEdgeNotifier::ObserverBase::attach;
+        using UEdgeNotifier::ObserverBase::detach;
+        using UEdgeNotifier::ObserverBase::attached;
+        
+      protected:
+
+        virtual void add(const UEdge& edge) {
+          snapshot.addUEdge(edge);
+        }
+        virtual void add(const std::vector<UEdge>& edges) {
+          for (int i = edges.size() - 1; i >= 0; ++i) {
+            snapshot.addUEdge(edges[i]);
+          }
+        }
+        virtual void erase(const UEdge& edge) {
+          snapshot.eraseUEdge(edge);
+        }
+        virtual void erase(const std::vector<UEdge>& edges) {
+          for (int i = 0; i < (int)edges.size(); ++i) {
+            snapshot.eraseUEdge(edges[i]);
+          }
+        }
+        virtual void build() {
+          UEdgeNotifier* notifier = getNotifier();
+          UEdge edge;
+          std::vector<UEdge> edges;
+          for (notifier->first(edge); edge != INVALID; notifier->next(edge)) {
+            edges.push_back(edge);
+          }
+          for (int i = edges.size() - 1; i >= 0; --i) {
+            snapshot.addUEdge(edges[i]);
+          }
+        }
+        virtual void clear() {
+          UEdgeNotifier* notifier = getNotifier();
+          UEdge edge;
+          for (notifier->first(edge); edge != INVALID; notifier->next(edge)) {
+            snapshot.eraseUEdge(edge);
+          }
+        }
+
+        Snapshot& snapshot;
+      };
+      
+      ListUGraph *graph;
+
+      NodeObserverProxy node_observer_proxy;
+      UEdgeObserverProxy edge_observer_proxy;
+
+      std::list<Node> added_nodes;
+      std::list<UEdge> added_edges;
+
+
+      void addNode(const Node& node) {
+        added_nodes.push_front(node);        
+      }
+      void eraseNode(const Node& node) {
+        std::list<Node>::iterator it = 
+          std::find(added_nodes.begin(), added_nodes.end(), node);
+        if (it == added_nodes.end()) {
+          clear();
+          edge_observer_proxy.detach();
+          throw NodeNotifier::ImmediateDetach();
+        } else {
+          added_nodes.erase(it);
+        }
+      }
+
+      void addUEdge(const UEdge& edge) {
+        added_edges.push_front(edge);        
+      }
+      void eraseUEdge(const UEdge& edge) {
+        std::list<UEdge>::iterator it = 
+          std::find(added_edges.begin(), added_edges.end(), edge);
+        if (it == added_edges.end()) {
+          clear();
+          node_observer_proxy.detach();
+          throw UEdgeNotifier::ImmediateDetach();
+        } else {
+          added_edges.erase(it);
+        }        
+      }
+
+      void attach(ListUGraph &_graph) {
+	graph = &_graph;
+	node_observer_proxy.attach(graph->getNotifier(Node()));
+        edge_observer_proxy.attach(graph->getNotifier(UEdge()));
+      }
+            
+      void detach() {
+	node_observer_proxy.detach();
+	edge_observer_proxy.detach();
+      }
+
+      bool attached() const {
+        return node_observer_proxy.attached();
+      }
+
+      void clear() {
+        added_nodes.clear();
+        added_edges.clear();        
+      }
+
+    public:
+
+      /// \brief Default constructor.
+      ///
+      /// Default constructor.
+      /// To actually make a snapshot you must call save().
+      Snapshot() 
+        : graph(0), node_observer_proxy(*this), 
+          edge_observer_proxy(*this) {}
+      
+      /// \brief Constructor that immediately makes a snapshot.
+      ///      
+      /// This constructor immediately makes a snapshot of the graph.
+      /// \param _graph The graph we make a snapshot of.
+      Snapshot(ListUGraph &_graph) 
+        : node_observer_proxy(*this), 
+          edge_observer_proxy(*this) {
+	attach(_graph);
+      }
+      
+      /// \brief Make a snapshot.
+      ///
+      /// Make a snapshot of the graph.
+      ///
+      /// This function can be called more than once. In case of a repeated
+      /// call, the previous snapshot gets lost.
+      /// \param _graph The graph we make the snapshot of.
+      void save(ListUGraph &_graph) {
+        if (attached()) {
+          detach();
+          clear();
+        }
+        attach(_graph);
+      }
+      
+      /// \brief Undo the changes until the last snapshot.
+      // 
+      /// Undo the changes until the last snapshot created by save().
+      void restore() {
+	detach();
+	for(std::list<UEdge>::iterator it = added_edges.begin(); 
+            it != added_edges.end(); ++it) {
+	  graph->erase(*it);
+	}
+	for(std::list<Node>::iterator it = added_nodes.begin(); 
+            it != added_nodes.end(); ++it) {
+	  graph->erase(*it);
+	}
+        clear();
+      }
+
+      /// \brief Gives back true when the snapshot is valid.
+      ///
+      /// Gives back true when the snapshot is valid.
+      bool valid() const {
+        return attached();
+      }
+    };
   };
 
 
@@ -1105,6 +1338,7 @@
       } else {
         bNodes[bNodeId].next = -1;
       }
+      bNodes[bNodeId].prev = -1;
       first_bnode = bNodeId;
       bNodes[bNodeId].first_edge = -1;
       return Node((bNodeId << 1) + 1);
@@ -1148,7 +1382,8 @@
         if (aNodes[aNodeId].prev != -1) {
           aNodes[aNodes[aNodeId].prev >> 1].next = aNodes[aNodeId].next;
         } else {
-          first_anode = aNodes[aNodeId].next >> 1;
+          first_anode = 
+            aNodes[aNodeId].next != -1 ? aNodes[aNodeId].next >> 1 : -1;
         }
         if (aNodes[aNodeId].next != -1) {
           aNodes[aNodes[aNodeId].next >> 1].prev = aNodes[aNodeId].prev;
@@ -1160,7 +1395,8 @@
         if (bNodes[bNodeId].prev != -1) {
           bNodes[bNodes[bNodeId].prev >> 1].next = bNodes[bNodeId].next;
         } else {
-          first_bnode = bNodes[bNodeId].next >> 1;
+          first_bnode = 
+            bNodes[bNodeId].next != -1 ? bNodes[bNodeId].next >> 1 : -1;
         }
         if (bNodes[bNodeId].next != -1) {
           bNodes[bNodes[bNodeId].next >> 1].prev = bNodes[bNodeId].prev;
@@ -1396,6 +1632,239 @@
       erase(b);
     }
 
+    /// \brief Class to make a snapshot of the graph and restore
+    /// to it later.
+    ///
+    /// Class to make a snapshot of the graph and to restore it
+    /// later.
+    ///
+    /// The newly added nodes and undirected edges can be removed
+    /// using the restore() function.
+    ///
+    /// \warning Edge and node deletions cannot be restored. This
+    /// events invalidate the snapshot. 
+    class Snapshot {
+    protected:
+
+      typedef Parent::NodeNotifier NodeNotifier;
+
+      class NodeObserverProxy : public NodeNotifier::ObserverBase {
+      public:
+
+        NodeObserverProxy(Snapshot& _snapshot)
+          : snapshot(_snapshot) {}
+
+        using NodeNotifier::ObserverBase::attach;
+        using NodeNotifier::ObserverBase::detach;
+        using NodeNotifier::ObserverBase::attached;
+        
+      protected:
+        
+        virtual void add(const Node& node) {
+          snapshot.addNode(node);
+        }
+        virtual void add(const std::vector<Node>& nodes) {
+          for (int i = nodes.size() - 1; i >= 0; ++i) {
+            snapshot.addNode(nodes[i]);
+          }
+        }
+        virtual void erase(const Node& node) {
+          snapshot.eraseNode(node);
+        }
+        virtual void erase(const std::vector<Node>& nodes) {
+          for (int i = 0; i < (int)nodes.size(); ++i) {
+            snapshot.eraseNode(nodes[i]);
+          }
+        }
+        virtual void build() {
+          NodeNotifier* notifier = getNotifier();
+          Node node;
+          std::vector<Node> nodes;
+          for (notifier->first(node); node != INVALID; notifier->next(node)) {
+            nodes.push_back(node);
+          }
+          for (int i = nodes.size() - 1; i >= 0; --i) {
+            snapshot.addNode(nodes[i]);
+          }
+        }
+        virtual void clear() {
+          NodeNotifier* notifier = getNotifier();
+          Node node;
+          for (notifier->first(node); node != INVALID; notifier->next(node)) {
+            snapshot.eraseNode(node);
+          }
+        }
+
+        Snapshot& snapshot;
+      };
+
+      class UEdgeObserverProxy : public UEdgeNotifier::ObserverBase {
+      public:
+
+        UEdgeObserverProxy(Snapshot& _snapshot)
+          : snapshot(_snapshot) {}
+
+        using UEdgeNotifier::ObserverBase::attach;
+        using UEdgeNotifier::ObserverBase::detach;
+        using UEdgeNotifier::ObserverBase::attached;
+        
+      protected:
+
+        virtual void add(const UEdge& edge) {
+          snapshot.addUEdge(edge);
+        }
+        virtual void add(const std::vector<UEdge>& edges) {
+          for (int i = edges.size() - 1; i >= 0; ++i) {
+            snapshot.addUEdge(edges[i]);
+          }
+        }
+        virtual void erase(const UEdge& edge) {
+          snapshot.eraseUEdge(edge);
+        }
+        virtual void erase(const std::vector<UEdge>& edges) {
+          for (int i = 0; i < (int)edges.size(); ++i) {
+            snapshot.eraseUEdge(edges[i]);
+          }
+        }
+        virtual void build() {
+          UEdgeNotifier* notifier = getNotifier();
+          UEdge edge;
+          std::vector<UEdge> edges;
+          for (notifier->first(edge); edge != INVALID; notifier->next(edge)) {
+            edges.push_back(edge);
+          }
+          for (int i = edges.size() - 1; i >= 0; --i) {
+            snapshot.addUEdge(edges[i]);
+          }
+        }
+        virtual void clear() {
+          UEdgeNotifier* notifier = getNotifier();
+          UEdge edge;
+          for (notifier->first(edge); edge != INVALID; notifier->next(edge)) {
+            snapshot.eraseUEdge(edge);
+          }
+        }
+
+        Snapshot& snapshot;
+      };
+      
+      ListBpUGraph *graph;
+
+      NodeObserverProxy node_observer_proxy;
+      UEdgeObserverProxy edge_observer_proxy;
+
+      std::list<Node> added_nodes;
+      std::list<UEdge> added_edges;
+
+
+      void addNode(const Node& node) {
+        added_nodes.push_front(node);        
+      }
+      void eraseNode(const Node& node) {
+        std::list<Node>::iterator it = 
+          std::find(added_nodes.begin(), added_nodes.end(), node);
+        if (it == added_nodes.end()) {
+          clear();
+          edge_observer_proxy.detach();
+          throw NodeNotifier::ImmediateDetach();
+        } else {
+          added_nodes.erase(it);
+        }
+      }
+
+      void addUEdge(const UEdge& edge) {
+        added_edges.push_front(edge);        
+      }
+      void eraseUEdge(const UEdge& edge) {
+        std::list<UEdge>::iterator it = 
+          std::find(added_edges.begin(), added_edges.end(), edge);
+        if (it == added_edges.end()) {
+          clear();
+          node_observer_proxy.detach();
+          throw UEdgeNotifier::ImmediateDetach();
+        } else {
+          added_edges.erase(it);
+        }        
+      }
+
+      void attach(ListBpUGraph &_graph) {
+	graph = &_graph;
+	node_observer_proxy.attach(graph->getNotifier(Node()));
+        edge_observer_proxy.attach(graph->getNotifier(UEdge()));
+      }
+            
+      void detach() {
+	node_observer_proxy.detach();
+	edge_observer_proxy.detach();
+      }
+
+      bool attached() const {
+        return node_observer_proxy.attached();
+      }
+
+      void clear() {
+        added_nodes.clear();
+        added_edges.clear();        
+      }
+
+    public:
+
+      /// \brief Default constructor.
+      ///
+      /// Default constructor.
+      /// To actually make a snapshot you must call save().
+      Snapshot() 
+        : graph(0), node_observer_proxy(*this), 
+          edge_observer_proxy(*this) {}
+      
+      /// \brief Constructor that immediately makes a snapshot.
+      ///      
+      /// This constructor immediately makes a snapshot of the graph.
+      /// \param _graph The graph we make a snapshot of.
+      Snapshot(ListBpUGraph &_graph) 
+        : node_observer_proxy(*this), 
+          edge_observer_proxy(*this) {
+	attach(_graph);
+      }
+      
+      /// \brief Make a snapshot.
+      ///
+      /// Make a snapshot of the graph.
+      ///
+      /// This function can be called more than once. In case of a repeated
+      /// call, the previous snapshot gets lost.
+      /// \param _graph The graph we make the snapshot of.
+      void save(ListBpUGraph &_graph) {
+        if (attached()) {
+          detach();
+          clear();
+        }
+        attach(_graph);
+      }
+      
+      /// \brief Undo the changes until the last snapshot.
+      // 
+      /// Undo the changes until the last snapshot created by save().
+      void restore() {
+	detach();
+	for(std::list<UEdge>::iterator it = added_edges.begin(); 
+            it != added_edges.end(); ++it) {
+	  graph->erase(*it);
+	}
+	for(std::list<Node>::iterator it = added_nodes.begin(); 
+            it != added_nodes.end(); ++it) {
+	  graph->erase(*it);
+	}
+        clear();
+      }
+
+      /// \brief Gives back true when the snapshot is valid.
+      ///
+      /// Gives back true when the snapshot is valid.
+      bool valid() const {
+        return attached();
+      }
+    };
   };
 
   



More information about the Lemon-commits mailing list