00001
00002
00003
00004
00005
00006 #ifndef __RD_MAXMINPICKER_H__
00007 #define __RD_MAXMINPICKER_H__
00008
00009 #include <RDGeneral/types.h>
00010 #include <RDGeneral/utils.h>
00011 #include <RDGeneral/Invariant.h>
00012 #include <RDGeneral/RDLog.h>
00013 #include <RDBoost/Exceptions.h>
00014 #include <cstdlib>
00015 #include "DistPicker.h"
00016
00017 namespace RDPickers {
00018
00019 namespace {
00020 class distmatFunctor{
00021 public:
00022 distmatFunctor(const double *distMat) : dp_distMat(distMat) {};
00023 double operator()(unsigned int i,unsigned int j) {
00024 return getDistFromLTM(this->dp_distMat,i,j);
00025 }
00026 private:
00027 const double *dp_distMat;
00028 };
00029 }
00030
00031
00032
00033
00034
00035
00036 class MaxMinPicker : public DistPicker {
00037 public:
00038
00039
00040
00041 MaxMinPicker() {};
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 template <typename T>
00056 RDKit::INT_VECT lazyPick(T &func,
00057 unsigned int poolSize, unsigned int pickSize,
00058 RDKit::INT_VECT firstpicks=RDKit::INT_VECT()) const;
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 RDKit::INT_VECT pick(const double *distMat,
00090 unsigned int poolSize, unsigned int pickSize,
00091 RDKit::INT_VECT firstPicks) const {
00092 CHECK_INVARIANT(distMat, "Invalid Distance Matrix");
00093 if(poolSize<pickSize)
00094 throw ValueErrorException("pickSize cannot be larger than the poolSize");
00095 distmatFunctor functor(distMat);
00096 return this->lazyPick(functor,poolSize,pickSize,firstPicks);
00097 }
00098
00099
00100 RDKit::INT_VECT pick(const double *distMat,
00101 unsigned int poolSize, unsigned int pickSize) const {
00102 RDKit::INT_VECT iv;
00103 return pick(distMat,poolSize,pickSize,iv);
00104 }
00105
00106
00107
00108 };
00109
00110 template <typename T>
00111 RDKit::INT_VECT MaxMinPicker::lazyPick(T &func,
00112 unsigned int poolSize, unsigned int pickSize,
00113 RDKit::INT_VECT firstPicks) const {
00114 if(poolSize<pickSize)
00115 throw ValueErrorException("pickSize cannot be larger than the poolSize");
00116
00117 RDKit::INT_LIST pool;
00118
00119 RDKit::INT_VECT picks;
00120 picks.reserve(pickSize);
00121 unsigned int pick=0;
00122
00123
00124 for (unsigned int i = 0; i < poolSize; i++) {
00125 pool.push_back(i);
00126 }
00127
00128
00129 if(!firstPicks.size()){
00130 pick = rand()%poolSize;
00131
00132 picks.push_back(pick);
00133
00134 pool.remove(pick);
00135 } else{
00136 for(RDKit::INT_VECT::const_iterator pIdx=firstPicks.begin();
00137 pIdx!=firstPicks.end();++pIdx){
00138 pick = static_cast<unsigned int>(*pIdx);
00139 if(pick>=poolSize)
00140 throw ValueErrorException("pick index was larger than the poolSize");
00141 picks.push_back(pick);
00142 pool.remove(pick);
00143 }
00144 }
00145
00146 while (picks.size() < pickSize) {
00147 double maxOFmin = -1.0;
00148 RDKit::INT_LIST_I plri=pool.end();
00149 for(RDKit::INT_LIST_I pli=pool.begin();
00150 pli!=pool.end(); ++pli){
00151 unsigned int poolIdx = (*pli);
00152 double minTOi = RDKit::MAX_DOUBLE;
00153 for (RDKit::INT_VECT_CI pi = picks.begin();
00154 pi != picks.end(); ++pi) {
00155 unsigned int pickIdx = (*pi);
00156 CHECK_INVARIANT(poolIdx!=pickIdx,"");
00157 double dist = func(poolIdx,pickIdx);
00158 if (dist <= minTOi) {
00159 minTOi = dist;
00160 }
00161 }
00162 if (minTOi > maxOFmin || (RDKit::feq(minTOi,maxOFmin) && poolIdx<pick) ) {
00163 maxOFmin = minTOi;
00164 pick = poolIdx;
00165 plri = pli;
00166 }
00167 }
00168
00169
00170 picks.push_back(pick);
00171 CHECK_INVARIANT(plri!=pool.end(),"");
00172 pool.erase(plri);
00173 }
00174 return picks;
00175 }
00176
00177
00178 };
00179
00180 #endif