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 );
125 VectorFloat::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;
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;
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!" << std::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;
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 /= Float(geneSize);
332 individual.fitness = 1.0/(minError*minError);
334 return individual.fitness;
337 virtual bool train(
const MatrixFloat &trainingData){
339 if( !initialized )
return false;
341 UINT currentIteration = 0;
342 UINT numIterationsNoChange = 0;
343 bool keepTraining =
true;
344 Float 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" << std::endl;
377 Float delta = fabs( bestIndividualFitness-lastBestFitness );
378 lastBestFitness = bestIndividualFitness;
380 trainingLog <<
"Iteration: " << currentIteration <<
"\tBestFitness: " << bestIndividualFitness <<
"\tBestIndex: " << bestIndividualIndex <<
"\tDelta: " << delta <<
"\tNumIterationsNoChange: " << numIterationsNoChange << std::endl;
382 if( currentIteration >= maxIteration ){
383 keepTraining =
false;
384 trainingLog <<
"Max Iteration Reached!" << std::endl;
387 if( delta <= minChange ){
388 if( ++numIterationsNoChange >= minNumIterationsNoChange ){
389 keepTraining =
false;
390 trainingLog <<
"Min Changed Reached!" << std::endl;
393 numIterationsNoChange = 0;
396 if( customConvergenceCheck() ){
397 keepTraining =
false;
398 trainingLog <<
"Custom Convergance Triggered!" << std::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{
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 Float baiseCoeff){
457 this->baiseCoeff = baiseCoeff;
461 bool setMutationRate(
const Float mutationRate){
462 this->mutationRate = mutationRate;
466 bool setMinChange(
const Float minChange){
467 this->minChange = minChange;
473 if( newPopulation.size() == 0 )
return false;
475 population = newPopulation;
476 populationSize = (UINT)population.size();
477 populationWeights.
resize( populationSize );
478 accumSumLookup.
resize( populationSize );
483 VectorFloat::iterator geneIter;
485 while( populationIter != population.end() ){
486 weightsIter->value = populationIter->fitness;
487 weightsIter->index = index++;
496 virtual inline Float generateRandomGeneValue(){
500 virtual bool customConvergenceCheck(){
504 virtual bool printBest()
const{
505 if( !initialized )
return false;
507 std::cout <<
"BestIndividual: ";
508 for(UINT i=0; i<geneSize; i++){
509 std::cout << population[ bestIndividualIndex ].gene[i] <<
"\t";
511 std::cout << std::endl;
523 UINT minNumIterationsNoChange;
526 UINT bestIndividualIndex;
527 Float bestIndividualFitness;
542 #endif //GRT_EVOLUTIONARY_ALGORITHM_HEADER
EvolutionaryAlgorithm(const UINT populationSize=0, const UINT geneSize=0)
virtual bool estimatePopulationFitness(const MatrixFloat &trainingData, Float &bestFitness, UINT &bestIndex)
virtual ~EvolutionaryAlgorithm()
virtual bool resize(const unsigned int size)
virtual Float evaluateFitness(INDIVIDUAL &individual, const MatrixFloat &trainingData)
virtual bool evolvePopulation()
int getRandomNumberWeighted(const Vector< int > &values, const VectorFloat &weights)
unsigned int getNumRows() const
unsigned int getNumCols() const
Float getRandomNumberUniform(Float minRange=0.0, Float maxRange=1.0)
INDIVIDUAL & operator[](const UINT &index)
int getRandomNumberInt(int minRange, int maxRange)
virtual bool initPopulation(const UINT populationSize, const UINT geneSize)