BALL  1.4.1
simpleMolecularGraph.h
Go to the documentation of this file.
00001 // -*- Mode: C++; tab-width: 2; -*-
00002 // vi: set ts=2:
00003 //
00004 
00005 #ifndef BALL_STRUCTURE_SIMPLEMOLECULARGRAPH_H
00006 #define BALL_STRUCTURE_SIMPLEMOLECULARGRAPH_H
00007 
00008 #ifndef BALL_KERNEL_ATOM_H
00009 # include <BALL/KERNEL/atom.h>
00010 #endif
00011 
00012 #ifndef BALL_KERNEL_BOND_H
00013 # include <BALL/KERNEL/bond.h>
00014 #endif
00015 
00016 #ifndef BALL_STRUCTURE_MOLECULE_H
00017 # include <BALL/KERNEL/molecule.h>
00018 #endif
00019 
00020 #ifndef BALL_STRUCTURE_FRAGMENT_H
00021 # include <BALL/KERNEL/fragment.h>
00022 #endif
00023 
00024 #include <list>
00025 #include <iostream>
00026 #include <algorithm>
00027 
00028 namespace BALL
00029 {
00030   // forward declarations to resolve nasty dependencies
00031   template <typename Node, typename Edge> 
00032   class EdgeItem;
00033 
00034   template <typename Node, typename Edge> 
00035   class TSimpleMolecularGraph;
00036 
00040   template <typename Node, typename Edge>
00041   class NodeItem
00042   {
00043     public:
00047 
00048     typedef NodeItem<Node, Edge> NodeItemType;
00049 
00051     typedef EdgeItem<Node, Edge> EdgeItemType;
00052 
00054     typedef typename std::list<EdgeItem<Node, Edge>*>::iterator Iterator;
00056     typedef typename std::list<EdgeItem<Node, Edge>*>::const_iterator ConstIterator;
00058 
00059     friend class TSimpleMolecularGraph<Node, Edge>;
00060 
00061     NodeItem() ;
00062     NodeItem(const Atom& atom) ;
00063 
00064     Node& getData() ;
00065     const Node& getData() const ;
00066     void setData(const Node& data) ;
00067 
00068     const Atom* getAtom() const ;
00069     Atom* getAtom() ;
00070 
00071     Iterator begin() ;
00072     ConstIterator begin() const ;
00073     Iterator end() ;
00074     ConstIterator end() const ;
00075 
00076     Size getDegree() const ;
00077 
00078     bool operator == (const NodeItem& item) const ;
00079     bool operator != (const NodeItem& item) const ;
00080 
00081     protected:
00082 
00083     void deleteEdge_(EdgeItemType* item)
00084       ;
00085 
00086     Node  data_;
00087     Atom* atom_;
00088     std::list<EdgeItemType*> adjacent_edges_;
00089   };
00090 
00091 
00092   template <typename Node, typename Edge>
00093   class EdgeItem
00094   {
00095     public:
00096     typedef NodeItem<Node, Edge> NodeItemType;
00097     typedef EdgeItem<Node, Edge> EdgeItemType;
00098     typedef typename std::list<NodeItem<Node, Edge>*>::iterator Iterator;
00099     typedef typename std::list<NodeItem<Node, Edge>*>::const_iterator ConstIterator;
00100 
00101     EdgeItem() 
00102       : bond_(0), source_(0), target_(0)
00103     {}
00104 
00105     EdgeItem(const Bond& bond);
00106     EdgeItem(const Bond& bond, NodeItemType* source, NodeItemType* target);
00107 
00108     NodeItemType& getSource() {return *source_;}
00109     NodeItemType& getTarget() {return *target_;}
00110     const NodeItemType& getSource() const {return *source_;}
00111     const NodeItemType& getTarget() const {return *target_;}
00112     
00113     Node& getData() {return data_;}
00114     const Node& getData() const {return data_;}
00115     void setData(const Edge& data) { data_ = data; };
00116 
00117     Bond* getBond() { return bond_; }
00118     const Bond* getBond() const { return bond_; }
00119 
00120     bool operator == (const EdgeItem& item) const { return (bond_ == item.bond_); }
00121     bool operator != (const EdgeItem& item) const { return (bond_ != item.bond_); }
00122 
00123     protected:
00124     Edge  data_;
00125     Bond* bond_;
00126     NodeItemType* source_;
00127     NodeItemType* target_;
00128   };
00129 
00130   template <typename Node, typename Edge>
00131   EdgeItem<Node, Edge>::EdgeItem(const Bond& bond)
00132     : bond_(const_cast<Bond*>(&bond))
00133   {
00134   }
00135 
00136   template <typename Node, typename Edge>
00137   EdgeItem<Node, Edge>::EdgeItem(const Bond& bond, NodeItem<Node, Edge>* first, NodeItem<Node, Edge>* second)
00138     : bond_(const_cast<Bond*>(&bond)),
00139       source_(first),
00140       target_(second)
00141   {
00142   }
00143 
00144   template <typename Node, typename Edge>
00145   class TSimpleMolecularGraph
00146   {
00147     public:
00148     typedef NodeItem<Node, Edge> NodeItemType;
00149     typedef EdgeItem<Node, Edge> EdgeItemType;
00150     typedef typename std::list<NodeItemType>::iterator NodeIterator;
00151     typedef typename std::list<NodeItemType>::const_iterator NodeConstIterator;
00152     typedef typename std::list<EdgeItemType>::iterator EdgeIterator;
00153     typedef typename std::list<EdgeItemType>::const_iterator EdgeConstIterator;
00154 
00155     TSimpleMolecularGraph() ;
00156     TSimpleMolecularGraph(const Molecule& molecule) ;
00157 
00158     bool newNode(const Atom& atom) ;
00159     bool newEdge(const Bond& bond) ;
00160 
00161     bool deleteNode(NodeItemType& node);
00162     bool deleteEdge(EdgeItemType& edge);
00163         
00164     bool deleteNode(const Atom& atom);
00165     bool deleteEdge(const Bond& bond);
00166         
00167     NodeIterator beginNode() { return nodes_.begin(); }
00168     NodeConstIterator beginNode() const { return nodes_.begin(); }
00169     EdgeIterator beginEdge() { return edges_.begin(); }
00170     EdgeConstIterator beginEdge() const { return edges_.begin(); }
00171     NodeIterator endNode() { return nodes_.end(); }
00172     NodeConstIterator endNode() const { return nodes_.end(); }
00173     EdgeIterator endEdge() { return edges_.end(); }
00174     EdgeConstIterator endEdge() const { return edges_.end(); }
00175     
00176     bool has(const Atom& atom) const { return atom_to_node_.has(const_cast<Atom*>(&atom)); }
00177     bool has(const Bond& bond) const { return bond_to_edge_.has(const_cast<Bond*>(&bond)); }
00178 
00179     NodeItemType& getNode(Position index) { return nodes_[index]; };
00180     const NodeItemType& getNode(Position index) const { return nodes_[index]; };
00181     EdgeItemType& getEdge(Position index) { return edges_[index]; };
00182     const EdgeItemType& getEdge(Position index) const { return edges_[index]; };
00183 
00186     Size getNumberOfNodes() const ;
00187 
00190     Size getNumberOfEdges() const ;
00191 
00192     protected:
00193     std::list<NodeItemType> nodes_;
00194     std::list<EdgeItemType> edges_;
00195     HashMap<Atom*, NodeItemType*> atom_to_node_;
00196     HashMap<Bond*, EdgeItemType*> bond_to_edge_;
00197   };
00198 
00202   typedef TSimpleMolecularGraph<Index, Index> SimpleMolecularGraph;
00203 
00204   template <typename Node, typename Edge>
00205   TSimpleMolecularGraph<Node, Edge>::TSimpleMolecularGraph()
00206       
00207     : nodes_(),
00208       edges_(),
00209       atom_to_node_(),
00210       bond_to_edge_()
00211   {
00212   }
00213 
00214   template <typename Node, typename Edge>
00215   TSimpleMolecularGraph<Node, Edge>::TSimpleMolecularGraph(const Molecule& molecule)
00216       
00217     : nodes_(),
00218       edges_(),
00219       atom_to_node_(),
00220       bond_to_edge_()
00221   {
00222     AtomConstIterator ai = molecule.beginAtom();
00223     Atom::BondConstIterator bi;
00224     for (; +ai; ++ai)
00225     {
00226       newNode(*ai);
00227     }
00228     for (ai = molecule.beginAtom(); +ai; ++ai)
00229     {
00230       for (bi = ai->beginBond(); +bi; ++bi)
00231       {
00232         if (bi->getFirstAtom() == &*ai)
00233         {
00234           newEdge(*bi);
00235         }
00236       }
00237     }
00238   }
00239 
00240   template <typename Node, typename Edge>
00241   bool TSimpleMolecularGraph<Node, Edge>::newNode(const Atom& atom)
00242     
00243   {
00244     Atom* atom_ptr = const_cast<Atom*>(&atom);
00245 
00246     if (atom_to_node_.has(atom_ptr))
00247     {
00248       return false;
00249     }
00250 
00251     nodes_.push_back(NodeItemType(atom));
00252     atom_to_node_.insert(std::pair<Atom*, NodeItemType*>(atom_ptr, &(nodes_.back())));
00253 
00254     return true;
00255   }
00256 
00257   template <typename Node, typename Edge>
00258   bool TSimpleMolecularGraph<Node, Edge>::newEdge(const Bond& bond)
00259     
00260   {
00261     // Create convenience aliases for atoms.
00262     Atom* first = const_cast<Atom*>(bond.getFirstAtom());
00263     Atom* second = const_cast<Atom*>(bond.getSecondAtom()); 
00264 
00265     // Make sure we have atoms/nodes for this bond/edge.
00266     if (!atom_to_node_.has(first) || !atom_to_node_.has(second))
00267     {
00268       return false;
00269     }
00270 
00271     // Make sure not to create the same edge twice.
00272     if (bond_to_edge_.has(const_cast<Bond*>(&bond)))
00273     {
00274       return true;
00275     }
00276     
00277     // Create the new edge und add it to the hash map relating
00278     // the bond to the edge.
00279     NodeItemType* first_item = atom_to_node_[first];
00280     NodeItemType* second_item = atom_to_node_[second];
00281     edges_.push_back(EdgeItemType(bond, first_item, second_item));
00282     bond_to_edge_.insert(std::pair<Bond*, EdgeItemType*>(const_cast<Bond*>(&bond), &edges_.back()));
00283     first_item->adjacent_edges_.push_back(&edges_.back());
00284     second_item->adjacent_edges_.push_back(&edges_.back());
00285 
00286     return true;
00287   }
00288 
00289   template <typename Node, typename Edge>
00290   std::ostream& operator << (std::ostream& os, const TSimpleMolecularGraph<Node, Edge>& G)
00291   {   
00292     os << "Nodes:" << std::endl;
00293 
00294     typename TSimpleMolecularGraph<Node, Edge>::NodeConstIterator node = G.beginNode();
00295     Size count = 0;
00296     for (; node != G.endNode(); ++node)
00297     {
00298       os << count++ << ": " << node->getAtom()->getFullName() << " [" << node->getDegree() << "] '" << node->getAtom() << "'" << std::endl;     
00299     }
00300 
00301     os << "Edges:" << std::endl;  
00302 
00303     typename TSimpleMolecularGraph<Node, Edge>::EdgeConstIterator edge = G.beginEdge();
00304     count = 0;
00305     for (; edge != G.endEdge(); ++edge)
00306     {
00307       os << count++ << ": " << edge->getSource().getAtom() << "-" << edge->getTarget().getAtom() << " '" << edge->getBond() << "'" << std::endl;
00308     }
00309 
00310     return os;
00311   }
00312 
00313   template <typename Node, typename Edge>
00314   bool TSimpleMolecularGraph<Node, Edge>::deleteNode(const Atom& atom)
00315   {
00316     if (!atom_to_node_.has(const_cast<Atom*>(&atom)))
00317     {
00318       return false;
00319     }
00320     
00321     return deleteNode(*atom_to_node_[const_cast<Atom*>(&atom)]);
00322   }
00323 
00324   template <typename Node, typename Edge>
00325   bool TSimpleMolecularGraph<Node, Edge>::deleteEdge(const Bond& bond)
00326   {
00327     if (!bond_to_edge_.has(const_cast<Bond*>(&bond)))
00328     {
00329       return false;
00330     }
00331     
00332     return deleteEdge(*bond_to_edge_[const_cast<Bond*>(&bond)]);
00333   }
00334 
00335   template <typename Node, typename Edge>
00336   bool TSimpleMolecularGraph<Node, Edge>::deleteNode(typename TSimpleMolecularGraph<Node, Edge>::NodeItemType& node)
00337   {
00338     NodeIterator node_it = std::find(nodes_.begin(), nodes_.end(), node);
00339     if (node_it == nodes_.end())
00340     {
00341       return false;
00342     }
00343 
00344     bool remove = true;
00345     while (remove)
00346     {
00347       remove = false;
00348       typename NodeItemType::Iterator edge(node.begin());
00349       for (; edge != node.end(); ++edge)
00350       {
00351         deleteEdge(**edge);
00352         break;
00353       }
00354     }
00355 
00356     atom_to_node_.erase(node_it->getAtom());
00357     nodes_.erase(node_it);
00358   
00359     return true;
00360   }
00361 
00362   template <typename Node, typename Edge>
00363   bool TSimpleMolecularGraph<Node, Edge>::deleteEdge(typename TSimpleMolecularGraph<Node, Edge>::EdgeItemType& edge)
00364   {
00365     typename std::list<EdgeItemType>::iterator edge_it = std::find(edges_.begin(), edges_.end(), edge);
00366     if (edge_it == edges_.end())
00367     {
00368       return false;
00369     }
00370     edge.getSource().deleteEdge_(&edge);
00371     edge.getTarget().deleteEdge_(&edge);
00372     bond_to_edge_.erase(edge_it->getBond());
00373     edges_.erase(edge_it);
00374     
00375     return true;
00376   }
00377 
00378 
00379   template <typename Node, typename Edge>
00380   NodeItem<Node, Edge>::NodeItem()
00381     
00382     : atom_(0)
00383   {
00384   }
00385 
00386   template <typename Node, typename Edge>
00387   NodeItem<Node, Edge>::NodeItem(const Atom& atom)
00388     
00389     : atom_(const_cast<Atom*>(&atom))
00390   {
00391   }
00392 
00393   template <typename Node, typename Edge>
00394   Node& NodeItem<Node, Edge>::getData()
00395     
00396   {
00397     return data_;
00398   }
00399 
00400   template <typename Node, typename Edge>
00401   const Node& NodeItem<Node, Edge>::getData() const 
00402     
00403   { 
00404     return data_;
00405   }
00406 
00407 
00408   template <typename Node, typename Edge>
00409   void NodeItem<Node, Edge>::setData(const Node& data) 
00410     
00411   { 
00412     data_ = data; 
00413   }
00414 
00415   
00416   template <typename Node, typename Edge>
00417   const Atom* NodeItem<Node, Edge>::getAtom() const 
00418     
00419   { 
00420     return atom_;
00421   }
00422 
00423   template <typename Node, typename Edge>
00424   Atom* NodeItem<Node, Edge>::getAtom() 
00425     
00426   { 
00427     return atom_;
00428   }
00429 
00430   template <typename Node, typename Edge>
00431   typename NodeItem<Node, Edge>::Iterator NodeItem<Node, Edge>::begin() 
00432     
00433   { 
00434     return adjacent_edges_.begin(); 
00435   }
00436   
00437   template <typename Node, typename Edge>
00438   typename NodeItem<Node, Edge>::ConstIterator NodeItem<Node, Edge>::begin() const 
00439     
00440   { 
00441     return adjacent_edges_.begin(); 
00442   }
00443 
00444   template <typename Node, typename Edge>
00445   typename NodeItem<Node, Edge>::Iterator NodeItem<Node, Edge>::end() 
00446     
00447   { 
00448     return adjacent_edges_.end(); 
00449   }
00450 
00451   template <typename Node, typename Edge>
00452   typename NodeItem<Node, Edge>::ConstIterator NodeItem<Node, Edge>::end() const    
00453     
00454   { 
00455     return adjacent_edges_.end(); 
00456   }
00457 
00458   template <typename Node, typename Edge>
00459   Size NodeItem<Node, Edge>::getDegree() const 
00460     
00461   { 
00462     return (Size)adjacent_edges_.size(); 
00463   }
00464 
00465   template <typename Node, typename Edge>
00466   bool NodeItem<Node, Edge>::operator == (const NodeItem& item) const 
00467     
00468   { 
00469     return (atom_ == item.atom_); 
00470   }
00471 
00472   template <typename Node, typename Edge>
00473   bool NodeItem<Node, Edge>::operator != (const NodeItem& item) const 
00474     
00475   { 
00476     return (atom_ != item.atom_); 
00477   }
00478 
00479   template <typename Node, typename Edge>
00480   void NodeItem<Node, Edge>::deleteEdge_(EdgeItemType* item)
00481     
00482   {
00483     Iterator it(std::find(adjacent_edges_.begin(), adjacent_edges_.end(), item));
00484     if (it != adjacent_edges_.end())
00485     {
00486       adjacent_edges_.erase(it);
00487     }
00488   }
00489 
00490   template <typename Node, typename Edge>
00491   BALL_INLINE
00492   Size TSimpleMolecularGraph<Node, Edge>::getNumberOfNodes() const
00493     
00494   {
00495     return nodes_.size();
00496   }
00497 
00498   template <typename Node, typename Edge>
00499   BALL_INLINE
00500   Size TSimpleMolecularGraph<Node, Edge>::getNumberOfEdges() const
00501     
00502   {
00503     return edges_.size();
00504   }
00505 
00506   
00507 } // namespace BALL
00508 
00509 #endif // BALL_STRUCTURE_MOLECULARGRAPH_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines