RankAtoms.h

Go to the documentation of this file.
00001 //
00002 //  Copyright (C) 2004-2008 Greg Landrum and Rational Discovery LLC
00003 //
00004 //   @@ All Rights Reserved  @@
00005 //
00006 
00007 //! \file RankAtoms.h
00008 /*!
00009     \brief Utility functionality used by atom rankers.
00010 */
00011 #ifndef _RD_RANKATOMS_H_
00012 #define _RD_RANKATOMS_H_
00013 
00014 #include <queue>
00015 #include <vector>
00016 #include <list>
00017 #include <algorithm>
00018 
00019 namespace RankAtoms {
00020   typedef std::vector<int> INT_VECT;
00021   typedef std::list<int> INT_LIST;
00022 
00023   //! utility function for ranking atoms
00024   void updateInPlayIndices(const INT_VECT &ranks,INT_LIST &indicesInPlay);
00025 
00026   //! returns the count of unique items in an std::vector
00027   template <typename T>
00028   unsigned int countClasses(const std::vector<T> &vect){
00029     std::vector<T> sortedVect = vect;
00030     std::sort(sortedVect.begin(),sortedVect.end(),std::less<T>());
00031     typename std::vector<T>::iterator newEnd=std::unique(sortedVect.begin(),sortedVect.end());
00032     return newEnd-sortedVect.begin();
00033   }
00034 
00035   //! functor for implementing > on two std::pairs.  The first entries are compared.
00036   template <typename T>
00037   struct pairGTFunctor {
00038     bool operator() (const std::pair<T,int> &v1,const std::pair<T,int> &v2){
00039       return v1.first > v2.first;
00040     }
00041   };
00042 
00043   //! function for implementing < on two std::pairs.  The first entries are compared.
00044   template <typename T>
00045   bool pairLess(const std::pair<T,int> &v1,const std::pair<T,int> &v2){
00046     return v1.first < v2.first;
00047   }
00048 
00049   //! ranks the entries in a vector
00050   /*!
00051     \param vect the vector to rank
00052     \param res  is used to return the ranks of each entry
00053   */
00054   template <typename T>  
00055   void rankVect(const std::vector<T> &vect,INT_VECT &res){
00056     PRECONDITION(res.size()>=vect.size(),"vector size mismatch");
00057     unsigned int nEntries = vect.size();
00058 
00059     std::vector< std::pair<T,int> > sortedVect;
00060     sortedVect.resize(nEntries);
00061     for(unsigned int i=0;i<nEntries;++i){
00062       sortedVect[i]=std::make_pair(vect[i],i);
00063     }
00064     std::sort(sortedVect.begin(),sortedVect.end(),pairLess<T>);
00065     int currRank=0;
00066     T lastV = sortedVect[0].first;
00067     for(unsigned int i=0;i<nEntries;++i){
00068       const std::pair<T,int> &p = sortedVect[i];
00069       if(p.first==lastV){
00070         res[p.second] = currRank;
00071       } else {
00072         res[p.second] = ++currRank;
00073         lastV = p.first;
00074       }
00075     }
00076   }    
00077 
00078   //! finds the relative rankings of the entries in \c vals.
00079   /*!
00080     \param nAtoms         the number of points in play
00081     \param vals           the values to be ranked
00082     \param indicesInPlay  a list containing the indices that
00083            are being considered (only those entries in \c ranks
00084            that appear in \c indicesInPlay will be modified)
00085     \param ranks          the current ranks of entries, this is updated
00086            with new ranks
00087   */
00088   template <typename T>
00089   void sortAndRankVect(unsigned int nAtoms,
00090                        const std::vector<T> &vals,
00091                        const INT_LIST &indicesInPlay,
00092                        INT_VECT &ranks) {
00093     // --------------
00094     //
00095     // start by getting the internal ranking of the values passed in
00096     //
00097     // --------------
00098     INT_VECT newRanks;
00099     newRanks.resize(vals.size());
00100     rankVect(vals,newRanks);
00101 
00102     // --------------
00103     //  
00104     // At the end of this operation, fixedRanks will contain the ranks
00105     // of atoms that are no longer active (-1 for active atoms).
00106     //
00107     // --------------
00108     for(INT_LIST::const_iterator ilCIt=indicesInPlay.begin();
00109         ilCIt!=indicesInPlay.end();++ilCIt){
00110       ranks[*ilCIt] = -1;
00111     }
00112 
00113 #ifdef VERYVERBOSE_CANON
00114     std::cout << "new: ";
00115     debugVect(newRanks);
00116     std::cout << "fixed: ";
00117     debugVect(ranks);
00118 #endif
00119 
00120     INT_VECT idxVect;
00121     idxVect.assign(indicesInPlay.begin(),indicesInPlay.end());
00122 
00123     // -------------
00124     //
00125     //  Loop over all the new ranks.  We'll know that we're done
00126     //  when currNewRank > maxNewRank
00127     //
00128     // -------------
00129     INT_VECT::iterator ivIt;
00130     int currNewRank= *(std::min_element(newRanks.begin(),newRanks.end()));
00131     int maxNewRank = *(std::max_element(newRanks.begin(),newRanks.end()));
00132     while(currNewRank<=maxNewRank){
00133       //
00134       // If this rank is already present in ranks, increment
00135       //  this rank and all new ranks that are higher:
00136       //
00137       while(std::find(ranks.begin(),ranks.end(),currNewRank)!=ranks.end()){
00138         for(ivIt=newRanks.begin();ivIt!=newRanks.end();++ivIt){
00139           if(*ivIt>=currNewRank)
00140             *ivIt += 1;
00141         }
00142         // increment both thie current rank *and* the maximum new rank
00143         ++currNewRank;
00144         ++maxNewRank;
00145       }
00146 
00147       //
00148       //  now grab all entries with this new rank and copy them into
00149       //  the ranks list
00150       //
00151       ivIt=std::find(newRanks.begin(),newRanks.end(),currNewRank);
00152       while(ivIt!=newRanks.end()){
00153         int offset=ivIt-newRanks.begin();
00154         int idx = idxVect[offset];
00155         ranks[idx] = currNewRank;
00156         ivIt++;
00157         ivIt=std::find(ivIt,newRanks.end(),currNewRank);
00158       }
00159       ++currNewRank;
00160     }
00161   }
00162 }
00163 #endif

Generated on Sat May 24 08:36:32 2008 for RDCode by  doxygen 1.5.3