00001
00046
00047
00048
00049
00050 #include <iomanip>
00051 #include <vector>
00052 #include <EALib/UncertaintyQuantification.h>
00053
00054
00055
00056 template<class T> double percentile(std::vector<T> v, double p =.25) {
00057 if (v.empty()) throw SHARKEXCEPTION("[percentile] list must not be empty");
00058 std::sort(v.begin(),v.end());
00059 unsigned N = v.size();
00060
00061 double n = p * (double(N) - 1.0) + 1.0;
00062 unsigned k = unsigned(floor(n));
00063 double d = n - k;
00064 if(k == 0) return v[0];
00065 if(k == N) return v[N - 1];
00066
00067 return v[k - 1] + d * (v[k] - v[k - 1]);
00068 }
00069
00070
00071
00072 struct RankingObject {
00073 RankingObject(double x, unsigned i) : fitnessOld(x), fitnessNew(x), index(i), reev(false) {};
00074 double fitnessOld;
00075 double fitnessNew;
00076 unsigned rankNew;
00077 unsigned rankOld;
00078 unsigned Delta;
00079 unsigned index;
00080 bool reev;
00081 };
00082
00083 bool rankingObjectLessFitnessOld(const RankingObject &x, const RankingObject &y) {
00084 if(x.fitnessOld < y.fitnessOld) return true;
00085 return false;
00086 }
00087 bool rankingObjectLessFitnessNew(const RankingObject &x, const RankingObject &y) {
00088 if(x.fitnessNew < y.fitnessNew) return true;
00089 return false;
00090 }
00091
00092
00093 double deltaLimTheta(unsigned R, unsigned l, double theta) {
00094 std::vector<double> v;
00095
00096 for(unsigned i=1; i<(2*l-1); i++) v.push_back(fabs(double(i)-double(R)));
00097
00098 return percentile(v, 0.5 * theta);
00099 }
00100
00101
00102 double UncertaintyQuantification(Population& p, NoisyFitnessFunction& f, double theta, double r_l) {
00103 unsigned l = p.size();
00104 unsigned i;
00105
00106
00107 std::vector<RankingObject> v;
00108 for (i=0; i<l; i++)
00109 v.push_back(RankingObject(p[i].getFitness(), i));
00110 for (i=0; i<l; i++)
00111 v.push_back(RankingObject(p[i].getFitness(), i));
00112
00113
00114 if (!r_l) r_l = Shark::max(0.1, 2.0 / l);
00115 unsigned l_reev = unsigned(floor(r_l * l));
00116 if (Rng::coinToss(r_l * l - floor(r_l * l))) l_reev++;
00117
00118
00119
00120 for (i=0; i<l_reev; i++) {
00121 v[i].fitnessNew = f.fitness(dynamic_cast< std::vector< double >& >(p[i][0]));
00122 v[i].reev = true;
00123 }
00124
00125
00126 std::sort(v.begin(), v.end(), &rankingObjectLessFitnessOld);
00127 for (i=0; i<2*l; i++) v[i].rankOld = i+1;
00128
00129
00130 std::sort(v.begin(), v.end(), &rankingObjectLessFitnessNew);
00131 for (i=0; i<2*l; i++) v[i].rankNew = i+1;
00132
00133
00134
00135 for (i=0; i<2*l; i++) {
00136 v[i].Delta = (unsigned) abs(int(v[i].rankNew) - int(v[i].rankOld));
00137 if (v[i].Delta) v[i].Delta -= 1;
00138 }
00139
00140
00141 double s = 0.;
00142 for (i=0; i<2*l; i++) {
00143 if(v[i].reev) {
00144
00145
00146 p[ v[i].index] .setFitness(.5*(v[i].fitnessNew + v[i].fitnessOld));
00147 s += 2 * v[i].Delta;
00148 if(v[i].fitnessNew > v[i].fitnessOld) {
00149 s -= deltaLimTheta(v[i].rankNew - 1, l, theta);
00150 s -= deltaLimTheta(v[i].rankOld, l, theta);
00151 } else if(v[i].fitnessOld > v[i].fitnessNew) {
00152 s -= deltaLimTheta(v[i].rankNew, l, theta);
00153 s -= deltaLimTheta(v[i].rankOld - 1, l, theta);
00154 } else{
00155 s -= deltaLimTheta(v[i].rankNew, l, theta);
00156 s -= deltaLimTheta(v[i].rankOld, l, theta);
00157 }
00158 }
00159 }
00160 s /= l_reev;
00161
00162 return s;
00163 }