src/lemon/smart_graph.h
author klao
Wed, 10 Nov 2004 21:42:28 +0000
changeset 978 175cf8c3a994
parent 974 785062a83f8e
child 980 0f1044b7a3af
permissions -rw-r--r--
"make check" pass under gcc-3.4.3
     1 /* -*- C++ -*-
     2  * src/lemon/smart_graph.h - Part of LEMON, a generic C++ optimization library
     3  *
     4  * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     5  * (Egervary Combinatorial Optimization Research Group, EGRES).
     6  *
     7  * Permission to use, modify and distribute this software is granted
     8  * provided that this copyright notice appears in all copies. For
     9  * precise terms see the accompanying LICENSE file.
    10  *
    11  * This software is provided "AS IS" with no warranty of any kind,
    12  * express or implied, and with no claim as to its suitability for any
    13  * purpose.
    14  *
    15  */
    16 
    17 #ifndef LEMON_SMART_GRAPH_H
    18 #define LEMON_SMART_GRAPH_H
    19 
    20 ///\ingroup graphs
    21 ///\file
    22 ///\brief SmartGraph and SymSmartGraph classes.
    23 
    24 #include <vector>
    25 
    26 #include <lemon/invalid.h>
    27 
    28 #include <lemon/clearable_graph_extender.h>
    29 #include <lemon/extendable_graph_extender.h>
    30 #include <lemon/idmappable_graph_extender.h>
    31 #include <lemon/iterable_graph_extender.h>
    32 #include <lemon/alteration_observer_registry.h>
    33 #include <lemon/default_map.h>
    34 
    35 #include <lemon/utility.h>
    36 
    37 namespace lemon {
    38 
    39   /// \addtogroup graphs
    40   /// @{
    41 
    42   class SmartGraph;
    43   ///Base of SmartGraph
    44 
    45   ///Base of SmartGraph
    46   ///
    47   class SmartGraphBase {
    48 
    49     friend class SmatGraph;
    50 
    51   protected:
    52     struct NodeT 
    53     {
    54       int first_in,first_out;      
    55       NodeT() : first_in(-1), first_out(-1) {}
    56     };
    57     struct EdgeT 
    58     {
    59       int head, tail, next_in, next_out;      
    60       //FIXME: is this necessary?
    61       EdgeT() : next_in(-1), next_out(-1) {}  
    62     };
    63 
    64     std::vector<NodeT> nodes;
    65 
    66     std::vector<EdgeT> edges;
    67     
    68     
    69   public:
    70 
    71     typedef SmartGraphBase Graph;
    72 
    73     class Node;
    74     class Edge;
    75 
    76     
    77   public:
    78 
    79     SmartGraphBase() : nodes(), edges() { }
    80     SmartGraphBase(const SmartGraphBase &_g) : nodes(_g.nodes), edges(_g.edges) { }
    81     
    82     typedef True NodeNumTag;
    83     typedef True EdgeNumTag;
    84 
    85     ///Number of nodes.
    86     int nodeNum() const { return nodes.size(); }
    87     ///Number of edges.
    88     int edgeNum() const { return edges.size(); }
    89 
    90     /// Maximum node ID.
    91     
    92     /// Maximum node ID.
    93     ///\sa id(Node)
    94     int maxNodeId() const { return nodes.size()-1; }
    95     /// Maximum edge ID.
    96     
    97     /// Maximum edge ID.
    98     ///\sa id(Edge)
    99     int maxEdgeId() const { return edges.size()-1; }
   100 
   101     Node tail(Edge e) const { return edges[e.n].tail; }
   102     Node head(Edge e) const { return edges[e.n].head; }
   103 
   104     /// Node ID.
   105     
   106     /// The ID of a valid Node is a nonnegative integer not greater than
   107     /// \ref maxNodeId(). The range of the ID's is not surely continuous
   108     /// and the greatest node ID can be actually less then \ref maxNodeId().
   109     ///
   110     /// The ID of the \ref INVALID node is -1.
   111     ///\return The ID of the node \c v. 
   112     static int id(Node v) { return v.n; }
   113     /// Edge ID.
   114     
   115     /// The ID of a valid Edge is a nonnegative integer not greater than
   116     /// \ref maxEdgeId(). The range of the ID's is not surely continuous
   117     /// and the greatest edge ID can be actually less then \ref maxEdgeId().
   118     ///
   119     /// The ID of the \ref INVALID edge is -1.
   120     ///\return The ID of the edge \c e. 
   121     static int id(Edge e) { return e.n; }
   122 
   123     Node addNode() {
   124       Node n; n.n=nodes.size();
   125       nodes.push_back(NodeT()); //FIXME: Hmmm...
   126       return n;
   127     }
   128     
   129     Edge addEdge(Node u, Node v) {
   130       Edge e; e.n=edges.size(); edges.push_back(EdgeT()); //FIXME: Hmmm...
   131       edges[e.n].tail=u.n; edges[e.n].head=v.n;
   132       edges[e.n].next_out=nodes[u.n].first_out;
   133       edges[e.n].next_in=nodes[v.n].first_in;
   134       nodes[u.n].first_out=nodes[v.n].first_in=e.n;
   135 
   136       return e;
   137     }
   138 
   139     void clear() {
   140       edges.clear();
   141       nodes.clear();
   142     }
   143 
   144 
   145     class Node {
   146       friend class SmartGraphBase;
   147       friend class SmartGraph;
   148 
   149     protected:
   150       int n;
   151       ///\todo It should be removed (or at least define a setToId() instead).
   152       ///
   153       Node(int nn) {n=nn;}
   154     public:
   155       Node() {}
   156       Node (Invalid) { n=-1; }
   157       bool operator==(const Node i) const {return n==i.n;}
   158       bool operator!=(const Node i) const {return n!=i.n;}
   159       bool operator<(const Node i) const {return n<i.n;}
   160     };
   161     
   162 
   163     class Edge {
   164       friend class SmartGraphBase;
   165       friend class SmartGraph;
   166 
   167     protected:
   168       int n;
   169       ///\todo It should be removed (or at least define a setToId() instead).
   170       ///
   171       Edge(int nn) {n=nn;}
   172     public:
   173       Edge() { }
   174       Edge (Invalid) { n=-1; }
   175       bool operator==(const Edge i) const {return n==i.n;}
   176       bool operator!=(const Edge i) const {return n!=i.n;}
   177       bool operator<(const Edge i) const {return n<i.n;}
   178     };
   179 
   180     void first(Node& node) const {
   181       node.n = nodes.size() - 1;
   182     }
   183 
   184     static void next(Node& node) {
   185       --node.n;
   186     }
   187 
   188     void first(Edge& edge) const {
   189       edge.n = edges.size() - 1;
   190     }
   191 
   192     static void next(Edge& edge) {
   193       --edge.n;
   194     }
   195 
   196     void firstOut(Edge& edge, const Node& node) const {
   197       edge.n = nodes[node.n].first_out;
   198     }
   199 
   200     void nextOut(Edge& edge) const {
   201       edge.n = edges[edge.n].next_out;
   202     }
   203 
   204     void firstIn(Edge& edge, const Node& node) const {
   205       edge.n = nodes[node.n].first_in;
   206     }
   207     
   208     void nextIn(Edge& edge) const {
   209       edge.n = edges[edge.n].next_in;
   210     }
   211 
   212     Edge _findEdge(Node u,Node v, Edge prev = INVALID) 
   213     {
   214       int e = (prev.n==-1)? nodes[u.n].first_out : edges[prev.n].next_out;
   215       while(e!=-1 && edges[e].tail!=v.n) e = edges[e].next_out;
   216       prev.n=e;
   217       return prev;
   218     }
   219 
   220   };
   221 
   222   typedef AlterableGraphExtender<SmartGraphBase> AlterableSmartGraphBase;
   223   typedef IterableGraphExtender<AlterableSmartGraphBase> IterableSmartGraphBase;
   224   typedef IdMappableGraphExtender<IterableSmartGraphBase> IdMappableSmartGraphBase;
   225   typedef DefaultMappableGraphExtender<IdMappableSmartGraphBase> MappableSmartGraphBase;
   226   typedef ExtendableGraphExtender<MappableSmartGraphBase> ExtendableSmartGraphBase;
   227   typedef ClearableGraphExtender<ExtendableSmartGraphBase> ClearableSmartGraphBase;
   228 
   229   ///A smart graph class.
   230 
   231   ///This is a simple and fast graph implementation.
   232   ///It is also quite memory efficient, but at the price
   233   ///that <b> it does support only limited (only stack-like)
   234   ///node and edge deletions</b>.
   235   ///It conforms to 
   236   ///the \ref concept::ExtendableGraph "ExtendableGraph" concept.
   237   ///\sa concept::ExtendableGraph.
   238   ///
   239   ///\todo Some member functions could be \c static.
   240   ///
   241   ///\author Alpar Juttner
   242   class SmartGraph :public ClearableSmartGraphBase {
   243   public:
   244     /// Finds an edge between two nodes.
   245     
   246     /// Finds an edge from node \c u to node \c v.
   247     ///
   248     /// If \c prev is \ref INVALID (this is the default value), then
   249     /// it finds the first edge from \c u to \c v. Otherwise it looks for
   250     /// the next edge from \c u to \c v after \c prev.
   251     /// \return The found edge or \ref INVALID if there is no such an edge.
   252     ///
   253     /// Thus you can iterate through each edge from \c u to \c v as it follows.
   254     /// \code
   255     /// for(Edge e=G.findEdge(u,v);e!=INVALID;e=G.findEdge(u,v,e)) {
   256     ///   ...
   257     /// }
   258     /// \endcode
   259     /// \todo Possibly it should be a global function.
   260     Edge findEdge(Node u,Node v, Edge prev = INVALID) 
   261     {
   262       return _findEdge(u,v,prev);
   263     }
   264     
   265     ///Internal data structure to store snapshots
   266     
   267     ///\ingroup graphs
   268     ///\sa makeSnapShot()
   269     ///\sa rollBack()
   270     struct SnapShot 
   271     {
   272       unsigned int node_num;
   273       unsigned int edge_num;
   274     };
   275     
   276     ///Make a snapshot of the graph.
   277 
   278     ///Make a snapshot of the graph.
   279     ///
   280     ///The newly added nodes and edges can be removed using the
   281     ///rollBack() function.
   282     ///
   283     ///\return An stucture SnapShot describing the pesent state of the
   284     ///graph.
   285     ///\note After you rolled back to a state, you cannot roll "back" to
   286     ///a later state, in other word you cannot add again the edges deleted
   287     ///by rollBack().
   288     ///\todo This function might be called saveState() or getState().
   289     SnapShot makeSnapShot() 
   290     {
   291       SnapShot s;
   292       s.node_num=nodes.size();
   293       s.edge_num=edges.size();
   294       return s;
   295     }
   296     
   297     ///Undo the changes until a snapshot.
   298 
   299     ///Undo the changes until a snapshot created by makeSnapShot().
   300     ///
   301     ///\param s an internal stucture given back by makeSnapShot()
   302     ///\note After you rolled back to a state, you cannot "roll forward" to
   303     ///a later state, in other word you cannot add again the edges deleted
   304     ///by rollBack().
   305     ///
   306     ///\todo This function might be called undo().
   307     
   308     void rollBack(const SnapShot &s)
   309     {
   310       while(s.edge_num>edges.size()) {
   311 	edge_observers.erase(Edge(edges.size()-1));
   312 	nodes[edges.back().head].first_in=edges.back().next_in;
   313 	nodes[edges.back().tail].first_out=edges.back().next_out;
   314 	edges.pop_back();
   315       }
   316       //nodes.resize(s.nodes_num);
   317       while(s.node_num>nodes.size()) {
   318 	node_observers.erase(Node(nodes.size()-1));
   319 	nodes.pop_back();
   320       }
   321     }
   322   };
   323   
   324   /// @}  
   325 } //namespace lemon
   326 
   327 
   328 #endif //LEMON_SMART_GRAPH_H