lemon/list_graph.h
author deba
Fri, 04 Nov 2005 16:40:54 +0000
changeset 1774 9fd56d75293e
parent 1770 657de7e5043c
child 1791 62e7d237e1fb
permissions -rw-r--r--
UnsupportedException on erase with Snapshot
     1 /* -*- C++ -*-
     2  * lemon/list_graph.h - Part of LEMON, a generic C++ optimization library
     3  *
     4  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     5  * (Egervary Research Group on Combinatorial Optimization, 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_LIST_GRAPH_H
    18 #define LEMON_LIST_GRAPH_H
    19 
    20 ///\ingroup graphs
    21 ///\file
    22 ///\brief ListGraph, UndirListGraph classes.
    23 
    24 #include <lemon/bits/erasable_graph_extender.h>
    25 #include <lemon/bits/clearable_graph_extender.h>
    26 #include <lemon/bits/extendable_graph_extender.h>
    27 #include <lemon/bits/iterable_graph_extender.h>
    28 #include <lemon/bits/alteration_notifier.h>
    29 #include <lemon/bits/default_map.h>
    30 
    31 #include <lemon/bits/undir_graph_extender.h>
    32 
    33 #include <lemon/error.h>
    34 
    35 #include <list>
    36 
    37 namespace lemon {
    38 
    39   class ListGraphBase {
    40 
    41   protected:
    42     struct NodeT {
    43       int first_in, first_out;
    44       int prev, next;
    45     };
    46  
    47     struct EdgeT {
    48       int target, source;
    49       int prev_in, prev_out;
    50       int next_in, next_out;
    51     };
    52 
    53     std::vector<NodeT> nodes;
    54 
    55     int first_node;
    56 
    57     int first_free_node;
    58 
    59     std::vector<EdgeT> edges;
    60 
    61     int first_free_edge;
    62     
    63   public:
    64     
    65     typedef ListGraphBase Graph;
    66     
    67     class Node {
    68       friend class ListGraphBase;
    69     protected:
    70 
    71       int id;
    72       Node(int pid) { id = pid;}
    73 
    74     public:
    75       Node() {}
    76       Node (Invalid) { id = -1; }
    77       bool operator==(const Node& node) const {return id == node.id;}
    78       bool operator!=(const Node& node) const {return id != node.id;}
    79       bool operator<(const Node& node) const {return id < node.id;}
    80     };
    81 
    82     class Edge {
    83       friend class ListGraphBase;
    84     protected:
    85 
    86       int id;
    87       Edge(int pid) { id = pid;}
    88 
    89     public:
    90       Edge() {}
    91       Edge (Invalid) { id = -1; }
    92       bool operator==(const Edge& edge) const {return id == edge.id;}
    93       bool operator!=(const Edge& edge) const {return id != edge.id;}
    94       bool operator<(const Edge& edge) const {return id < edge.id;}
    95     };
    96 
    97 
    98 
    99     ListGraphBase()
   100       : nodes(), first_node(-1),
   101 	first_free_node(-1), edges(), first_free_edge(-1) {}
   102 
   103     
   104     /// Maximum node ID.
   105     
   106     /// Maximum node ID.
   107     ///\sa id(Node)
   108     int maxId(Node = INVALID) const { return nodes.size()-1; } 
   109 
   110     /// Maximum edge ID.
   111     
   112     /// Maximum edge ID.
   113     ///\sa id(Edge)
   114     int maxId(Edge = INVALID) const { return edges.size()-1; }
   115 
   116     Node source(Edge e) const { return edges[e.id].source; }
   117     Node target(Edge e) const { return edges[e.id].target; }
   118 
   119 
   120     void first(Node& node) const { 
   121       node.id = first_node;
   122     }
   123 
   124     void next(Node& node) const {
   125       node.id = nodes[node.id].next;
   126     }
   127 
   128 
   129     void first(Edge& e) const { 
   130       int n;
   131       for(n = first_node; 
   132 	  n!=-1 && nodes[n].first_in == -1; 
   133 	  n = nodes[n].next);
   134       e.id = (n == -1) ? -1 : nodes[n].first_in;
   135     }
   136 
   137     void next(Edge& edge) const {
   138       if (edges[edge.id].next_in != -1) {
   139 	edge.id = edges[edge.id].next_in;
   140       } else {
   141 	int n;
   142 	for(n = nodes[edges[edge.id].target].next;
   143 	  n!=-1 && nodes[n].first_in == -1; 
   144 	  n = nodes[n].next);
   145 	edge.id = (n == -1) ? -1 : nodes[n].first_in;
   146       }      
   147     }
   148 
   149     void firstOut(Edge &e, const Node& v) const {
   150       e.id = nodes[v.id].first_out;
   151     }
   152     void nextOut(Edge &e) const {
   153       e.id=edges[e.id].next_out;
   154     }
   155 
   156     void firstIn(Edge &e, const Node& v) const {
   157       e.id = nodes[v.id].first_in;
   158     }
   159     void nextIn(Edge &e) const {
   160       e.id=edges[e.id].next_in;
   161     }
   162 
   163     
   164     static int id(Node v) { return v.id; }
   165     static int id(Edge e) { return e.id; }
   166 
   167     static Node fromId(int id, Node) { return Node(id);}
   168     static Edge fromId(int id, Edge) { return Edge(id);}
   169 
   170     /// Adds a new node to the graph.
   171 
   172     /// \warning It adds the new node to the front of the list.
   173     /// (i.e. the lastly added node becomes the first.)
   174     Node addNode() {     
   175       int n;
   176       
   177       if(first_free_node==-1) {
   178 	n = nodes.size();
   179 	nodes.push_back(NodeT());
   180       } else {
   181 	n = first_free_node;
   182 	first_free_node = nodes[n].next;
   183       }
   184       
   185       nodes[n].next = first_node;
   186       if(first_node != -1) nodes[first_node].prev = n;
   187       first_node = n;
   188       nodes[n].prev = -1;
   189       
   190       nodes[n].first_in = nodes[n].first_out = -1;
   191       
   192       return Node(n);
   193     }
   194     
   195     Edge addEdge(Node u, Node v) {
   196       int n;      
   197 
   198       if (first_free_edge == -1) {
   199 	n = edges.size();
   200 	edges.push_back(EdgeT());
   201       } else {
   202 	n = first_free_edge;
   203 	first_free_edge = edges[n].next_in;
   204       }
   205       
   206       edges[n].source = u.id; 
   207       edges[n].target = v.id;
   208 
   209       edges[n].next_out = nodes[u.id].first_out;
   210       if(nodes[u.id].first_out != -1) {
   211 	edges[nodes[u.id].first_out].prev_out = n;
   212       }
   213       
   214       edges[n].next_in = nodes[v.id].first_in;
   215       if(nodes[v.id].first_in != -1) {
   216 	edges[nodes[v.id].first_in].prev_in = n;
   217       }
   218       
   219       edges[n].prev_in = edges[n].prev_out = -1;
   220 	
   221       nodes[u.id].first_out = nodes[v.id].first_in = n;
   222 
   223       return Edge(n);
   224     }
   225     
   226     void erase(const Node& node) {
   227       int n = node.id;
   228       
   229       if(nodes[n].next != -1) {
   230 	nodes[nodes[n].next].prev = nodes[n].prev;
   231       }
   232       
   233       if(nodes[n].prev != -1) {
   234 	nodes[nodes[n].prev].next = nodes[n].next;
   235       } else {
   236 	first_node = nodes[n].next;
   237       }
   238       
   239       nodes[n].next = first_free_node;
   240       first_free_node = n;
   241 
   242     }
   243     
   244     void erase(const Edge& edge) {
   245       int n = edge.id;
   246       
   247       if(edges[n].next_in!=-1) {
   248 	edges[edges[n].next_in].prev_in = edges[n].prev_in;
   249       }
   250 
   251       if(edges[n].prev_in!=-1) {
   252 	edges[edges[n].prev_in].next_in = edges[n].next_in;
   253       } else {
   254 	nodes[edges[n].target].first_in = edges[n].next_in;
   255       }
   256 
   257       
   258       if(edges[n].next_out!=-1) {
   259 	edges[edges[n].next_out].prev_out = edges[n].prev_out;
   260       } 
   261 
   262       if(edges[n].prev_out!=-1) {
   263 	edges[edges[n].prev_out].next_out = edges[n].next_out;
   264       } else {
   265 	nodes[edges[n].source].first_out = edges[n].next_out;
   266       }
   267       
   268       edges[n].next_in = first_free_edge;
   269       first_free_edge = n;      
   270 
   271     }
   272 
   273     void clear() {
   274       edges.clear();
   275       nodes.clear();
   276       first_node = first_free_node = first_free_edge = -1;
   277     }
   278 
   279   protected:
   280     void _changeTarget(Edge e, Node n) 
   281     {
   282       if(edges[e.id].next_in != -1)
   283 	edges[edges[e.id].next_in].prev_in = edges[e.id].prev_in;
   284       if(edges[e.id].prev_in != -1)
   285 	edges[edges[e.id].prev_in].next_in = edges[e.id].next_in;
   286       else nodes[edges[e.id].target].first_in = edges[e.id].next_in;
   287       if (nodes[n.id].first_in != -1) {
   288 	edges[nodes[n.id].first_in].prev_in = e.id;
   289       }
   290       edges[e.id].target = n.id;
   291       edges[e.id].prev_in = -1;
   292       edges[e.id].next_in = nodes[n.id].first_in;
   293       nodes[n.id].first_in = e.id;
   294     }
   295     void _changeSource(Edge e, Node n) 
   296     {
   297       if(edges[e.id].next_out != -1)
   298 	edges[edges[e.id].next_out].prev_out = edges[e.id].prev_out;
   299       if(edges[e.id].prev_out != -1)
   300 	edges[edges[e.id].prev_out].next_out = edges[e.id].next_out;
   301       else nodes[edges[e.id].source].first_out = edges[e.id].next_out;
   302       if (nodes[n.id].first_out != -1) {
   303 	edges[nodes[n.id].first_out].prev_out = e.id;
   304       }
   305       edges[e.id].source = n.id;
   306       edges[e.id].prev_out = -1;
   307       edges[e.id].next_out = nodes[n.id].first_out;
   308       nodes[n.id].first_out = e.id;
   309     }
   310 
   311   };
   312 
   313   typedef ErasableGraphExtender<
   314     ClearableGraphExtender<
   315     ExtendableGraphExtender<
   316     MappableGraphExtender<
   317     IterableGraphExtender<
   318     AlterableGraphExtender<ListGraphBase> > > > > > ExtendedListGraphBase;
   319 
   320   /// \addtogroup graphs
   321   /// @{
   322 
   323   ///A list graph class.
   324 
   325   ///This is a simple and fast erasable graph implementation.
   326   ///
   327   ///It addition that it conforms to the
   328   ///\ref concept::ErasableGraph "ErasableGraph" concept,
   329   ///it also provides several additional useful extra functionalities.
   330   ///\sa concept::ErasableGraph.
   331 
   332   class ListGraph : public ExtendedListGraphBase 
   333   {
   334   public:
   335     /// Changes the target of \c e to \c n
   336 
   337     /// Changes the target of \c e to \c n
   338     ///
   339     ///\note The <tt>Edge</tt>'s and <tt>OutEdge</tt>'s
   340     ///referencing the changed edge remain
   341     ///valid. However <tt>InEdge</tt>'s are invalidated.
   342     void changeTarget(Edge e, Node n) { 
   343       _changeTarget(e,n); 
   344     }
   345     /// Changes the source of \c e to \c n
   346 
   347     /// Changes the source of \c e to \c n
   348     ///
   349     ///\note The <tt>Edge</tt>'s and <tt>InEdge</tt>'s
   350     ///referencing the changed edge remain
   351     ///valid. However <tt>OutEdge</tt>'s are invalidated.
   352     void changeSource(Edge e, Node n) { 
   353       _changeSource(e,n);
   354     }
   355 
   356     /// Invert the direction of an edge.
   357 
   358     ///\note The <tt>Edge</tt>'s
   359     ///referencing the changed edge remain
   360     ///valid. However <tt>OutEdge</tt>'s  and <tt>InEdge</tt>'s are invalidated.
   361     void reverseEdge(Edge e) {
   362       Node t=target(e);
   363       _changeTarget(e,source(e));
   364       _changeSource(e,t);
   365     }
   366 
   367     ///Using this it possible to avoid the superfluous memory allocation.
   368 
   369     ///Using this it possible to avoid the superfluous memory allocation.
   370     ///\todo more docs...
   371     void reserveEdge(int n) { edges.reserve(n); };
   372 
   373     ///Contract two nodes.
   374 
   375     ///This function contracts two nodes.
   376     ///
   377     ///Node \p b will be removed but instead of deleting
   378     ///its neighboring edges, they will be joined to \p a.
   379     ///The last parameter \p r controls whether to remove loops. \c true
   380     ///means that loops will be removed.
   381     ///
   382     ///\note The <tt>Edge</tt>s
   383     ///referencing a moved edge remain
   384     ///valid. However <tt>InEdge</tt>'s and <tt>OutEdge</tt>'s
   385     ///may be invalidated.
   386     void contract(Node a, Node b, bool r = true) 
   387     {
   388       for(OutEdgeIt e(*this,b);e!=INVALID;) {
   389 	OutEdgeIt f=e;
   390 	++f;
   391 	if(r && target(e)==a) erase(e);
   392 	else changeSource(e,a);
   393 	e=f;
   394       }
   395       for(InEdgeIt e(*this,b);e!=INVALID;) {
   396 	InEdgeIt f=e;
   397 	++f;
   398 	if(r && source(e)==a) erase(e);
   399 	else changeTarget(e,a);
   400 	e=f;
   401       }
   402       erase(b);
   403     }
   404 
   405     ///Split a node.
   406 
   407     ///This function splits a node. First a new node is added to the graph,
   408     ///then the source of each outgoing edge of \c n is moved to this new node.
   409     ///If \c connect is \c true (this is the default value), then a new edge
   410     ///from \c n to the newly created node is also added.
   411     ///\return The newly created node.
   412     ///
   413     ///\note The <tt>Edge</tt>s
   414     ///referencing a moved edge remain
   415     ///valid. However <tt>InEdge</tt>'s and <tt>OutEdge</tt>'s
   416     ///may be invalidated.
   417     ///\warning This functionality cannot be used together with the Snapshot
   418     ///feature.
   419     ///\todo It could be implemented in a bit faster way.
   420     Node split(Node n, bool connect = true) 
   421     {
   422       Node b = addNode();
   423       for(OutEdgeIt e(*this,n);e!=INVALID;) {
   424  	OutEdgeIt f=e;
   425 	++f;
   426 	changeSource(e,b);
   427 	e=f;
   428       }
   429       if(connect) addEdge(n,b);
   430       return b;
   431     }
   432       
   433     ///Class to make a snapshot of the graph and to restrore to it later.
   434 
   435     ///Class to make a snapshot of the graph and to restrore to it later.
   436     ///
   437     ///The newly added nodes and edges can be removed using the
   438     ///restore() function.
   439     ///
   440     ///\warning Edge and node deletions cannot be restored.
   441     ///\warning Snapshots cannot be nested.
   442     class Snapshot : protected AlterationNotifier<Node>::ObserverBase,
   443 		     protected AlterationNotifier<Edge>::ObserverBase
   444     {
   445     public:
   446       
   447       class UnsupportedOperation : public LogicError {
   448       public:
   449 	virtual const char* exceptionName() const {
   450 	  return "lemon::ListGraph::Snapshot::UnsupportedOperation";
   451 	}
   452       };
   453             
   454 
   455       protected:
   456       
   457       ListGraph *g;
   458       std::list<Node> added_nodes;
   459       std::list<Edge> added_edges;
   460       
   461       bool active;
   462       virtual void add(const Node& n) {
   463 	added_nodes.push_back(n);
   464       };
   465       virtual void erase(const Node&) 
   466       {
   467 	throw UnsupportedOperation();
   468       }
   469       virtual void add(const Edge& n) {
   470 	added_edges.push_back(n);
   471       };
   472       virtual void erase(const Edge&) 
   473       {
   474 	throw UnsupportedOperation();
   475       }
   476 
   477       ///\bug What is this used for?
   478       ///
   479       virtual void build() {}
   480       ///\bug What is this used for?
   481       ///
   482       virtual void clear() {}
   483 
   484       void regist(ListGraph &_g) {
   485 	g=&_g;
   486 	AlterationNotifier<Node>::ObserverBase::
   487 	  attach(g->getNotifier(Node()));
   488 	AlterationNotifier<Edge>::ObserverBase::
   489 	  attach(g->getNotifier(Edge()));
   490       }
   491             
   492       void deregist() {
   493 	AlterationNotifier<Node>::ObserverBase::
   494 	  detach();
   495 	AlterationNotifier<Edge>::ObserverBase::
   496 	  detach();
   497 	g=0;
   498       }
   499 
   500     public:
   501       ///Default constructur.
   502       
   503       ///Default constructur.
   504       ///To actually make a snapshot you must call save().
   505       ///
   506       Snapshot() : g(0) {}
   507       ///Constructor that immediately makes a snapshot.
   508       
   509       ///This constructor immediately makes a snapshot of the graph.
   510       ///\param _g The graph we make a snapshot of.
   511       Snapshot(ListGraph &_g) {
   512 	regist(_g);
   513       }
   514       ///\bug Is it necessary?
   515       ///
   516       ~Snapshot() 
   517       {
   518 	if(g) deregist();
   519       }
   520       
   521       ///Make a snapshot.
   522 
   523       ///Make a snapshot of the graph.
   524       ///
   525       ///This function can be called more than once. In case of a repeated
   526       ///call, the previous snapshot gets lost.
   527       ///\param _g The graph we make the snapshot of.
   528       void save(ListGraph &_g) 
   529       {
   530 	if(g!=&_g) {
   531 	  if(g) deregist();
   532 	  regist(_g);
   533 	}
   534 	added_nodes.clear();
   535 	added_edges.clear();
   536       }
   537       
   538     ///Undo the changes until the last snapshot.
   539 
   540     ///Undo the changes until last snapshot created by save().
   541     ///
   542     ///\todo This function might be called undo().
   543       void restore() {
   544 	ListGraph &old_g=*g;
   545 	deregist();
   546 	while(!added_edges.empty()) {
   547 	  old_g.erase(added_edges.front());
   548 	  added_edges.pop_front();
   549 	}
   550  	while(!added_nodes.empty()) {
   551 	  old_g.erase(added_nodes.front());
   552 	  added_nodes.pop_front();
   553 	}
   554       }
   555     };
   556     
   557   };
   558 
   559   ///@}
   560 
   561   /**************** Undirected List Graph ****************/
   562 
   563   typedef ErasableUndirGraphExtender<
   564     ClearableUndirGraphExtender<
   565     ExtendableUndirGraphExtender<
   566     MappableUndirGraphExtender<
   567     IterableUndirGraphExtender<
   568     AlterableUndirGraphExtender<
   569     UndirGraphExtender<ListGraphBase> > > > > > > ExtendedUndirListGraphBase;
   570 
   571   /// \addtogroup graphs
   572   /// @{
   573 
   574   ///An undirected list graph class.
   575 
   576   ///This is a simple and fast erasable undirected graph implementation.
   577   ///
   578   ///It conforms to the
   579   ///\ref concept::UndirGraph "UndirGraph" concept.
   580   ///
   581   ///\sa concept::UndirGraph.
   582   ///
   583   ///\todo Snapshot, reverseEdge(), changeTarget(), changeSource(), contract()
   584   ///haven't been implemented yet.
   585   ///
   586   class UndirListGraph : public ExtendedUndirListGraphBase {
   587   public:
   588     typedef ExtendedUndirListGraphBase Parent;
   589     /// \brief Changes the target of \c e to \c n
   590     ///
   591     /// Changes the target of \c e to \c n
   592     ///
   593     /// \note The <tt>Edge</tt>'s and <tt>OutEdge</tt>'s
   594     /// referencing the changed edge remain
   595     /// valid. However <tt>InEdge</tt>'s are invalidated.
   596     void changeTarget(UndirEdge e, Node n) { 
   597       _changeTarget(e,n); 
   598     }
   599     /// Changes the source of \c e to \c n
   600     ///
   601     /// Changes the source of \c e to \c n
   602     ///
   603     ///\note The <tt>Edge</tt>'s and <tt>InEdge</tt>'s
   604     ///referencing the changed edge remain
   605     ///valid. However <tt>OutEdge</tt>'s are invalidated.
   606     void changeSource(UndirEdge e, Node n) { 
   607       _changeSource(e,n); 
   608     }
   609     /// \brief Contract two nodes.
   610     ///
   611     /// This function contracts two nodes.
   612     ///
   613     /// Node \p b will be removed but instead of deleting
   614     /// its neighboring edges, they will be joined to \p a.
   615     /// The last parameter \p r controls whether to remove loops. \c true
   616     /// means that loops will be removed.
   617     ///
   618     /// \note The <tt>Edge</tt>s
   619     /// referencing a moved edge remain
   620     /// valid.
   621     void contract(Node a, Node b, bool r = true) {
   622       for(IncEdgeIt e(*this, b); e!=INVALID;) {
   623 	IncEdgeIt f = e; ++f;
   624 	if (r && runningNode(e) == a) {
   625 	  erase(e);
   626 	} else if (source(e) == b) {
   627 	  changeSource(e, a);
   628 	} else {
   629 	  changeTarget(e, a);
   630 	}
   631 	e = f;
   632       }
   633       erase(b);
   634     }
   635   };
   636 
   637   
   638   /// @}  
   639 } //namespace lemon
   640   
   641 
   642 #endif