00001 #include "BinaryTournamentSelect.h"
00002 #include <gsl/gsl_math.h>
00003 #include <iostream>
00004 #include <algorithm>
00005 #include "CFatalException.h"
00006
00007
00008 using namespace std;
00009 BinaryTournamentSelect::BinaryTournamentSelect(GeneralRNG &LocalRandom, tProbabilityFunction myPF,tDistanceFunction myDF):
00010 distancecount(0),
00011 Random(LocalRandom),
00012 ProbabilityFunction(myPF),
00013 DistanceFunction(myDF),
00014 ReturnIndex(0)
00015 {
00016
00017 }
00018
00019 BinaryTournamentSelect::~BinaryTournamentSelect()
00020 {
00021 cout << "Distance Count: " << distancecount << endl;
00022 }
00023
00024 void BinaryTournamentSelect::DoInit()
00025 {
00026 if (ProbabilityFunction().size() != DistanceFunction().size())
00027 throw CFatalException("Probabilities and Crowding distances do not have the same size !");
00028
00029 localprobabilities = ProbabilityFunction();
00030 localdistances = DistanceFunction();
00031 const size_t popsize = localdistances.size();
00032 PopulationIndex.assign(popsize*2,0);
00033 for (size_t i = 0; i < popsize; ++i)
00034 {
00035 PopulationIndex.at(i) = i;
00036 PopulationIndex.at(i+popsize) = i;
00037 }
00038 for (size_t i = 0; i < popsize; ++i)
00039 {
00040 int CurrentIndex = Random.GetNumber(popsize -i);
00041 swap(PopulationIndex.at(popsize-i-1),PopulationIndex.at(CurrentIndex));
00042 CurrentIndex = Random.GetNumber(popsize -i);
00043 swap(PopulationIndex.at(2*popsize-i-1),PopulationIndex.at(popsize+CurrentIndex));
00044 }
00045 ReturnIndex = 0;
00046 }
00047
00048 size_t BinaryTournamentSelect::DoGetOne()
00049 {
00050 const double tolerance = 1e-5;
00051
00052 const int fatherindex = PopulationIndex.at(ReturnIndex);
00053 const int motherindex = PopulationIndex.at(ReturnIndex+1);
00054
00055 ReturnIndex += 2;
00056
00057 const int comparison = gsl_fcmp(localprobabilities(fatherindex), localprobabilities(motherindex), tolerance);
00058 switch (comparison)
00059 {
00060 case 1:
00061 return fatherindex;
00062 case -1:
00063 return motherindex;
00064 case 0:
00065 distancecount++;
00066 if (localdistances(fatherindex) >= localdistances(motherindex))
00067 return fatherindex;
00068 else
00069 return motherindex;
00070 default:
00071 throw CFatalException("Something went very wrong in CBinaryTournamentSelect::GetOne");
00072 }
00073 }