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