Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

selection.cc

Go to the documentation of this file.
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     // Compute selection matrices for each method
00041     //
00042 
00043     // Init the final matrix
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         // Let the individual tell it's selection willingness towards
00053         // every individual, including itself
00054         for (int j=0; j<popSize; j++)
00055             rowsum += (mSelection.get(i,j) = situation.getOrdered(i).selector().select(situation, i, j));
00056         
00057         // Equalize row sum to 1.0
00058         // rowsum = 1/(rowsum*mOPop.size);
00059         for (int j=0; j<popSize; j++)
00060             mSelection.get(i,j) /= rowsum;
00061     }
00062     // sout << mSelection;
00063     
00064     // Sum the matrices
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                 // TRACE2 ("Selected %d+%d", i,j);
00077                 a = i;
00078                 b = j;
00079                 return;
00080             }
00081         }
00082     }
00083     FORBIDDEN;
00084 }
00085 
00086 
00087 
00089 //  ----       |                 o             ---- o                     o            //
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 //      ----       |                 o            ----                      //
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 // We must use our own mutator that is not affected by the possible
00209 // self-adaptation of the mutation rates
00210 ConstantMutator selectorMutator (0.02);
00211 
00212 void Selector::addGenesTo (Gentainer& g, const StringMap& params) {
00213 
00214     // Parameters of different selection methods
00215 
00216     // mMuPart (for u% selection)
00217     //g.add (&(new FloatGene ("u%", 0.01, 0.99, 0.2))->setMutator(&selectorMutator));
00218     g.add (new BitFloatGene ("u%", 0.01, 0.99, 16, params));
00219     g.add (new IntGene ("q", 2, 10, 1.0));      // mQ (for tournament selection)
00220     g.add (new FloatGene ("e+", 1, 2, 0.2));    // mEtaPlus (for rank-based selection)
00221 
00222     g["u%"].hide ();
00223     g["q"].hide ();
00224     g["e+"].hide ();
00225 
00226     // Weights/propabilities of the different selection methods
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         // Selection method parameters
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         // Selection method weights/propabilities
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             // Ensure that selection method weights sum to 1.0
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         // Add the results of different selection functions together,
00261         // weighing them nicely
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         // Choose one selection method using the propabilities for
00269         // different methods
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; // Probibility selection is not supported currently
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     /* TODO: Handle error situation. */
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 // Use locally autoadapted mu
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 void Selector::operator= (const Selector& o) {
00327     SelectionPrms::operator= (o);
00328     mScore = o.mScore;
00329 }
00330 
00331 void Selector::operator= (const SelectionPrms& o) {
00332     SelectionPrms::operator= (o);
00333     mScore = 0;
00334 }
00335 */
00336 

Generated on Thu Feb 10 20:12:01 2005 for NeHeP by doxygen1.2.18