CMS 3D CMS Logo

/afs/cern.ch/work/a/aaltunda/public/www/CMSSW_6_2_7/src/DetectorDescription/Core/interface/adjgraph.h

Go to the documentation of this file.
00001 #ifndef DDD_graph_h
00002 #define DDD_graph_h
00003 
00004 #include <vector>
00005 #include <map>
00006 #include <iostream>
00007 
00008 // Adjecencylist graph
00009 
00010 // N,E must be concepts of default constructable, assignable, copyable, operator<
00011 template <class N, class E> 
00012 class graph
00013 {
00014 public:
00015   typedef std::vector<double>::size_type index_type;
00016   // (node-index target, edge)
00017   typedef std::pair<index_type, index_type> edge_type;
00018   // (std::vector of edge_types for the adj_list)
00019   typedef std::vector<edge_type> edge_list;
00020   // (node-index -> edge_list) the adjacency-list
00021   typedef std::vector<edge_list> adj_list;
00022   
00023   class const_iterator
00024   {
00025     friend class graph<N, E>;
00026   public:
00027     typedef typename graph::index_type index_type;
00028     typedef typename graph::adj_list adj_list;
00029     typedef typename graph::edge_list edge_list;
00030     
00031     struct value_type
00032     {
00033       friend class graph<N,E>::const_iterator;
00034       value_type( const graph & g, index_type a, index_type e ) 
00035         : gr_( g ), a_( a ), e_( e ) 
00036         { }
00037       
00038       const N & from( void ) const { return gr_.nodeData( a_ ); }
00039       const N & to( void )   const { return gr_.nodeData( gr_.adjl_[a_][e_].first ); }
00040       const E & edge( void ) const { return gr_.edgeData( gr_.adjl_[a_][e_].second ); }
00041       
00042     private:
00043       const graph & gr_;
00044       index_type a_, e_;       
00045     };
00046     
00047     typedef value_type& reference;
00048     typedef value_type* pointer;
00049        
00050     bool operator==( const const_iterator & i ) const {  
00051       return (( vt_.a_ == i.vt_.a_ ) && ( vt_.e_ == i.vt_.e_ )) ? true : false;
00052     }
00053     
00054     bool operator!=( const const_iterator & i ) const {
00055       return (( vt_.a_ == i.vt_.a_ ) && ( vt_.e_ == i.vt_.e_ )) ? false : true;
00056     }
00057 
00058     void operator++() {
00059       while( vt_.gr_.size() > vt_.a_ )
00060       {
00061         index_type i = vt_.gr_.adjl_[vt_.a_].size();
00062         if( i > vt_.e_+1 )
00063         {
00064           ++vt_.e_;
00065           return;
00066         }
00067         vt_.e_=0;
00068         ++vt_.a_;
00069         while( vt_.gr_.size() > vt_.a_ )
00070         {
00071           if( vt_.gr_.adjl_[vt_.a_].size())
00072           {
00073             return;
00074           }
00075           ++vt_.a_;
00076         }
00077       } 
00078     }
00079 
00080     const value_type & operator*() const {
00081       return vt_;    
00082     }
00083     
00084     const value_type * operator->() const {
00085       return &vt_;
00086     }  
00087     
00088   private:
00089     explicit const_iterator( const graph & g )
00090       : vt_( g, 0, 0 )
00091       {}
00092       
00093     const_iterator( const graph & g, index_type ait, index_type eit ) 
00094       : vt_( g, ait, eit )
00095       {} 
00096        
00097     value_type vt_;
00098       
00099     bool operator<( const const_iterator & i ) const { 
00100       return ( vt_.a_ < i.vt_.a_ ) && ( vt_.e_ < i.vt_.e_ );
00101     }
00102 
00103     bool operator>(const const_iterator & i) const {
00104       return ( vt_.a_ > i.vt_.a_ ) && ( vt_.e_ > i.vt_.e_ );
00105     }
00106   };
00107 
00108   void dump_graph( void ) const;  
00109   // Graphtypes
00110   
00111   struct value_type {
00112     value_type(const N & n, const E & e) : first(n), second(e) { }
00113     const N & first;
00114     const E & second;
00115     N firstToValue() const { return first; }
00116     E secondToValue() const { return second; }
00117   };
00118 
00119   // (node-index -> node)
00120   typedef std::vector<N> node_list;
00121   typedef std::vector<E> edge_store;
00122   
00123   // (node-index -> edge_list) the adjacency-list
00124   typedef typename adj_list::iterator adj_iterator;
00125   typedef typename adj_list::const_iterator const_adj_iterator;
00126     
00127   
00128   // assigns a node-index to the node
00129   typedef std::map<N, index_type> indexer_type;
00130   typedef typename indexer_type::iterator indexer_iterator;
00131   typedef typename indexer_type::const_iterator const_indexer_iterator;
00132   
00133   // supported iterators and ranges
00134   typedef typename edge_list::iterator edge_iterator;
00135   
00136   typedef typename edge_list::const_iterator const_edge_iterator;
00137   
00138   typedef std::pair<edge_iterator,edge_iterator> edge_range;
00139   
00140   typedef std::pair<const_edge_iterator, const_edge_iterator> const_edge_range;
00141 
00142   typedef std::pair<index_type, bool> index_result;  
00143   
00144 public:
00145   // creation, deletion
00146   graph() : edges_(1)  { }
00147   ~graph() { }
00148 
00149   // operations
00150   
00151   // O(log(n)), n...number of nodes
00152   index_type addNode(const N &); 
00153   // O(log(n*e)), n,e...number of nodes,edges
00154   void addEdge(const N & from, const N & to, const E & edge);
00155   
00156   // O(1)
00157   //index_type addNode(const node_type &);
00158   // O(log(e))
00159   //index_type addEdge(const node_type & from, const node_type & to, const E & e);
00160  
00161   inline index_result nodeIndex(const N &) const;
00162   
00163   //index_type edgeIndex(const E &) const;
00164   
00165   // indexed edge_ranges, O(1) operation
00166   inline edge_range edges(index_type nodeIndex);
00167   inline const_edge_range edges(index_type nodeIndex) const;
00168   
00169   // indexed edge_ranges, O(log(n)) operation, n...number of nodes
00170   inline edge_range edges(const N &);
00171   inline const_edge_range edges(const N &) const;
00172   
00173   inline const N & nodeData(const edge_type &) const;
00174   inline const N & nodeData(index_type) const;
00175   inline const N & nodeData(const const_adj_iterator &) const;
00176  
00177   // replace oldNode by newNode O(log(n))
00178   bool replace(const N  & oldNode , const N & newNode );
00179    
00180   //replace oldEdge by newEdge
00181   bool replaceEdge(const E & ldEdge, const E &newEdge ); 
00182    
00183   const E & edgeData(index_type i) const { return edges_[i]; }
00184   // const N & nodeData(const adj_iterator &) const;
00185   // index of a node (O(log(n))
00186   
00188   void clear();
00189   // access to the linear-iterator
00190   const_iterator begin_iter() const { return const_iterator(*this); }    
00191   
00192   const_iterator end_iter() const { return const_iterator(*this, adjl_.size(),0); }
00193   
00194   size_t edge_size() const { return edges_.size(); }
00195   
00196   // access to the adjacency-list
00197   adj_iterator begin() { return adjl_.begin(); } 
00198   const_adj_iterator begin() const { return adjl_.begin(); }
00199   adj_iterator end() { return adjl_.end(); }
00200   const_adj_iterator end() const { return adjl_.end(); }
00201   typename adj_list::size_type size() const { return adjl_.size(); }
00202   
00203   // finds all roots of the graph and puts them into the edge_list
00204   void findRoots(edge_list &) const;
00205   
00206   // inverts the directed graph, i.e. edge(A,B) -> edge(B,A)
00207   void invert(graph & g) const;
00208 
00209   void swap( graph<N, E> & );
00210   
00211   // Data   
00212 private:
00213   
00214   // adjacency list
00215   adj_list adjl_;
00216   
00217   // std::mapping of index to node
00218   node_list nodes_;
00219   
00220   // std::mapping of indes to edge
00221   edge_store edges_;
00222   
00223   // indexer for N and E
00224   indexer_type indexer_; // eIndexer_;
00225   
00226   // dummy
00227   edge_list emptyEdges_;
00228   
00229 };
00230 
00231                                                         
00232 
00233 template<class N, class E>
00234 typename graph<N,E>::index_type graph<N,E>::addNode(const N & node)
00235 {
00236   index_type idx = indexer_.size() ; //  +1;
00237   std::pair<indexer_iterator,bool> result 
00238     = indexer_.insert(typename indexer_type::value_type(node,idx));
00239   
00240   if ( result.second ) { // new index!
00241     nodes_.push_back(node);
00242     adjl_.push_back(edge_list());
00243   }  
00244   else {
00245     idx = result.first->second;
00246   }
00247   return idx;
00248 }
00249 
00250 
00251 template<class N, class E>
00252 typename graph<N,E>::index_result graph<N,E>::nodeIndex(const N & node) const
00253 {
00254   typename indexer_type::const_iterator result = indexer_.find(node);
00255   index_type idx = 0;
00256   bool flag = false;
00257   if (result != indexer_.end()) {
00258     flag = true;
00259     idx = result->second;
00260   }
00261   return index_result(idx, flag);
00262 }
00263 
00264 
00265 template<class N, class E>
00266 void graph<N,E>::addEdge(const N & from, const N & to, const E & edge)
00267 {
00268   index_type iFrom = addNode(from);
00269   index_type iTo   = addNode(to);
00270   
00271   adjl_[iFrom].push_back(edge_type(iTo,edges_.size()));
00272   edges_.push_back(edge);
00273 }
00274 
00275 
00276 template<class N, class E>
00277 typename graph<N,E>::edge_range graph<N,E>::edges(index_type nodeIndex)
00278 {
00279   edge_list & edges = adjl_[nodeIndex];
00280   return edge_range(edges.begin(), edges.end());
00281 }
00282 
00283 
00284 template<class N, class E>
00285 typename graph<N,E>::const_edge_range graph<N,E>::edges(index_type nodeIndex) const
00286 {
00287   const edge_list & edges = adjl_[nodeIndex];
00288   return const_edge_range(edges.begin(), edges.end());
00289 }
00290 
00291 
00292 template<class N, class E>
00293 typename graph<N,E>::edge_range graph<N,E>::edges(const N & node)
00294 {
00295   index_result idxResult = nodeIndex(node);
00296   edge_range result(emptyEdges_.begin(),emptyEdges_.end());
00297   if (idxResult.second) {
00298     result = edges(idxResult.first);
00299   }   
00300   return result;
00301 }
00302 
00303 
00304 template<class N, class E>
00305 typename graph<N,E>::const_edge_range graph<N,E>::edges(const N & node) const
00306 {
00307   index_result idxResult = nodeIndex(node);
00308   const_edge_range result(emptyEdges_.begin(),emptyEdges_.end());
00309   if (idxResult.second) {
00310     result = edges(idxResult.first);
00311   }   
00312   return result;
00313 }
00314 
00315 
00316 template<class N, class E>
00317 const N & graph<N,E>::nodeData(const edge_type & edge) const
00318 {
00319   return nodes_[edge.first];
00320 }
00321 
00322 
00323 template<class N, class E>
00324 const N & graph<N,E>::nodeData(index_type i) const
00325 {
00326   return nodes_[i];
00327 }
00328 
00329 
00330 template<class N, class E>
00331 const N & graph<N,E>::nodeData(const const_adj_iterator & it) const
00332 {
00333   return nodes_[it-adjl_.begin()];
00334 }
00335 
00336 template<class N, class E>
00337 void graph<N,E>::findRoots(edge_list & result) const
00338 {
00339   result.clear();
00340       
00341   const_adj_iterator it = begin();   
00342   const_adj_iterator ed = end();
00343   std::vector<bool> rootCandidate(size(), true);
00344   
00345   for (; it != ed; ++it) {
00346     const edge_list & el = *it;
00347     typename edge_list::const_iterator el_it = el.begin();
00348     typename edge_list::const_iterator el_ed = el.end();
00349     for (; el_it != el_ed; ++el_it) {
00350       rootCandidate[el_it->first]=false; 
00351       //el_rt = el_it; // stop at the first encountered candidate!
00352       //std::cout << "graphwalker: found a root candidate = " << g.nodeData(el_rt->first) << std::endl;
00353       //break; 
00354     }
00355   }
00356   std::vector<bool>::size_type v_sz = 0;
00357   std::vector<bool>::size_type v_ed = rootCandidate.size();
00358   for (; v_sz < v_ed; ++v_sz) {
00359     if (rootCandidate[v_sz]) {
00360       //std::cout << "found = " << g.nodeData(v_sz) << std::endl;
00361       result.push_back(edge_type(v_sz,0));    
00362     }
00363   }  
00364 }
00365 
00366 template<class N, class E>
00367 bool graph<N,E>::replace(const N & oldNode, const N & newNode)
00368 {
00369   typename indexer_type::iterator it = indexer_.find(oldNode);
00370   if (it != indexer_.end()) {
00371     index_type oldIndex = it->second;
00372     nodes_[oldIndex]=newNode;
00373     indexer_[newNode]=oldIndex;
00374     indexer_.erase(it);
00375   }  
00376   else throw(oldNode);
00377   return true;   
00378 }
00379 
00380 template<class N, class E>
00381 bool graph<N,E>::replaceEdge(const E & oldEdge, const E & newEdge)
00382 {
00383   typename edge_store::size_type it = 0;
00384   typename edge_store::size_type ed = edges_.size();
00385   bool result = false;
00386   //std::cout << "newedge=" << newEdge << std::endl;
00387   for (; it < ed; ++it) {
00388     //std::cout << "edge=" << edges_[it] << " ";
00389     if ( edges_[it] == oldEdge ) {
00390       //std::cout << "FOUND!" << std::endl;
00391       result = true;
00392       edges_[it] = newEdge;
00393       break;
00394     }
00395   }
00396   //std::cout << std::endl;
00397   return result;
00398 }
00399 
00400 template<class N, class E>
00401 void graph<N,E>::clear()
00402 {
00403   adjl_.clear();
00404   nodes_.clear();
00405   edges_.clear();
00406   indexer_.clear();
00407 }
00408 
00409 template<class N, class E>
00410 void graph<N,E>::dump_graph() const
00411 {
00412   //  std::cout << adjl_ << std::endl;
00413   /*
00414     std::cout << "Nodes and their indices:" << std::endl;
00415     typename indexer_type::const_iterator it = indexer_.begin();
00416     for (; it != indexer_.end(); ++it) {
00417     std::cout << ' ' << it->first << ' ' << it->second << std::endl;
00418     }
00419   */   
00420 }
00421 
00422 
00423 template<class N, class E>
00424 void graph<N,E>::invert(graph<N,E> & g) const
00425 {
00426   adj_list::size_type it = 0;
00427   adj_list::size_type ed = adjl_.size();
00428   // loop over adjacency-list of this graph
00429   for (; it < ed; ++it) {
00430     const edge_list & el = adjl_[it];
00431     edge_list::size_type eit = 0;
00432     edge_list::size_type eed = el.size();
00433     // loop over edges of current node
00434     for (; eit < eed; ++eit) {
00435       const edge_type & e = el[eit];
00436       g.addEdge(nodeData(e.first), nodeData(it), edgeData(e.second));
00437     } 
00438   } 
00439 }
00440 
00441 template<class N, class E>
00442 void graph<N,E>::swap( graph<N, E> & g) { 
00443   adjl_.swap(g.adjl_);
00444   nodes_.swap(g.nodes_);
00445   edges_.swap(g.edges_);
00446   indexer_.swap(g.indexer_);
00447   emptyEdges_.swap(g.emptyEdges_);
00448 }
00449 
00450 template<typename T> std::ostream & operator<<(std::ostream & o, const std::vector< std::vector<std::pair<T,T> > > v)
00451 {
00452   typedef typename std::vector<std::vector<std::pair<T,T> > > v_t;
00453   typedef typename std::vector<std::pair<T,T> > i_t;
00454   
00455   typename v_t::const_iterator it(v.begin()), ed(v.end());
00456   for (; it != ed; ++it) {
00457     typename i_t::const_iterator iit(it->begin()), ied(it->end());
00458     for(; iit != ied; ++iit) {
00459       o << iit->first << ':' << iit->second << std::endl;
00460     }
00461   }
00462   return o;
00463 }
00464 #endif