Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

buildable_atom_algorithms.h

Go to the documentation of this file.
00001 // -*- mode: c++; -*-
00002 //
00003 //The Biomolecule Toolkit (BTK) is a C++ library for use in the
00004 //modeling, analysis, and design of biological macromolecules.
00005 //Copyright (C) 2004, Christopher Saunders <ctsa@users.sourceforge.net>
00006 //
00007 //This program is free software; you can redistribute it and/or modify
00008 //it under the terms of the GNU Lesser General Public License as published
00009 //by the Free Software Foundation; either version 2.1 of the License, or (at
00010 //your option) any later version.
00011 //
00012 //This program is distributed in the hope that it will be useful,  but
00013 //WITHOUT ANY WARRANTY; without even the implied warranty of
00014 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015 //Lesser General Public License for more details. 
00016 //
00017 //You should have received a copy of the GNU Lesser General Public License 
00018 //along with this program; if not, write to the Free Software Foundation, 
00019 //Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00020 
00025 
00026 #ifndef BUILDABLE_ATOM_ALGORITHMS_H
00027 #define BUILDABLE_ATOM_ALGORITHMS_H
00028 
00029 
00030 #include "atom_algorithms.h"
00031 #include "buildable_atom.h"
00032 #include "linear_algebra.h"
00033 
00034 #include <boost/concept_check.hpp>
00035 
00036 #include <iterator>
00037 #include <queue>
00038 #include <set>
00039 
00040 
00041 namespace BTK {
00042 
00045 
00046 
00049   template <typename AtomType>
00050   void 
00051   add_bond(AtomType& first,
00052            AtomType& last);
00053 
00058   template <typename AtomType>
00059   unsigned
00060   bond_distance_4(AtomType& a1, 
00061                   AtomType& a2);
00062 
00068   template <typename AtomIterator>
00069   void
00070   build(AtomIterator first,
00071         AtomIterator last);
00072 
00080   // implementation: runs bredth-first search to find the closest
00081   // buildable atom to build off of, and tries to rebuild atoms back
00082   // toward the target atom, until target atom becomes buildable
00083   //
00084   template <typename AtomType>
00085   void
00086   build_atom(AtomType& a);
00087 
00088 #if 0
00093   template <typename AtomIterator>
00094   void
00095   conservative_build(AtomIterator first,
00096                      AtomIterator last);
00097 #endif
00098 
00104   template <typename AtomType>
00105   void 
00106   restricted_rotate(AtomType& start,
00107                     AtomType& boundary,
00108                     double delta_angle);
00109 
00117   template <typename AtomType, typename UnaryFunction>
00118   UnaryFunction
00119   for_each_buildable_atom(AtomType& start, 
00120                           AtomType& boundary, 
00121                           UnaryFunction func);
00122 
00124   
00125 } // namespace BTK  
00126 
00127 
00128 
00129 
00130 
00131 
00133 // implementation
00134 //
00135 
00136 namespace BTK{
00137   namespace Internal{
00138     template <typename AtomType, typename UnaryFunction>
00139     void
00140     for_each_buildable_atom_iter(AtomType& a, 
00141                                  std::set<AtomType*>& visited, 
00142                                  UnaryFunction func);
00143 
00144     template <typename AtomType>
00145     void
00146     cache_bond_distance_4(AtomType& a);
00147 
00148     template <typename AtomType>
00149     void
00150     cache_bond_distance_4_iter(AtomType& start,
00151                                AtomType& boundary,
00152                                AtomType& a1,
00153                                unsigned dist);
00154 
00155     template <typename AtomType>
00156     bool
00157     build_atom_iter(std::set<AtomType*>& visited,
00158                     std::queue<AtomType*>& bfs_queue,
00159                     std::map<AtomType*,AtomType*>& traceback);
00160 
00161     template <typename AtomType>
00162     void
00163     build_atom_traceback(AtomType& a,
00164                          std::map<AtomType*,AtomType*>& traceback);
00165   }
00166 }
00167 
00168 
00169 
00170 template <typename AtomType>
00171 void 
00172 BTK::
00173 add_bond(AtomType& first,
00174          AtomType& last)
00175 {
00176   first.add_adjacent(last);
00177   last.add_adjacent(first);
00178 
00181 }
00182 
00183 
00184 template <typename AtomType>
00185 unsigned
00186 BTK::
00187 bond_distance_4(AtomType& a1, 
00188                 AtomType& a2)
00189 {
00190   // requires BuildableAtom
00191   boost::function_requires<boost::ConvertibleConcept<AtomType,BuildableAtom> >();
00192 
00193   AtomType* ap1 = &a1;
00194   AtomType* ap2 = &a2;
00195   if(ap1 == ap2) return 0;
00196   else if(ap1 > ap2) std::swap(ap1,ap2);
00197 
00198   if(! ap1->is_bond_distance_cached()) {
00199     Internal::cache_bond_distance_4(*ap1);
00200     ap1->set_is_bond_distance_cached(true);
00201   }
00202 
00203   return ap1->bond_distance_4(*ap2);
00204 }
00205 
00206 template <typename AtomIterator>
00207 void
00208 BTK::
00209 build(AtomIterator first,
00210       AtomIterator last)
00211 {
00212   for(;first!=last;++first){
00213     build_atom(*first);
00214   }
00215 }
00216 
00217 // run bfs search for built atoms to build atom a from
00218 template <typename AtomType>
00219 void
00220 BTK::
00221 build_atom(AtomType& a)
00222 {
00223   // bfs search for closest built atom
00224   if(a.build()) return;
00225 
00226   std::set<AtomType*> visited;
00227   std::queue<AtomType*> bfs_queue;
00228   std::map<AtomType*,AtomType*> traceback;
00229 
00230   visited.insert(&a);
00231   bfs_queue.push(&a);
00232   traceback[&a] = 0;
00233 
00234   bool result = Internal::build_atom_iter(visited,bfs_queue,traceback);
00235 
00236   // if nothing found to build off of, then bootstrap
00237   if(!result) a.boot_build();
00238 }
00239 
00240 
00241 template <typename AtomType>
00242 void 
00243 BTK::
00244 restricted_rotate(AtomType& start,
00245                   AtomType& boundary,
00246                   double delta_angle)
00247 {
00248   boost::function_requires<boost::ConvertibleConcept<AtomType,BuildableAtom> >();
00249 
00250   BTKMatrix rot_matrix( create_rotation_matrix(start.position()-boundary.position(),delta_angle) );
00251   BTKVector rot_offset( prec_prod(rot_matrix,-boundary.position())+boundary.position() ); 
00252   
00253   for_each_buildable_atom(start,boundary,atom_rotator<AtomType>(rot_matrix,rot_offset));
00254 }
00255 
00256 
00257 template <typename AtomType, typename UnaryFunction>
00258 UnaryFunction
00259 BTK::
00260 for_each_buildable_atom(AtomType& start, 
00261                         AtomType& boundary, 
00262                         UnaryFunction func)
00263 {
00264   boost::function_requires<boost::ConvertibleConcept<AtomType,BuildableAtom> >();
00265 
00266   std::set<AtomType*> visited;
00267   
00268   visited.insert(&start);
00269   visited.insert(&boundary);
00270   Internal::for_each_buildable_atom_iter(start,visited,func);
00271   return func;
00272 }
00273 
00274 
00275 
00276 
00277 
00279 // private implementation
00280 //
00281 template <typename AtomType, typename UnaryFunction>
00282 void
00283 BTK::Internal::
00284 for_each_buildable_atom_iter(AtomType& a,
00285                              std::set<AtomType*>& visited,
00286                              UnaryFunction func)
00287 {
00288   typename BuildableAtom::adjacent_iterator ai=a.adjacent_begin(), ai_end=a.adjacent_end();
00289 
00290   for (;ai!=ai_end;ai++){
00291     if( visited.find(static_cast<AtomType*>(*ai)) == visited.end() ){
00292       visited.insert(static_cast<AtomType*>(*ai));
00293       func(*static_cast<AtomType*>(*ai));
00294       for_each_buildable_atom_iter(*static_cast<AtomType*>(*ai),visited,func);
00295     }
00296   }
00297 }
00298 
00299 template <typename AtomType>
00300 void
00301 BTK::Internal::
00302 cache_bond_distance_4(AtomType& a)
00303 {
00306   //
00307   //  std::cerr << "cached_bond_dist atom: " << a.position() << " " << ELEMENT::name(a.element()) << std::endl;
00308   cache_bond_distance_4_iter(a,a,a,0);
00309 }
00310 
00311 
00312 template <typename AtomType>
00313 void
00314 BTK::Internal::
00315 cache_bond_distance_4_iter(AtomType& start,
00316                            AtomType& boundary,
00317                            AtomType& a1,
00318                            unsigned dist)
00319 {
00320   dist += 1;
00321 
00322   BuildableAtom::const_adjacent_iterator ai=start.adjacent_begin(),ai_end=start.adjacent_end();
00323   for (;ai!=ai_end;++ai){
00324     AtomType& a2 = *static_cast<AtomType*>(*ai);
00325     if(&a2 == &boundary) continue;
00326 
00327     AtomType* ap1 = &a1;
00328     AtomType* ap2 = &a2;
00329     if( ap1 > ap2 ) std::swap(ap1,ap2);
00330     if( dist < ap1->bond_distance_4(*ap2) ){
00331       ap1->set_bond_distance_4(*ap2,dist);
00332     }
00333     if( dist < 4 ) cache_bond_distance_4_iter(a2,start,a1,dist);
00334   }
00335 }
00336 
00337 
00338 template <typename AtomType>
00339 bool
00340 BTK::Internal::
00341 build_atom_iter(std::set<AtomType*>& visited,
00342                 std::queue<AtomType*>& bfs_queue,
00343                 std::map<AtomType*,AtomType*>& traceback)
00344 {
00345   AtomType& a = *(bfs_queue.front());
00346   bfs_queue.pop();
00347   bool are_any_built = false;
00348 
00349   BuildableAtom::adjacent_iterator ai=a.adjacent_begin(),ai_end=a.adjacent_end();
00350   for(;ai!=ai_end;++ai){
00351     AtomType& a2 = *static_cast<AtomType*>(*ai);
00352 
00353     if(visited.find(&a2) != visited.end()) continue;
00354 
00355     if(!a2.is_built()) {
00356       if(a2.build()) {
00357         // succesful new build, now use traceback to build back
00358         // towards original goal, starting a new bfs build search on
00359         // any atoms that cause trouble along the way
00360         //
00361         build_atom_traceback(a,traceback);
00362         return true;
00363       }
00364     } else {
00365       are_any_built = true;
00366     }
00367  
00368     traceback[&a2] = &a;
00369     visited.insert(&a2);
00370     bfs_queue.push(&a2);
00371   }
00372 
00373   while(! bfs_queue.empty() ){
00374     bool result = build_atom_iter(visited,bfs_queue,traceback);
00375     if(result) are_any_built = true;
00376   }
00377   return are_any_built;
00378 }
00379 
00380 
00381 template <typename AtomType>
00382 void
00383 BTK::Internal::
00384 build_atom_traceback(AtomType& a,
00385                      std::map<AtomType*,AtomType*>& traceback)
00386 {
00387   if(!a.build()){
00388     // start a totally fresh bfs on a
00389     build_atom(a);
00390     if(!a.is_built()) return;
00391   }
00392   AtomType* a2 = traceback[&a];
00393   if(!a2) return;
00394   build_atom_traceback(*a2,traceback);
00395 }
00396 
00397 
00398 
00399 #endif
00400 
00401 

Generated on Wed Apr 14 00:43:16 2004 for BTK by doxygen 1.3.6