00001
00025 #include "nhp/individual.h"
00026 #include "nhp/population.h"
00027 #include "nhp/simplepopula.h"
00028 #include "nhp/selection.h"
00029 #include "nhp/genes.h"
00030 #include "nhp/mutator.h"
00031 #include <magic/mmath.h>
00032
00033 SelectionMatrix::SelectionMatrix (const SelectionSituation& situation) {
00034 calculateMatrix (situation);
00035 }
00036
00037 void SelectionMatrix::calculateMatrix (const SelectionSituation& situation) {
00038
00039
00040
00041
00042
00043
00044 int popSize = situation.population().size();
00045 mSelection.make (popSize, popSize);
00046 mSelection = 0.0;
00047
00048 double rowsum;
00049 for (int i=0; i<popSize; i++) {
00050 rowsum=0.0;
00051
00052
00053
00054 for (int j=0; j<popSize; j++)
00055 rowsum += (mSelection.get(i,j) = situation.getOrdered(i).selector().select(situation, i, j));
00056
00057
00058
00059 for (int j=0; j<popSize; j++)
00060 mSelection.get(i,j) /= rowsum;
00061 }
00062
00063
00064
00065 mSelection.multiplyToSum (1.0);
00066 mSelection *= transpose (mSelection);
00067 mSelection.multiplyToSum (1.0);
00068 }
00069
00070 void SelectionMatrix::selectRandomPair (int& a, int& b) const {
00071 double rn=frnd();
00072 double pos=0.0;
00073 for (int i=0; i<mSelection.rows; i++) {
00074 for (int j=0; j<mSelection.cols; j++) {
00075 if ((pos+=mSelection.get(i,j)) >= rn) {
00076
00077 a = i;
00078 b = j;
00079 return;
00080 }
00081 }
00082 }
00083 FORBIDDEN;
00084 }
00085
00086
00087
00089
00090
00091
00092
00093
00095
00096 SelectionSituation::SelectionSituation (const SimplePopulation& pop)
00097 : mrPop (pop), mOrdPop (pop.getPopArray()) {
00098 mOrdPop.quicksort ();
00099 }
00100
00101
00102
00104
00105
00106
00107
00108
00109
00110
00112
00113 SelectionPrms::SelectionPrms () {
00114 mMu = -1;
00115 mMuPart = 0.2;
00116 mEtaPlus = 1.0;
00117 mQ = 3;
00118 mAdaptiveMu = false;
00119 mAdaptiveEtaPlus = false;
00120 mAdaptiveQ = false;
00121
00122 mWeightedSelection = false;
00123
00124 mSelMethodW.make (Selector::number_of_methods);
00125 useOnlyMethod (Selector::MULAMBDASELECTION);
00126 }
00127
00128 void SelectionPrms::adaptParams (bool adapt_mu, bool adapt_etaplus, bool adapt_q) {
00129 ASSERTWITH (!adapt_mu || mMu<0,
00130 "Must use partial mu with self-adaptation");
00131
00132 mAdaptiveMu = adapt_mu;
00133 mAdaptiveEtaPlus = adapt_etaplus;
00134 mAdaptiveQ = adapt_q;
00135 }
00136
00137 void SelectionPrms::useOnlyMethod (int m) {
00138 ASSERT (m>=0 && m<Selector::number_of_methods);
00139
00140 for (int i=0; i<Selector::number_of_methods; i++)
00141 mSelMethodW[i] = 0.0;
00142
00143 mSelMethodW[m] = 1.0;
00144
00145 mAdaptiveWeights = false;
00146 }
00147
00148 void SelectionPrms::setEtaPlus (double etaplus) {
00149 ASSERT (etaplus>=1 && etaplus<=2);
00150 mEtaPlus = etaplus;
00151 }
00152
00153 void SelectionPrms::setQ (int q) {
00154 ASSERT (q>1);
00155 mQ = q;
00156 }
00157
00158 void SelectionPrms::setMu (int m) {
00159 ASSERT (m>0);
00160 mMu = m;
00161 mMuPart = -1;
00162 mAdaptiveMu = false;
00163 }
00164
00165 void SelectionPrms::setMuPart (double muPart) {
00166 ASSERT (muPart>=0 && muPart<1);
00167 mMu = -1;
00168 mMuPart = muPart;
00169 }
00170
00171 int SelectionPrms::muFor (int populsize) const {
00172 if (mMu>=0)
00173 return mMu;
00174 else {
00175 ASSERT (mMuPart>=0);
00176 return int (mMuPart*populsize+0.5);
00177 }
00178 }
00179
00180 void SelectionPrms::copy (const SelectionPrms& o) {
00181 mMu = o.mMu;
00182 mMuPart = o.mMuPart;
00183 mEtaPlus = o.mEtaPlus;
00184 mQ = o.mQ;
00185 mAdaptiveMu = o.mAdaptiveMu;
00186 mAdaptiveEtaPlus = o.mAdaptiveEtaPlus;
00187 mAdaptiveQ = o.mAdaptiveQ;
00188
00189 mWeightedSelection = o.mWeightedSelection;
00190 mSelMethodW = o.mSelMethodW;
00191 mAdaptiveWeights = o.mAdaptiveWeights;
00192 }
00193
00194
00196
00197
00198
00199
00200
00201
00202
00204
00205 Selector::Selector (const SelectionPrms& orig) : SelectionPrms (orig), mScore (0) {
00206 }
00207
00208
00209
00210 ConstantMutator selectorMutator (0.02);
00211
00212 void Selector::addGenesTo (Gentainer& g, const StringMap& params) {
00213
00214
00215
00216
00217
00218 g.add (new BitFloatGene ("u%", 0.01, 0.99, 16, params));
00219 g.add (new IntGene ("q", 2, 10, 1.0));
00220 g.add (new FloatGene ("e+", 1, 2, 0.2));
00221
00222 g["u%"].hide ();
00223 g["q"].hide ();
00224 g["e+"].hide ();
00225
00226
00227 for (int i=0; i<4; i++) {
00228 g.add (new FloatGene (format ("s%d",i), 0, 1, 0.2));
00229 g[(CONSTR)format ("s%d",i)].hide ();
00230 }
00231 }
00232
00233 void Selector::read (const Genome& g) {
00234 try {
00235
00236 if (mAdaptiveMu)
00237 mMuPart = static_cast <const FloatGene*> (g.getGene ("u%"))->getvalue();
00238 if (mAdaptiveEtaPlus)
00239 mEtaPlus = static_cast <const FloatGene*> (g.getGene ("e+"))->getvalue();
00240 if (mAdaptiveQ)
00241 mQ = static_cast <const IntGene*> (g.getGene ("q"))->getvalue();
00242
00243
00244 if (mAdaptiveWeights) {
00245 mSelMethodW.make (Selector::number_of_methods);
00246 for (int i=0; i<Selector::number_of_methods; i++) {
00247 const Genstruct& gene = *g.getGene (format ("s%d", i));
00248 mSelMethodW[i] = dynamic_cast <const FloatGene&> (gene).getvalue();
00249 }
00250
00251 multiplyToUnity (mSelMethodW);
00252 }
00253 } catch (...) {
00254 ASSERT (false);
00255 }
00256 }
00257
00258 double Selector::select (const SelectionSituation& situation, int i, int j) const {
00259 if (mWeightedSelection) {
00260
00261
00262 double love=0.0;
00263 for (int m=0; m<Selector::number_of_methods; m++)
00264 love += mSelMethodW[m] * selectWithMethod (situation, m, i, j);
00265 return love;
00266 } else {
00267
00268
00269
00270
00271 double p=frnd ();
00272 for (int m=0; m<Selector::number_of_methods; p-=mSelMethodW[m++])
00273 if (p <= mSelMethodW[m])
00274 return selectWithMethod (situation, m, i, j);
00275 FORBIDDEN;
00276 }
00277 }
00278
00279 double Selector::selectWithMethod (const SelectionSituation& situation, int sm, int i, int j) const {
00280 ASSERTWITH (sm>=0 && sm<=3, "Selection method index out of range");
00281
00282 switch (sm) {
00283 case 0: return muLambdaSelection (situation, i, j);
00284 case 1: return linearRanking (situation, i, j);
00285 case 2: return proportionalSelection (situation, i, j);
00286 case 3: return tournamentSelection (situation, i, j);
00287 };
00288
00289
00290 return 0.0;
00291 }
00292
00293 double Selector::muLambdaSelection (const SelectionSituation& situation, int i, int j) const {
00294 const SimplePopulation& pop = situation.population();
00295 int mu;
00296 if (pop.mUseGlobalMu)
00297 mu = pop.selParams().muFor (pop.size());
00298 else
00299 mu = muFor (pop.size());
00300
00301 return (j>mu)? 0.0 : 1.0;
00302 }
00303
00304 double Selector::linearRanking (const SelectionSituation& situation, int i, int j) const {
00305 double ep = situation.population().mUseGlobalEtaPlus?
00306 situation.population().selParams().mEtaPlus
00307 : mEtaPlus;
00308
00309 return (ep-(2*ep-2)*double(j-1)/double(situation.population().size()-1));
00310 }
00311
00312 double Selector::proportionalSelection (const SelectionSituation& situation, int i, int j) const {
00313 return situation.getOrdered(j).getfitness() / situation.population().mFitnessStats.avgFitness();
00314 }
00315
00316 double Selector::tournamentSelection (const SelectionSituation& situation, int i, int j) const {
00317 double q = situation.population().mUseGlobalQ?
00318 int(situation.population().selParams().mQ)
00319 : mQ;
00320 int popSize = situation.population().size();
00321 return pow (popSize, -q) * (pow(popSize-j+1, q)-pow(popSize-j, q));
00322 }
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336