33 #ifndef GRT_EVOLUTIONARY_ALGORITHM_HEADER
34 #define GRT_EVOLUTIONARY_ALGORITHM_HEADER
36 #include "Individual.h"
40 template <
typename INDIVIDUAL>
53 minNumIterationsNoChange = 1;
55 bestIndividualIndex = 0;
56 bestIndividualFitness = 0;
65 errorLog.setProceedingText(
"[EVO ERROR]");
66 trainingLog.setProceedingText(
"[EVO TRAINING]");
67 warningLog.setProceedingText(
"[EVO WARNING]");
87 return population[ index ];
101 this->populationSize = 0;
103 bestIndividualIndex = 0;
104 bestIndividualFitness = 0;
106 populationWeights.clear();
107 accumSumLookup.clear();
108 populationHistory.clear();
109 fitnessHistory.clear();
111 if( populationSize == 0 || geneSize == 0 )
return false;
114 this->populationSize = populationSize;
115 this->geneSize = geneSize;
116 population.resize( populationSize );
117 populationWeights.resize( populationSize );
118 accumSumLookup.resize( populationSize );
123 typename vector< INDIVIDUAL >::iterator populationIter = population.begin();
124 vector< IndexedDouble >::iterator weightsIter = populationWeights.begin();
125 vector< double >::iterator geneIter;
127 while( populationIter != population.end() ){
128 populationIter->fitness = 0;
129 populationIter->gene.resize( geneSize );
132 for(i=0; i<geneSize; i++){
133 populationIter->gene[ i ] = generateRandomGeneValue();
136 weightsIter->value = populationIter->fitness;
137 weightsIter->index = index++;
144 parents = population;
166 if( !initialized )
return false;
168 typename vector< INDIVIDUAL >::iterator populationIter = population.begin();
169 vector< IndexedDouble >::iterator weightsIter = populationWeights.begin();
171 while( populationIter != population.end() ){
174 weightsIter->index = index++;
177 if( weightsIter->value > bestFitness ){
178 bestFitness = weightsIter->value;
179 bestIndex = weightsIter->index;
198 if( !initialized )
return false;
204 UINT crossOverPoint = 0;
205 typename vector< INDIVIDUAL >::iterator populationIter = population.begin();
206 vector< IndexedDouble >::iterator weightsIter = populationWeights.begin();
209 weightsIter = populationWeights.begin();
210 while( populationIter != population.end() ){
211 weightsIter->value = baiseWeights ? pow( populationIter->fitness, baiseCoeff ) : populationIter->fitness;
212 weightsIter->index = index++;
219 sort(populationWeights.begin(),populationWeights.end(),IndexedDouble::sortIndexedDoubleByValueAscending);
222 accumSumLookup[0] = populationWeights[0].value;
223 for(
unsigned int i=1; i<populationSize; i++){
224 accumSumLookup[i] = accumSumLookup[i-1] + populationWeights[i].value;
227 if( accumSumLookup[populationSize-1] == 0 ){
228 warningLog <<
"evolvePopulation() - The accum sum is zero!" << endl;
232 populationIter = population.begin();
236 populationIter->gene = parents[ bestIndividualIndex ].gene;
247 while( populationIter != population.end() ){
257 for(i=0; i<geneSize; i++){
258 if( i < crossOverPoint ) populationIter->gene[i] = parents[ mom ].gene[i];
259 else populationIter->gene[i] = parents[ dad ].gene[i];
263 for(i=0; i<geneSize; i++){
265 populationIter->gene[ i ] = generateRandomGeneValue();
273 if( populationIter != population.end() ){
275 for(i=0; i<geneSize; i++){
276 if( i < crossOverPoint ) populationIter->gene[i] = parents[ dad ].gene[i];
277 else populationIter->gene[i] = parents[ mom ].gene[i];
281 for(i=0; i<geneSize; i++){
283 populationIter->gene[ i ] = generateRandomGeneValue();
294 parents = population;
309 individual.fitness = 0;
311 if( !initialized )
return 0;
313 if( trainingData.
getNumCols() != geneSize )
return 0;
317 double minError = numeric_limits< double >::max();
319 for(UINT i=0; i<M; i++){
322 for(UINT j=0; j<geneSize; j++){
323 error += ( trainingData[i][j] - individual.gene[j] ) * ( trainingData[i][j] - individual.gene[j] );
325 if( error < minError ) minError = error;
329 minError /= double(geneSize);
332 individual.fitness = 1.0/(minError*minError);
334 return individual.fitness;
339 if( !initialized )
return false;
341 UINT currentIteration = 0;
342 UINT numIterationsNoChange = 0;
343 bool keepTraining =
true;
344 double lastBestFitness = 0;
347 populationHistory.reserve( maxIteration/storeRate );
348 fitnessHistory.reserve( maxIteration/storeRate );
356 lastBestFitness = bestIndividualFitness;
359 populationHistory.push_back( population );
360 fitnessHistory.push_back( IndexedDouble(bestIndividualIndex, bestIndividualFitness) );
364 while( keepTraining ){
368 errorLog <<
"Failed to evolve population" << endl;
377 double delta = fabs( bestIndividualFitness-lastBestFitness );
378 lastBestFitness = bestIndividualFitness;
380 trainingLog <<
"Iteration: " << currentIteration <<
"\tBestFitness: " << bestIndividualFitness <<
"\tBestIndex: " << bestIndividualIndex <<
"\tDelta: " << delta <<
"\tNumIterationsNoChange: " << numIterationsNoChange << endl;
382 if( currentIteration >= maxIteration ){
383 keepTraining =
false;
384 trainingLog <<
"Max Iteration Reached!" << endl;
387 if( delta <= minChange ){
388 if( ++numIterationsNoChange >= minNumIterationsNoChange ){
389 keepTraining =
false;
390 trainingLog <<
"Min Changed Reached!" << endl;
393 numIterationsNoChange = 0;
396 if( customConvergenceCheck() ){
397 keepTraining =
false;
398 trainingLog <<
"Custom Convergance Triggered!" << endl;
405 if( currentIteration % storeRate == 0 && storeHistory ){
406 populationHistory.push_back( population );
407 fitnessHistory.push_back( IndexedDouble(bestIndividualIndex, bestIndividualFitness) );
414 UINT getPopulationSize()
const{
415 return populationSize;
418 bool getInitialized()
const{
422 vector< INDIVIDUAL > getPopulation()
const{
426 bool setPopulationSize(
const UINT populationSize){
427 this->populationSize = populationSize;
431 bool setMinNumIterationsNoChange(
const UINT minNumIterationsNoChange){
432 this->minNumIterationsNoChange = minNumIterationsNoChange;
436 bool setMaxIterations(
const UINT maxIteration){
437 this->maxIteration = maxIteration;
441 bool setStoreRate(
const UINT storeRate){
442 this->storeRate = storeRate;
446 bool setStoreHistory(
const bool storeHistory){
447 this->storeHistory = storeHistory;
451 bool setBaiseWeights(
const bool baiseWeights){
452 this->baiseWeights = baiseWeights;
456 bool setBaiseCoeff(
const double baiseCoeff){
457 this->baiseCoeff = baiseCoeff;
461 bool setMutationRate(
const double mutationRate){
462 this->mutationRate = mutationRate;
466 bool setMinChange(
const double minChange){
467 this->minChange = minChange;
471 virtual bool setPopulation(
const vector< INDIVIDUAL > &newPopulation ){
473 if( newPopulation.size() == 0 )
return false;
475 population = newPopulation;
476 populationSize = (UINT)population.size();
477 populationWeights.resize( populationSize );
478 accumSumLookup.resize( populationSize );
481 typename vector< INDIVIDUAL >::iterator populationIter = population.begin();
482 vector< IndexedDouble >::iterator weightsIter = populationWeights.begin();
483 vector< double >::iterator geneIter;
485 while( populationIter != population.end() ){
486 weightsIter->value = populationIter->fitness;
487 weightsIter->index = index++;
496 virtual inline double generateRandomGeneValue(){
500 virtual bool customConvergenceCheck(){
504 virtual bool printBest()
const{
505 if( !initialized )
return false;
507 cout <<
"BestIndividual: ";
508 for(UINT i=0; i<geneSize; i++){
509 cout << population[ bestIndividualIndex ].gene[i] <<
"\t";
519 UINT minNumIterationsNoChange;
522 UINT bestIndividualIndex;
523 double bestIndividualFitness;
532 vector< INDIVIDUAL > population;
533 vector< INDIVIDUAL > parents;
534 vector< IndexedDouble > populationWeights;
535 vector< vector< INDIVIDUAL > > populationHistory;
536 vector< IndexedDouble > fitnessHistory;
537 vector< double > accumSumLookup;
542 #endif //GRT_EVOLUTIONARY_ALGORITHM_HEADER
virtual bool initPopulation(const UINT populationSize, const UINT geneSize)
unsigned int getNumCols() const
virtual bool evolvePopulation()
int getRandomNumberWeighted(const vector< int > &values, const vector< double > &weights)
INDIVIDUAL & operator[](const UINT &index)
int getRandomNumberInt(int minRange, int maxRange)
double getRandomNumberUniform(double minRange=0.0, double maxRange=1.0)
virtual double evaluateFitness(INDIVIDUAL &individual, const MatrixDouble &trainingData)
virtual bool estimatePopulationFitness(const MatrixDouble &trainingData, double &bestFitness, UINT &bestIndex)
unsigned int getNumRows() const
EvolutionaryAlgorithm(const UINT populationSize=0, const UINT geneSize=0)
virtual ~EvolutionaryAlgorithm()