lemon/list_graph.h
author alpar
Fri, 03 Feb 2006 09:18:17 +0000
changeset 1949 5db4ff8d69de
parent 1875 98698b69a902
child 1956 a055123339d5
permissions -rw-r--r--
Fight with Doxygen.
Victory hasn't been reached yet, but it's on the horizon.
     1 /* -*- C++ -*-
     2  * lemon/list_graph.h - Part of LEMON, a generic C++ optimization library
     3  *
     4  * Copyright (C) 2006 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, ListUGraph 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 #include <lemon/bits/graph_extender.h>
    31 
    32 #include <lemon/error.h>
    33 
    34 #include <list>
    35 
    36 namespace lemon {
    37 
    38   class ListGraphBase {
    39 
    40   protected:
    41     struct NodeT {
    42       int first_in, first_out;
    43       int prev, next;
    44     };
    45  
    46     struct EdgeT {
    47       int target, source;
    48       int prev_in, prev_out;
    49       int next_in, next_out;
    50     };
    51 
    52     std::vector<NodeT> nodes;
    53 
    54     int first_node;
    55 
    56     int first_free_node;
    57 
    58     std::vector<EdgeT> edges;
    59 
    60     int first_free_edge;
    61     
    62   public:
    63     
    64     typedef ListGraphBase Graph;
    65     
    66     class Node {
    67       friend class ListGraphBase;
    68     protected:
    69 
    70       int id;
    71       Node(int pid) { id = pid;}
    72 
    73     public:
    74       Node() {}
    75       Node (Invalid) { id = -1; }
    76       bool operator==(const Node& node) const {return id == node.id;}
    77       bool operator!=(const Node& node) const {return id != node.id;}
    78       bool operator<(const Node& node) const {return id < node.id;}
    79     };
    80 
    81     class Edge {
    82       friend class ListGraphBase;
    83     protected:
    84 
    85       int id;
    86       Edge(int pid) { id = pid;}
    87 
    88     public:
    89       Edge() {}
    90       Edge (Invalid) { id = -1; }
    91       bool operator==(const Edge& edge) const {return id == edge.id;}
    92       bool operator!=(const Edge& edge) const {return id != edge.id;}
    93       bool operator<(const Edge& edge) const {return id < edge.id;}
    94     };
    95 
    96 
    97 
    98     ListGraphBase()
    99       : nodes(), first_node(-1),
   100 	first_free_node(-1), edges(), first_free_edge(-1) {}
   101 
   102     
   103     /// Maximum node ID.
   104     
   105     /// Maximum node ID.
   106     ///\sa id(Node)
   107     int maxNodeId() const { return nodes.size()-1; } 
   108 
   109     /// Maximum edge ID.
   110     
   111     /// Maximum edge ID.
   112     ///\sa id(Edge)
   113     int maxEdgeId() const { return edges.size()-1; }
   114 
   115     Node source(Edge e) const { return edges[e.id].source; }
   116     Node target(Edge e) const { return edges[e.id].target; }
   117 
   118 
   119     void first(Node& node) const { 
   120       node.id = first_node;
   121     }
   122 
   123     void next(Node& node) const {
   124       node.id = nodes[node.id].next;
   125     }
   126 
   127 
   128     void first(Edge& e) const { 
   129       int n;
   130       for(n = first_node; 
   131 	  n!=-1 && nodes[n].first_in == -1; 
   132 	  n = nodes[n].next);
   133       e.id = (n == -1) ? -1 : nodes[n].first_in;
   134     }
   135 
   136     void next(Edge& edge) const {
   137       if (edges[edge.id].next_in != -1) {
   138 	edge.id = edges[edge.id].next_in;
   139       } else {
   140 	int n;
   141 	for(n = nodes[edges[edge.id].target].next;
   142 	  n!=-1 && nodes[n].first_in == -1; 
   143 	  n = nodes[n].next);
   144 	edge.id = (n == -1) ? -1 : nodes[n].first_in;
   145       }      
   146     }
   147 
   148     void firstOut(Edge &e, const Node& v) const {
   149       e.id = nodes[v.id].first_out;
   150     }
   151     void nextOut(Edge &e) const {
   152       e.id=edges[e.id].next_out;
   153     }
   154 
   155     void firstIn(Edge &e, const Node& v) const {
   156       e.id = nodes[v.id].first_in;
   157     }
   158     void nextIn(Edge &e) const {
   159       e.id=edges[e.id].next_in;
   160     }
   161 
   162     
   163     static int id(Node v) { return v.id; }
   164     static int id(Edge e) { return e.id; }
   165 
   166     static Node nodeFromId(int id) { return Node(id);}
   167     static Edge edgeFromId(int id) { return Edge(id);}
   168 
   169     /// Adds a new node to the graph.
   170 
   171     /// \warning It adds the new node to the front of the list.
   172     /// (i.e. the lastly added node becomes the first.)
   173     Node addNode() {     
   174       int n;
   175       
   176       if(first_free_node==-1) {
   177 	n = nodes.size();
   178 	nodes.push_back(NodeT());
   179       } else {
   180 	n = first_free_node;
   181 	first_free_node = nodes[n].next;
   182       }
   183       
   184       nodes[n].next = first_node;
   185       if(first_node != -1) nodes[first_node].prev = n;
   186       first_node = n;
   187       nodes[n].prev = -1;
   188       
   189       nodes[n].first_in = nodes[n].first_out = -1;
   190       
   191       return Node(n);
   192     }
   193     
   194     Edge addEdge(Node u, Node v) {
   195       int n;      
   196 
   197       if (first_free_edge == -1) {
   198 	n = edges.size();
   199 	edges.push_back(EdgeT());
   200       } else {
   201 	n = first_free_edge;
   202 	first_free_edge = edges[n].next_in;
   203       }
   204       
   205       edges[n].source = u.id; 
   206       edges[n].target = v.id;
   207 
   208       edges[n].next_out = nodes[u.id].first_out;
   209       if(nodes[u.id].first_out != -1) {
   210 	edges[nodes[u.id].first_out].prev_out = n;
   211       }
   212       
   213       edges[n].next_in = nodes[v.id].first_in;
   214       if(nodes[v.id].first_in != -1) {
   215 	edges[nodes[v.id].first_in].prev_in = n;
   216       }
   217       
   218       edges[n].prev_in = edges[n].prev_out = -1;
   219 	
   220       nodes[u.id].first_out = nodes[v.id].first_in = n;
   221 
   222       return Edge(n);
   223     }
   224     
   225     void erase(const Node& node) {
   226       int n = node.id;
   227       
   228       if(nodes[n].next != -1) {
   229 	nodes[nodes[n].next].prev = nodes[n].prev;
   230       }
   231       
   232       if(nodes[n].prev != -1) {
   233 	nodes[nodes[n].prev].next = nodes[n].next;
   234       } else {
   235 	first_node = nodes[n].next;
   236       }
   237       
   238       nodes[n].next = first_free_node;
   239       first_free_node = n;
   240 
   241     }
   242     
   243     void erase(const Edge& edge) {
   244       int n = edge.id;
   245       
   246       if(edges[n].next_in!=-1) {
   247 	edges[edges[n].next_in].prev_in = edges[n].prev_in;
   248       }
   249 
   250       if(edges[n].prev_in!=-1) {
   251 	edges[edges[n].prev_in].next_in = edges[n].next_in;
   252       } else {
   253 	nodes[edges[n].target].first_in = edges[n].next_in;
   254       }
   255 
   256       
   257       if(edges[n].next_out!=-1) {
   258 	edges[edges[n].next_out].prev_out = edges[n].prev_out;
   259       } 
   260 
   261       if(edges[n].prev_out!=-1) {
   262 	edges[edges[n].prev_out].next_out = edges[n].next_out;
   263       } else {
   264 	nodes[edges[n].source].first_out = edges[n].next_out;
   265       }
   266       
   267       edges[n].next_in = first_free_edge;
   268       first_free_edge = n;      
   269 
   270     }
   271 
   272     void clear() {
   273       edges.clear();
   274       nodes.clear();
   275       first_node = first_free_node = first_free_edge = -1;
   276     }
   277 
   278   protected:
   279     void _changeTarget(Edge e, Node n) 
   280     {
   281       if(edges[e.id].next_in != -1)
   282 	edges[edges[e.id].next_in].prev_in = edges[e.id].prev_in;
   283       if(edges[e.id].prev_in != -1)
   284 	edges[edges[e.id].prev_in].next_in = edges[e.id].next_in;
   285       else nodes[edges[e.id].target].first_in = edges[e.id].next_in;
   286       if (nodes[n.id].first_in != -1) {
   287 	edges[nodes[n.id].first_in].prev_in = e.id;
   288       }
   289       edges[e.id].target = n.id;
   290       edges[e.id].prev_in = -1;
   291       edges[e.id].next_in = nodes[n.id].first_in;
   292       nodes[n.id].first_in = e.id;
   293     }
   294     void _changeSource(Edge e, Node n) 
   295     {
   296       if(edges[e.id].next_out != -1)
   297 	edges[edges[e.id].next_out].prev_out = edges[e.id].prev_out;
   298       if(edges[e.id].prev_out != -1)
   299 	edges[edges[e.id].prev_out].next_out = edges[e.id].next_out;
   300       else nodes[edges[e.id].source].first_out = edges[e.id].next_out;
   301       if (nodes[n.id].first_out != -1) {
   302 	edges[nodes[n.id].first_out].prev_out = e.id;
   303       }
   304       edges[e.id].source = n.id;
   305       edges[e.id].prev_out = -1;
   306       edges[e.id].next_out = nodes[n.id].first_out;
   307       nodes[n.id].first_out = e.id;
   308     }
   309 
   310   };
   311 
   312   typedef ErasableGraphExtender<
   313     ClearableGraphExtender<
   314     ExtendableGraphExtender<
   315     MappableGraphExtender<
   316     IterableGraphExtender<
   317     AlterableGraphExtender<
   318     GraphExtender<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     ///Split an edge.
   434 
   435     ///This function splits an edge. First a new node \c b is added to the graph,
   436     ///then the original edge is re-targetes to \c b. Finally an edge
   437     ///from \c b to the original target is added.
   438     ///\return The newly created node.
   439     ///\warning This functionality cannot be used together with the Snapshot
   440     ///feature.
   441     Node split(Edge e) 
   442     {
   443       Node b = addNode();
   444       addEdge(b,target(e));
   445       changeTarget(e,b);
   446       return b;
   447     }
   448       
   449     ///Class to make a snapshot of the graph and to restrore to it later.
   450 
   451     ///Class to make a snapshot of the graph and to restrore to it later.
   452     ///
   453     ///The newly added nodes and edges can be removed using the
   454     ///restore() function.
   455     ///
   456     ///\warning Edge and node deletions cannot be restored.
   457     ///\warning Snapshots cannot be nested.
   458     class Snapshot : protected AlterationNotifier<Node>::ObserverBase,
   459 		     protected AlterationNotifier<Edge>::ObserverBase
   460     {
   461     public:
   462       
   463       class UnsupportedOperation : public LogicError {
   464       public:
   465 	virtual const char* exceptionName() const {
   466 	  return "lemon::ListGraph::Snapshot::UnsupportedOperation";
   467 	}
   468       };
   469             
   470 
   471       protected:
   472       
   473       ListGraph *g;
   474       std::list<Node> added_nodes;
   475       std::list<Edge> added_edges;
   476       
   477       bool active;
   478       virtual void add(const Node& n) {
   479 	added_nodes.push_back(n);
   480       };
   481       virtual void erase(const Node&) 
   482       {
   483 	throw UnsupportedOperation();
   484       }
   485       virtual void add(const Edge& n) {
   486 	added_edges.push_back(n);
   487       };
   488       virtual void erase(const Edge&) 
   489       {
   490 	throw UnsupportedOperation();
   491       }
   492 
   493       ///\bug What is this used for?
   494       ///
   495       virtual void build() {}
   496       ///\bug What is this used for?
   497       ///
   498       virtual void clear() {}
   499 
   500       void regist(ListGraph &_g) {
   501 	g=&_g;
   502 	AlterationNotifier<Node>::ObserverBase::
   503 	  attach(g->getNotifier(Node()));
   504 	AlterationNotifier<Edge>::ObserverBase::
   505 	  attach(g->getNotifier(Edge()));
   506       }
   507             
   508       void deregist() {
   509 	AlterationNotifier<Node>::ObserverBase::
   510 	  detach();
   511 	AlterationNotifier<Edge>::ObserverBase::
   512 	  detach();
   513 	g=0;
   514       }
   515 
   516     public:
   517       ///Default constructur.
   518       
   519       ///Default constructur.
   520       ///To actually make a snapshot you must call save().
   521       ///
   522       Snapshot() : g(0) {}
   523       ///Constructor that immediately makes a snapshot.
   524       
   525       ///This constructor immediately makes a snapshot of the graph.
   526       ///\param _g The graph we make a snapshot of.
   527       Snapshot(ListGraph &_g) {
   528 	regist(_g);
   529       }
   530       ///\bug Is it necessary?
   531       ///
   532       ~Snapshot() 
   533       {
   534 	if(g) deregist();
   535       }
   536       
   537       ///Make a snapshot.
   538 
   539       ///Make a snapshot of the graph.
   540       ///
   541       ///This function can be called more than once. In case of a repeated
   542       ///call, the previous snapshot gets lost.
   543       ///\param _g The graph we make the snapshot of.
   544       void save(ListGraph &_g) 
   545       {
   546 	if(g!=&_g) {
   547 	  if(g) deregist();
   548 	  regist(_g);
   549 	}
   550 	added_nodes.clear();
   551 	added_edges.clear();
   552       }
   553       
   554     ///Undo the changes until the last snapshot.
   555 
   556     ///Undo the changes until last snapshot created by save().
   557     ///
   558     ///\todo This function might be called undo().
   559       void restore() {
   560 	ListGraph &old_g=*g;
   561 	deregist();
   562 	while(!added_edges.empty()) {
   563 	  old_g.erase(added_edges.front());
   564 	  added_edges.pop_front();
   565 	}
   566  	while(!added_nodes.empty()) {
   567 	  old_g.erase(added_nodes.front());
   568 	  added_nodes.pop_front();
   569 	}
   570       }
   571     };
   572     
   573   };
   574 
   575   ///@}
   576 
   577   /**************** Undirected List Graph ****************/
   578 
   579   typedef ErasableUGraphExtender<
   580     ClearableUGraphExtender<
   581     ExtendableUGraphExtender<
   582     MappableUGraphExtender<
   583     IterableUGraphExtender<
   584     AlterableUGraphExtender<
   585     UGraphExtender<ListGraphBase> > > > > > > ExtendedListUGraphBase;
   586 
   587   /// \addtogroup graphs
   588   /// @{
   589 
   590   ///An undirected list graph class.
   591 
   592   ///This is a simple and fast erasable undirected graph implementation.
   593   ///
   594   ///It conforms to the
   595   ///\ref concept::UGraph "UGraph" concept.
   596   ///
   597   ///\sa concept::UGraph.
   598   ///
   599   ///\todo Snapshot, reverseEdge(), changeTarget(), changeSource(), contract()
   600   ///haven't been implemented yet.
   601   ///
   602   class ListUGraph : public ExtendedListUGraphBase {
   603   public:
   604     typedef ExtendedListUGraphBase Parent;
   605     /// \brief Changes the target of \c e to \c n
   606     ///
   607     /// Changes the target of \c e to \c n
   608     ///
   609     /// \note The <tt>Edge</tt>'s and <tt>OutEdge</tt>'s
   610     /// referencing the changed edge remain
   611     /// valid. However <tt>InEdge</tt>'s are invalidated.
   612     void changeTarget(UEdge e, Node n) { 
   613       _changeTarget(e,n); 
   614     }
   615     /// Changes the source of \c e to \c n
   616     ///
   617     /// Changes the source of \c e to \c n
   618     ///
   619     ///\note The <tt>Edge</tt>'s and <tt>InEdge</tt>'s
   620     ///referencing the changed edge remain
   621     ///valid. However <tt>OutEdge</tt>'s are invalidated.
   622     void changeSource(UEdge e, Node n) { 
   623       _changeSource(e,n); 
   624     }
   625     /// \brief Contract two nodes.
   626     ///
   627     /// This function contracts two nodes.
   628     ///
   629     /// Node \p b will be removed but instead of deleting
   630     /// its neighboring edges, they will be joined to \p a.
   631     /// The last parameter \p r controls whether to remove loops. \c true
   632     /// means that loops will be removed.
   633     ///
   634     /// \note The <tt>Edge</tt>s
   635     /// referencing a moved edge remain
   636     /// valid.
   637     void contract(Node a, Node b, bool r = true) {
   638       for(IncEdgeIt e(*this, b); e!=INVALID;) {
   639 	IncEdgeIt f = e; ++f;
   640 	if (r && runningNode(e) == a) {
   641 	  erase(e);
   642 	} else if (source(e) == b) {
   643 	  changeSource(e, a);
   644 	} else {
   645 	  changeTarget(e, a);
   646 	}
   647 	e = f;
   648       }
   649       erase(b);
   650     }
   651   };
   652 
   653   
   654   /// @}  
   655 } //namespace lemon
   656   
   657 
   658 #endif