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