RDCode: RankAtoms.h Source File

# 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   template <typename T>
    00050   class argless {
    00051   public:
    00052     argless(const T& c) : container(c) {};
    00053     bool operator() (unsigned int v1,unsigned int v2){
    00054       return container[v1]<container[v2];
    00055     }
    00056     const T &container;
    00057   };
    00058
    00059
    00060   //! ranks the entries in a vector
    00061   /*!
    00062     \param vect the vector to rank
    00063     \param res  is used to return the ranks of each entry
    00064   */
    00065   template <typename T>
    00066   void rankVect(const std::vector<T> &vect,INT_VECT &res){
    00067     PRECONDITION(res.size()>=vect.size(),"vector size mismatch");
    00068     unsigned int nEntries = vect.size();
    00069
    00070     std::vector< unsigned int > indices(nEntries);
    00071     for(unsigned int i=0;i<nEntries;++i) indices[i]=i;
    00072     std::sort(indices.begin(),indices.end(),argless< std::vector<T> >(vect) );
    00073
    00074     int currRank=0;
    00075     T lastV = vect[indices[0]];
    00076     for(unsigned int i=0;i<nEntries;++i){
    00077       T v = vect[indices[i]];
    00078       if(v==lastV){
    00079         res[indices[i]] = currRank;
    00080       } else {
    00081         res[indices[i]] = ++currRank;
    00082         lastV = v;
    00083       }
    00084     }
    00085   }
    00086
    00087   //! finds the relative rankings of the entries in \c vals.
    00088   /*!
    00089     \param nAtoms         the number of points in play
    00090     \param vals           the values to be ranked
    00091     \param indicesInPlay  a list containing the indices that
    00092            are being considered (only those entries in \c ranks
    00093            that appear in \c indicesInPlay will be modified)
    00094     \param ranks          the current ranks of entries, this is updated
    00095            with new ranks
    00096   */
    00097   template <typename T>
    00098   void sortAndRankVect(unsigned int nAtoms,
    00099                        const std::vector<T> &vals,
    00100                        const INT_LIST &indicesInPlay,
    00101                        INT_VECT &ranks) {
    00102     // --------------
    00103     //
    00104     // start by getting the internal ranking of the values passed in
    00105     //
    00106     // --------------
    00107     INT_VECT newRanks;
    00108     newRanks.resize(vals.size());
    00109     rankVect(vals,newRanks);
    00110
    00111     // --------------
    00112     //
    00113     // At the end of this operation, fixedRanks will contain the ranks
    00114     // of atoms that are no longer active (-1 for active atoms).
    00115     //
    00116     // --------------
    00117     for(INT_LIST::const_iterator ilCIt=indicesInPlay.begin();
    00118         ilCIt!=indicesInPlay.end();++ilCIt){
    00119       ranks[*ilCIt] = -1;
    00120     }
    00121
    00122 #ifdef VERYVERBOSE_CANON
    00123     std::cout << "new: ";
    00124     debugVect(newRanks);
    00125     std::cout << "fixed: ";
    00126     debugVect(ranks);
    00127 #endif
    00128
    00129     INT_VECT idxVect;
    00130     idxVect.assign(indicesInPlay.begin(),indicesInPlay.end());
    00131
    00132     // -------------
    00133     //
    00134     //  Loop over all the new ranks.  We'll know that we're done
    00135     //  when currNewRank > maxNewRank
    00136     //
    00137     // -------------
    00138     INT_VECT::iterator ivIt;
    00139     int currNewRank= *(std::min_element(newRanks.begin(),newRanks.end()));
    00140     int maxNewRank = *(std::max_element(newRanks.begin(),newRanks.end()));
    00141     while(currNewRank<=maxNewRank){
    00142       //
    00143       // If this rank is already present in ranks, increment
    00144       //  this rank and all new ranks that are higher:
    00145       //
    00146       while(std::find(ranks.begin(),ranks.end(),currNewRank)!=ranks.end()){
    00147         for(ivIt=newRanks.begin();ivIt!=newRanks.end();++ivIt){
    00148           if(*ivIt>=currNewRank)
    00149             *ivIt += 1;
    00150         }
    00151         // increment both thie current rank *and* the maximum new rank
    00152         ++currNewRank;
    00153         ++maxNewRank;
    00154       }
    00155
    00156       //
    00157       //  now grab all entries with this new rank and copy them into
    00158       //  the ranks list
    00159       //
    00160       ivIt=std::find(newRanks.begin(),newRanks.end(),currNewRank);
    00161       while(ivIt!=newRanks.end()){
    00162         int offset=ivIt-newRanks.begin();
    00163         int idx = idxVect[offset];
    00164         ranks[idx] = currNewRank;
    00165         ivIt++;
    00166         ivIt=std::find(ivIt,newRanks.end(),currNewRank);
    00167       }
    00168       ++currNewRank;
    00169     }
    00170   }
    00171 }
    00172 #endif