CMS 3D CMS Logo

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