[Lemon-commits] deba: r3338 - in lemon/trunk/lemon: . bits

Lemon SVN svn at lemon.cs.elte.hu
Fri Oct 19 17:21:08 CEST 2007


Author: deba
Date: Fri Oct 19 17:21:07 2007
New Revision: 3338

Modified:
   lemon/trunk/lemon/bits/edge_set_extender.h
   lemon/trunk/lemon/edge_set.h
   lemon/trunk/lemon/list_graph.h
   lemon/trunk/lemon/smart_graph.h

Log:
Bug fix in undirected graphs (adding loops)
Bug fix in undirected edgesets (alteration notifying)

Redesigned undirected edgesets (like the smart or ugraph)



Modified: lemon/trunk/lemon/bits/edge_set_extender.h
==============================================================================
--- lemon/trunk/lemon/bits/edge_set_extender.h	(original)
+++ lemon/trunk/lemon/bits/edge_set_extender.h	Fri Oct 19 17:21:07 2007
@@ -590,8 +590,10 @@
     UEdge addEdge(const Node& from, const Node& to) {
       UEdge uedge = Parent::addEdge(from, to);
       notifier(UEdge()).add(uedge);
-      notifier(Edge()).add(Parent::direct(uedge, true));
-      notifier(Edge()).add(Parent::direct(uedge, false));
+      std::vector<Edge> edges;
+      edges.push_back(Parent::direct(uedge, true));
+      edges.push_back(Parent::direct(uedge, false));
+      notifier(Edge()).add(edges);
       return uedge;
     }
     
@@ -602,8 +604,10 @@
     }
 
     void erase(const UEdge& uedge) {
-      notifier(Edge()).erase(Parent::direct(uedge, true));
-      notifier(Edge()).erase(Parent::direct(uedge, false));
+      std::vector<Edge> edges;
+      edges.push_back(Parent::direct(uedge, true));
+      edges.push_back(Parent::direct(uedge, false));
+      notifier(Edge()).erase(edges);
       notifier(UEdge()).erase(uedge);
       Parent::erase(uedge);
     }

Modified: lemon/trunk/lemon/edge_set.h
==============================================================================
--- lemon/trunk/lemon/edge_set.h	(original)
+++ lemon/trunk/lemon/edge_set.h	Fri Oct 19 17:21:07 2007
@@ -241,8 +241,6 @@
   /// this class. Its interface must conform to the \ref concepts::Graph
   /// "Graph" concept.
   ///
-  /// In the edge extension and removing it conforms to the 
-  /// \ref concepts::Graph "Graph" concept.
   template <typename _Graph>
   class ListEdgeSet : public EdgeSetExtender<ListEdgeSetBase<_Graph> > {
 
@@ -320,6 +318,315 @@
     
   };
 
+  template <typename _Graph>
+  class ListUEdgeSetBase {
+  public:
+
+    typedef _Graph Graph;
+    typedef typename Graph::Node Node;
+    typedef typename Graph::NodeIt NodeIt;
+
+  protected:
+
+    struct NodeT {
+      int first_out;
+      NodeT() : first_out(-1) {}
+    };
+
+    typedef DefaultMap<Graph, Node, NodeT> NodesImplBase;
+
+    NodesImplBase* nodes;
+
+    struct EdgeT {
+      Node target;
+      int prev_out, next_out;
+      EdgeT() : prev_out(-1), next_out(-1) {}
+    };
+
+    std::vector<EdgeT> edges;
+
+    int first_edge;
+    int first_free_edge;
+
+    const Graph* graph;
+
+    void initalize(const Graph& _graph, NodesImplBase& _nodes) {
+      graph = &_graph;
+      nodes = &_nodes;
+    }
+    
+  public:
+
+    class UEdge {
+      friend class ListUEdgeSetBase;
+    protected:
+
+      int id;
+      explicit UEdge(int _id) { id = _id;}
+
+    public:
+      UEdge() {}
+      UEdge (Invalid) { id = -1; }
+      bool operator==(const UEdge& edge) const {return id == edge.id;}
+      bool operator!=(const UEdge& edge) const {return id != edge.id;}
+      bool operator<(const UEdge& edge) const {return id < edge.id;}
+    };
+
+    class Edge {
+      friend class ListUEdgeSetBase;
+    protected:
+      Edge(int _id) : id(_id) {}
+      int id;
+    public:
+      operator UEdge() const { return uEdgeFromId(id / 2); }
+
+      Edge() {}
+      Edge(Invalid) : id(-1) {}
+      bool operator==(const Edge& edge) const { return id == edge.id; }
+      bool operator!=(const Edge& edge) const { return id != edge.id; }
+      bool operator<(const Edge& edge) const { return id < edge.id; }
+    };
+
+    ListUEdgeSetBase() : first_edge(-1), first_free_edge(-1) {} 
+
+    UEdge addEdge(const Node& u, const Node& v) {
+      int n;
+
+      if (first_free_edge == -1) {
+	n = edges.size();
+	edges.push_back(EdgeT());
+	edges.push_back(EdgeT());
+      } else {
+	n = first_free_edge;
+	first_free_edge = edges[n].next_out;
+      }
+      
+      edges[n].target = u;
+      edges[n | 1].target = v;
+
+      edges[n].next_out = (*nodes)[v].first_out;
+      if ((*nodes)[v].first_out != -1) {
+	edges[(*nodes)[v].first_out].prev_out = n;
+      }
+      (*nodes)[v].first_out = n;
+      edges[n].prev_out = -1;
+      
+      if ((*nodes)[u].first_out != -1) {
+	edges[(*nodes)[u].first_out].prev_out = (n | 1);
+      }
+      edges[n | 1].next_out = (*nodes)[u].first_out;
+      (*nodes)[u].first_out = (n | 1);
+      edges[n | 1].prev_out = -1;
+
+      return UEdge(n / 2);
+    }
+
+    void erase(const UEdge& edge) {
+      int n = edge.id * 2;
+      
+      if (edges[n].next_out != -1) {
+	edges[edges[n].next_out].prev_out = edges[n].prev_out;
+      } 
+
+      if (edges[n].prev_out != -1) {
+	edges[edges[n].prev_out].next_out = edges[n].next_out;
+      } else {
+	(*nodes)[edges[n | 1].target].first_out = edges[n].next_out;
+      }
+
+      if (edges[n | 1].next_out != -1) {
+	edges[edges[n | 1].next_out].prev_out = edges[n | 1].prev_out;
+      } 
+
+      if (edges[n | 1].prev_out != -1) {
+	edges[edges[n | 1].prev_out].next_out = edges[n | 1].next_out;
+      } else {
+	(*nodes)[edges[n].target].first_out = edges[n | 1].next_out;
+      }
+      
+      edges[n].next_out = first_free_edge;
+      first_free_edge = n;      
+           
+    }
+
+    void clear() {
+      Node node;
+      for (first(node); node != INVALID; next(node)) {
+        (*nodes)[node].first_out = -1;
+      }
+      edges.clear();
+      first_edge = -1;
+      first_free_edge = -1;
+    }
+
+    void first(Node& node) const {
+      graph->first(node);
+    }
+
+    void next(Node& node) const {
+      graph->next(node);
+    }
+
+    void first(Edge& edge) const {
+      Node node;
+      first(node);
+      while (node != INVALID && (*nodes)[node].first_out == -1) {
+        next(node);
+      }
+      edge.id = (node == INVALID) ? -1 : (*nodes)[node].first_out;
+    }
+
+    void next(Edge& edge) const {
+      if (edges[edge.id].next_out != -1) {
+	edge.id = edges[edge.id].next_out;
+      } else {
+	Node node = edges[edge.id ^ 1].target;
+	next(node);
+        while(node != INVALID && (*nodes)[node].first_out == -1) {
+          next(node);
+        }
+	edge.id = (node == INVALID) ? -1 : (*nodes)[node].first_out;
+      }      
+    }
+
+    void first(UEdge& uedge) const {
+      Node node;
+      first(node);
+      while (node != INVALID) {
+        uedge.id = (*nodes)[node].first_out;
+        while ((uedge.id & 1) != 1) {
+          uedge.id = edges[uedge.id].next_out;
+        }
+        if (uedge.id != -1) {
+          uedge.id /= 2;
+          return;
+        } 
+        next(node);
+      }
+      uedge.id = -1;
+    }
+
+    void next(UEdge& uedge) const {
+      Node node = edges[uedge.id * 2].target;
+      uedge.id = edges[(uedge.id * 2) | 1].next_out;
+      while ((uedge.id & 1) != 1) {
+        uedge.id = edges[uedge.id].next_out;
+      }
+      if (uedge.id != -1) {
+        uedge.id /= 2;
+        return;
+      } 
+      next(node);
+      while (node != INVALID) {
+        uedge.id = (*nodes)[node].first_out;
+        while ((uedge.id & 1) != 1) {
+          uedge.id = edges[uedge.id].next_out;
+        }
+        if (uedge.id != -1) {
+          uedge.id /= 2;
+          return;
+        } 
+	next(node);
+      }
+      uedge.id = -1;
+    }
+
+    void firstOut(Edge& edge, const Node& node) const {
+      edge.id = (*nodes)[node].first_out;
+    }
+    
+    void nextOut(Edge& edge) const {
+      edge.id = edges[edge.id].next_out;        
+    }
+
+    void firstIn(Edge& edge, const Node& node) const {
+      edge.id = (((*nodes)[node].first_out) ^ 1);
+      if (edge.id == -2) edge.id = -1;
+    }
+
+    void nextIn(Edge& edge) const {
+      edge.id = ((edges[edge.id ^ 1].next_out) ^ 1);
+      if (edge.id == -2) edge.id = -1;
+    }
+
+    void firstInc(UEdge &edge, bool& dir, const Node& node) const {
+      int de = (*nodes)[node].first_out;
+      if (de != -1 ) {
+        edge.id = de / 2;
+        dir = ((de & 1) == 1);
+      } else {
+        edge.id = -1;
+        dir = true;
+      }
+    }
+    void nextInc(UEdge &edge, bool& dir) const {
+      int de = (edges[(edge.id * 2) | (dir ? 1 : 0)].next_out);
+      if (de != -1 ) {
+        edge.id = de / 2;
+        dir = ((de & 1) == 1);
+      } else {
+        edge.id = -1;
+        dir = true;
+      }
+    }
+
+    static bool direction(Edge edge) {
+      return (edge.id & 1) == 1;
+    }
+
+    static Edge direct(UEdge uedge, bool dir) {
+      return Edge(uedge.id * 2 + (dir ? 1 : 0));
+    }
+
+    int id(const Node& node) const { return graph->id(node); }
+    static int id(Edge e) { return e.id; }
+    static int id(UEdge e) { return e.id; }
+
+    Node nodeFromId(int id) const { return graph->nodeFromId(id); }
+    static Edge edgeFromId(int id) { return Edge(id);}
+    static UEdge uEdgeFromId(int id) { return UEdge(id);}
+
+    int maxNodeId() const { return graph->maxNodeId(); };
+    int maxUEdgeId() const { return edges.size() / 2 - 1; }
+    int maxEdgeId() const { return edges.size()-1; }
+
+    Node source(Edge e) const { return edges[e.id ^ 1].target; }
+    Node target(Edge e) const { return edges[e.id].target; }
+
+    Node source(UEdge e) const { return edges[2 * e.id].target; }
+    Node target(UEdge e) const { return edges[2 * e.id + 1].target; }
+
+    typedef typename ItemSetTraits<Graph, Node>::ItemNotifier NodeNotifier;
+
+    NodeNotifier& notifier(Node) const {
+      return graph->notifier(Node());
+    } 
+
+    template <typename _Value>
+    class NodeMap : public Graph::template NodeMap<_Value> {
+    public:
+
+      typedef typename _Graph::template NodeMap<_Value> Parent;
+
+      explicit NodeMap(const ListUEdgeSetBase<Graph>& edgeset) 
+	: Parent(*edgeset.graph) {}
+
+      NodeMap(const ListUEdgeSetBase<Graph>& edgeset, const _Value& value)
+	: Parent(*edgeset.graph, value) {}
+
+      NodeMap& operator=(const NodeMap& cmap) {
+        return operator=<NodeMap>(cmap);
+      }
+
+      template <typename CMap>
+      NodeMap& operator=(const CMap& cmap) {
+        Parent::operator=(cmap);
+        return *this;
+      }
+    };
+
+  };
+
   /// \ingroup semi_adaptors
   ///
   /// \brief Graph using a node set of another graph and an
@@ -336,13 +643,11 @@
   /// In the edge extension and removing it conforms to the 
   /// \ref concepts::UGraph "UGraph" concept.
   template <typename _Graph>
-  class ListUEdgeSet 
-    : public UEdgeSetExtender<UndirGraphExtender<ListEdgeSetBase<_Graph> > > {
+  class ListUEdgeSet : public UEdgeSetExtender<ListUEdgeSetBase<_Graph> > {
 
   public:
 
-    typedef UEdgeSetExtender<UndirGraphExtender<
-      ListEdgeSetBase<_Graph> > > Parent;
+    typedef UEdgeSetExtender<ListUEdgeSetBase<_Graph> > Parent;
     
     typedef typename Parent::Node Node;
     typedef typename Parent::Edge Edge;
@@ -661,6 +966,220 @@
     
   };
 
+
+  template <typename _Graph>
+  class SmartUEdgeSetBase {
+  public:
+
+    typedef _Graph Graph;
+    typedef typename Graph::Node Node;
+    typedef typename Graph::NodeIt NodeIt;
+
+  protected:
+
+    struct NodeT {
+      int first_out;
+      NodeT() : first_out(-1) {}
+    };
+
+    typedef DefaultMap<Graph, Node, NodeT> NodesImplBase;
+
+    NodesImplBase* nodes;
+
+    struct EdgeT {
+      Node target;
+      int next_out;
+      EdgeT() {}
+    };
+
+    std::vector<EdgeT> edges;
+
+    const Graph* graph;
+
+    void initalize(const Graph& _graph, NodesImplBase& _nodes) {
+      graph = &_graph;
+      nodes = &_nodes;
+    }
+    
+  public:
+
+    class UEdge {
+      friend class SmartUEdgeSetBase;
+    protected:
+
+      int id;
+      explicit UEdge(int _id) { id = _id;}
+
+    public:
+      UEdge() {}
+      UEdge (Invalid) { id = -1; }
+      bool operator==(const UEdge& edge) const {return id == edge.id;}
+      bool operator!=(const UEdge& edge) const {return id != edge.id;}
+      bool operator<(const UEdge& edge) const {return id < edge.id;}
+    };
+
+    class Edge {
+      friend class SmartUEdgeSetBase;
+    protected:
+      Edge(int _id) : id(_id) {}
+      int id;
+    public:
+      operator UEdge() const { return uEdgeFromId(id / 2); }
+
+      Edge() {}
+      Edge(Invalid) : id(-1) {}
+      bool operator==(const Edge& edge) const { return id == edge.id; }
+      bool operator!=(const Edge& edge) const { return id != edge.id; }
+      bool operator<(const Edge& edge) const { return id < edge.id; }
+    };
+
+    SmartUEdgeSetBase() {} 
+
+    UEdge addEdge(const Node& u, const Node& v) {
+      int n = edges.size();
+      edges.push_back(EdgeT());
+      edges.push_back(EdgeT());
+      
+      edges[n].target = u;
+      edges[n | 1].target = v;
+
+      edges[n].next_out = (*nodes)[v].first_out;
+      (*nodes)[v].first_out = n;
+
+      edges[n | 1].next_out = (*nodes)[u].first_out;	
+      (*nodes)[u].first_out = (n | 1);
+
+      return UEdge(n / 2);
+    }
+
+    void clear() {
+      Node node;
+      for (first(node); node != INVALID; next(node)) {
+        (*nodes)[node].first_out = -1;
+      }
+      edges.clear();
+    }
+
+    void first(Node& node) const {
+      graph->first(node);
+    }
+
+    void next(Node& node) const {
+      graph->next(node);
+    }
+
+    void first(Edge& edge) const { 
+      edge.id = edges.size() - 1;
+    }
+
+    void next(Edge& edge) const {
+      --edge.id;
+    }
+
+    void first(UEdge& edge) const { 
+      edge.id = edges.size() / 2 - 1;
+    }
+
+    void next(UEdge& edge) const {
+      --edge.id;
+    }
+
+    void firstOut(Edge& edge, const Node& node) const {
+      edge.id = (*nodes)[node].first_out;    
+    }
+    
+    void nextOut(Edge& edge) const {
+      edge.id = edges[edge.id].next_out;        
+    }
+
+    void firstIn(Edge& edge, const Node& node) const {
+      edge.id = (((*nodes)[node].first_out) ^ 1);
+      if (edge.id == -2) edge.id = -1;
+    }
+
+    void nextIn(Edge& edge) const {
+      edge.id = ((edges[edge.id ^ 1].next_out) ^ 1);
+      if (edge.id == -2) edge.id = -1;
+    }
+
+    void firstInc(UEdge &edge, bool& dir, const Node& node) const {
+      int de = (*nodes)[node].first_out;
+      if (de != -1 ) {
+        edge.id = de / 2;
+        dir = ((de & 1) == 1);
+      } else {
+        edge.id = -1;
+        dir = true;
+      }
+    }
+    void nextInc(UEdge &edge, bool& dir) const {
+      int de = (edges[(edge.id * 2) | (dir ? 1 : 0)].next_out);
+      if (de != -1 ) {
+        edge.id = de / 2;
+        dir = ((de & 1) == 1);
+      } else {
+        edge.id = -1;
+        dir = true;
+      }
+    }
+
+    static bool direction(Edge edge) {
+      return (edge.id & 1) == 1;
+    }
+
+    static Edge direct(UEdge uedge, bool dir) {
+      return Edge(uedge.id * 2 + (dir ? 1 : 0));
+    }
+
+    int id(Node node) const { return graph->id(node); }
+    static int id(Edge edge) { return edge.id; }
+    static int id(UEdge edge) { return edge.id; }
+
+    Node nodeFromId(int id) const { return graph->nodeFromId(id); }
+    static Edge edgeFromId(int id) { return Edge(id); }
+    static UEdge uEdgeFromId(int id) { return UEdge(id);}
+
+    int maxNodeId() const { return graph->maxNodeId(); };
+    int maxEdgeId() const { return edges.size() - 1; }
+    int maxUEdgeId() const { return edges.size() / 2 - 1; }
+
+    Node source(Edge e) const { return edges[e.id ^ 1].target; }
+    Node target(Edge e) const { return edges[e.id].target; }
+
+    Node source(UEdge e) const { return edges[2 * e.id].target; }
+    Node target(UEdge e) const { return edges[2 * e.id + 1].target; }
+
+    typedef typename ItemSetTraits<Graph, Node>::ItemNotifier NodeNotifier;
+
+    NodeNotifier& notifier(Node) const {
+      return graph->notifier(Node());
+    } 
+
+    template <typename _Value>
+    class NodeMap : public Graph::template NodeMap<_Value> {
+    public:
+
+      typedef typename _Graph::template NodeMap<_Value> Parent;
+
+      explicit NodeMap(const SmartUEdgeSetBase<Graph>& edgeset) 
+	: Parent(*edgeset.graph) { }
+
+      NodeMap(const SmartUEdgeSetBase<Graph>& edgeset, const _Value& value)
+	: Parent(*edgeset.graph, value) { }
+
+      NodeMap& operator=(const NodeMap& cmap) {
+        return operator=<NodeMap>(cmap);
+      }
+
+      template <typename CMap>
+      NodeMap& operator=(const CMap& cmap) {
+        Parent::operator=(cmap);
+        return *this;
+      }
+    };
+
+  };
+
   /// \ingroup semi_adaptors
   ///
   /// \brief Graph using a node set of another graph and an
@@ -677,13 +1196,11 @@
   /// In the edge extension and removing it conforms to the 
   /// \ref concepts::UGraph "UGraph" concept.
   template <typename _Graph>
-  class SmartUEdgeSet 
-    : public UEdgeSetExtender<UndirGraphExtender<SmartEdgeSetBase<_Graph> > > {
+  class SmartUEdgeSet : public UEdgeSetExtender<SmartUEdgeSetBase<_Graph> > {
 
   public:
 
-    typedef UEdgeSetExtender<UndirGraphExtender<
-      SmartEdgeSetBase<_Graph> > > Parent;
+    typedef UEdgeSetExtender<SmartUEdgeSetBase<_Graph> > Parent;
     
     typedef typename Parent::Node Node;
     typedef typename Parent::Edge Edge;

Modified: lemon/trunk/lemon/list_graph.h
==============================================================================
--- lemon/trunk/lemon/list_graph.h	(original)
+++ lemon/trunk/lemon/list_graph.h	Fri Oct 19 17:21:07 2007
@@ -977,17 +977,17 @@
       edges[n | 1].target = v.id;
 
       edges[n].next_out = nodes[v.id].first_out;
-      edges[n | 1].next_out = nodes[u.id].first_out;
       if (nodes[v.id].first_out != -1) {
 	edges[nodes[v.id].first_out].prev_out = n;
-      }
+      }      
+      edges[n].prev_out = -1;
+      nodes[v.id].first_out = n;
+      
+      edges[n | 1].next_out = nodes[u.id].first_out;
       if (nodes[u.id].first_out != -1) {
 	edges[nodes[u.id].first_out].prev_out = (n | 1);
       }
-      
-      edges[n].prev_out = edges[n | 1].prev_out = -1;
-	
-      nodes[v.id].first_out = n;
+      edges[n | 1].prev_out = -1;      
       nodes[u.id].first_out = (n | 1);
 
       return UEdge(n / 2);

Modified: lemon/trunk/lemon/smart_graph.h
==============================================================================
--- lemon/trunk/lemon/smart_graph.h	(original)
+++ lemon/trunk/lemon/smart_graph.h	Fri Oct 19 17:21:07 2007
@@ -185,10 +185,10 @@
 
   typedef GraphExtender<SmartGraphBase> ExtendedSmartGraphBase;
 
-  /// \ingroup graphs
-
-  ///A smart graph class.
-
+  ///\ingroup graphs
+  ///
+  ///\brief A smart graph class.
+  ///
   ///This is a simple and fast graph implementation.
   ///It is also quite memory efficient, but at the price
   ///that <b> it does support only limited (only stack-like)
@@ -571,9 +571,9 @@
       edges[n | 1].target = v.id;
 
       edges[n].next_out = nodes[v.id].first_out;
-      edges[n | 1].next_out = nodes[u.id].first_out;
-	
       nodes[v.id].first_out = n;
+
+      edges[n | 1].next_out = nodes[u.id].first_out;	
       nodes[u.id].first_out = (n | 1);
 
       return UEdge(n / 2);



More information about the Lemon-commits mailing list