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