25 #include "evodataviewer.h"
27 #include "randomgenerator.h"
28 #include <configurationhelper.h>
30 #include <QThreadPool>
31 #include <QtConcurrentMap>
32 #include <QtAlgorithms>
40 #pragma warning(disable:4996)
146 void runEvaluatorThreadForEvoga(EvaluatorThreadForEvoga* e)
176 int Evoga::mrand(
int i)
193 loadedIndividuals = 1;
195 savePopulationEachNGenerations = 0;
196 stopEvolution =
false;
197 averageIndividualFitnessOverGenerations =
true;
198 isStepByStep =
false;
205 if (statfit != NULL) {
206 for(
int i = 0; i < nogenerations; i++) {
215 void Evoga::setSeed(
int s)
223 double Evoga::drand()
225 return (
double)rand()/(double)RAND_MAX;
228 double Evoga::getNoise(
double minn,
double maxn)
236 return drand()*nrange+minn;
239 int Evoga::mutate(
int w,
double mut)
246 for(ii=0;ii < 8;ii++) {
250 for(ii=0;ii < 8;ii++) {
269 void Evoga::putGenome(
int fromgenome,
int tobestgenome)
271 if (tobestgenome < this->nreproducing) {
272 for (
int i = 0; i < this->glen; i++) {
273 bestgenome[tobestgenome][i] = genome[fromgenome][i];
280 void Evoga::getGenome(
int frombestgenome,
int togenome,
int mut)
282 for(
int i = 0; i < this->glen; i++) {
284 genome[togenome][i] = bestgenome[frombestgenome][i];
287 genome[togenome][i] = mutate(bestgenome[frombestgenome][i], mutation);
289 genome[togenome][i] = mutate(bestgenome[frombestgenome][i], mutations[i]);
295 void Evoga::copyGenes(
int from,
int to,
int mut)
297 for(
int i = 0; i < this->glen; i++) {
299 genome[to][i] = genome[from][i];
302 genome[to][i] = mutate(genome[from][i], mutation);
304 genome[to][i] = mutate(genome[from][i], mutations[i]);
311 void Evoga::reproduce()
323 this->computeFStat();
326 for(bi=0;bi<this->nreproducing;bi++) {
329 for(i=0;i< this->popSize;i++) {
336 this->putGenome(bx,bi);
339 if ((bi+1)<=this->savebest && cgen< this->nogenerations) {
340 sprintf(sbuffer,
"B%dS%d.gen",bi+1,this->currentSeed);
342 if ((fp=fopen(sbuffer,
"w")) == NULL) {
343 Logger::error(QString(
"I cannot open file B%1S%2.gen").arg(bi+1).arg(this->currentSeed));
346 if ((fp=fopen(sbuffer,
"a")) == NULL) {
347 Logger::error(QString(
"I cannot open file B%1S%2.gen").arg(bi+1).arg(this->currentSeed));
351 fprintf(fp,
"**NET : s%d_%d.wts\n",cgen,bx);
352 saveagenotype(fp,bx);
356 tfitness[bx]=-9999.0;
361 for(bi=0;bi<this->nreproducing;bi++)
362 for(i =0;i< this->noffspring;i++) {
363 if(this->elitism && bi==0)
364 this->getGenome(bi,bx,0);
366 this->getGenome(bi,bx,1);
372 for (i=0;i<this->popSize;i++) tfitness[i]=0.0;
377 void Evoga::saveBestInd()
390 sprintf(sbuffer,
"B%dS%d.gen",bi+1,this->currentSeed);
392 if ((fp=fopen(sbuffer,
"w")) == NULL) {
393 Logger::error(QString(
"I cannot open file B%1S%2.gen").arg(bi+1).arg(this->currentSeed));
396 if ((fp=fopen(sbuffer,
"a")) == NULL) {
397 Logger::error(QString(
"I cannot open file B%1S%2.gen").arg(bi+1).arg(this->currentSeed));
402 for(i=0;i<this->popSize;i++) {
403 ffit=this->tfitness[i]/this->ntfitness[i];
411 fprintf(fp,
"**NET : s%d_%d.wts\n",cgen,bi);
412 saveagenotype(fp,bi);
418 void Evoga::mreproduce()
430 this->computeFStat();
433 for(bi=0;bi<this->nreproducing;bi++) {
436 for(i=0;i< this->popSize;i++) {
443 this->putGenome(bx,bi);
446 if ((bi+1)<=this->savebest && cgen< this->nogenerations) {
447 sprintf(sbuffer,
"B%dS%d.gen",bi+1,this->currentSeed);
449 if ((fp=fopen(sbuffer,
"w")) == NULL) {
450 Logger::error(QString(
"I cannot open file B%1S%2.gen").arg(bi+1).arg(this->currentSeed));
453 if ((fp=fopen(sbuffer,
"a")) == NULL) {
454 Logger::error(QString(
"I cannot open file B%1S%2.gen").arg(bi+1).arg(this->currentSeed));
458 fprintf(fp,
"**NET : s%d_%d.wts\n",cgen,bx);
459 saveagenotype(fp,bx);
468 for(bi=0;bi<this->nreproducing;bi++)
469 for(i =0;i< this->noffspring;i++) {
470 if(this->elitism && bi==0)
471 this->getGenome(bi,bx,0);
473 this->getGenome(bi,bx,1);
479 for (i=0;i<this->popSize;i++) tfitness[i]=9999.0;
485 void Evoga::printPop()
487 for(
int i = 0; i < this->popSize; i++) {
488 QString output = QString(
"Fit %1 | ").arg(tfitness[i]);
489 for(
int l = 0; l < this->glen; l++) {
490 output += QString(
"%1 ").arg(this->genome[i][l]);
496 void Evoga::printBest()
498 for(
int i = 0; i < bestgenome.size(); i++) {
499 QString output = QString(
"Best %d | ").arg(i);
500 for (
int s = 0; s < this->glen; s++) {
501 output += QString(
"%1 ").arg(this->bestgenome[i][s]);
507 void Evoga::computeFStat()
515 for(i=0;i<this->popSize;i++) {
516 if(tfitness[i]<min) min=tfitness[i];
517 if(tfitness[i]>max) max=tfitness[i];
520 this->faverage=av/(double)this->popSize;
523 this->statfit[this->cgen][0]=this->fmax;
524 this->statfit[this->cgen][1]=this->faverage;
525 this->statfit[this->cgen][2]=this->fmin;
528 void Evoga::computeFStat2()
539 for(i=0;i<this->popSize;i++) {
540 if((tfitness[i]/ntfitness[i])<min) {
541 min=tfitness[i]/ntfitness[i];
543 if((tfitness[i]/ntfitness[i])>max) max=tfitness[i]/ntfitness[i];
544 av+=(tfitness[i]/ntfitness[i]);
546 this->faverage=av/(double)this->popSize;
549 this->statfit[this->cgen][0]=this->fmax;
550 this->statfit[this->cgen][1]=this->faverage;
551 this->statfit[this->cgen][2]=this->fmin;
554 void Evoga::saveagenotype(FILE *fp,
int ind)
557 fprintf(fp,
"DYNAMICAL NN\n");
558 for (j=0; j < this->glen; j++)
559 fprintf(fp,
"%d\n", this->genome[ind][j]);
560 fprintf(fp,
"END\n");
564 void Evoga::saveallg()
570 sprintf(filename,
"G%dS%d.gen",cgen,currentSeed);
571 if ((fp=fopen(filename,
"w+")) == NULL) {
575 for(i=0;i<this->popSize;i++) {
576 fprintf(fp,
"**NET : %d_%d_%d.wts\n",cgen,0,i);
577 this->saveagenotype(fp,i);
583 void Evoga::saveFStat()
587 sprintf(sbuffer,
"statS%d.fit",currentSeed);
589 fp=fopen(sbuffer ,
"w");
591 fp=fopen(sbuffer ,
"a");
594 fprintf(fp,
"%.3f %.3f %.3f\n",fmax,faverage,fmin);
606 void Evoga::loadgenotype(FILE *fp,
int ind)
611 fscanf(fp,
"DYNAMICAL NN\n");
612 for (j=0; j <this->glen; j++) {
613 fscanf(fp,
"%d\n",&v);
614 this->genome[ind][j]=v;
619 int Evoga::loadallg(
int gen,
const char *filew)
627 sprintf(filename,
"G%dS%d.gen", gen, seed);
629 sprintf(filename,
"%s", filew);
632 if ((fp = fopen(filename,
"r")) != NULL) {
636 fscanf(fp,
"%s : %s\n", flag, message);
637 if (strcmp(flag,
"**NET") == 0) {
638 loadgenotype(fp, genome.addOne());
643 Logger::info(QString(
"Loaded ind: %1").arg(genome.size()));
646 Logger::error(QString(
"File %1 could not be opened").arg(filename));
649 loadedIndividuals = genome.size();
651 return genome.size();
657 int Evoga::loadStatistics(
char *filename)
664 if ((fp=fopen(filename,
"r")) != NULL) {
665 while(fscanf(fp,
"%f %f %f\n",&max,&av,&min)!=EOF) {
666 this->statfit[i][0]=
max;
667 this->statfit[i][1]=av;
668 this->statfit[i][2]=
min;
680 void Evoga::randomizePop()
682 for (
int i = 0; i < genome.size(); i++) {
683 for(
int g = 0; g < glen; g++) {
684 genome[i][g] = mrand(256);
689 void Evoga::setInitialPopulation(
int* ge)
694 for(i=0; i<genome.size(); i++)
695 for(g=0; g<glen; g++)
698 genome[i][g] = mrand(256);
700 genome[i][g] = ge[g];
704 void Evoga::setMutations(
float* mut)
707 for(
int i=0; i<glen; i++)
708 mutations[i] = mut[i];
711 int* Evoga::getGenes(
int ind)
713 return this->genome[ind];
716 int* Evoga::getBestGenes(
int ind)
718 return this->bestgenome[ind];
721 void Evoga::resetGenerationCounter()
730 Evonet* evonet = getResource<Evonet>(
"evonet" );
731 if (evonet->pheFileLoaded()) {
733 Evonet* evonet = getResource<Evonet>(
"evonet" );
734 float* muts =
new float[evonet->freeParameters()];
735 int* pheParams =
new int[evonet->freeParameters()];
738 evonet->getMutations(muts);
742 evonet->copyPheParameters(pheParams);
743 setInitialPopulation(pheParams);
753 Evonet* evonet = getResource<Evonet>(
"evonet" );
755 float wrange = evonet->getWrange();
757 for (
int i = 0; i<glen; i++) {
758 genome[ind][i] = -(evonet->getFreeParameter(i)-wrange)/(2*wrange)*255;
782 int startGeneration=0;
787 genome.resize(popSize * 2);
789 final_mrate = mutation;
791 Logger::info(
"Number of replications: " + QString::number(nreplications));
794 QVector<EvaluatorThreadForEvoga*> evaluators(popSize, NULL);
795 if (numThreads > 1) {
796 for (
int i = 0; i < evaluators.size(); i++) {
801 QThreadPool::globalInstance()->setMaxThreadCount(numThreads);
804 for(rp=0;rp<nreplications;rp++) {
805 mutation=initial_mutation;
809 resetGenerationCounter();
819 for (
int i=0;i<popSize+1;i++) {
826 DataChunk statTest(QString(
"stattest"),Qt::blue,2000,
false);
827 if (statTest.loadRawData(QString(statfile),0)) {
828 startGeneration=statTest.getIndex();
830 Logger::info(
"Recovering from startGeneration: " + QString::number(startGeneration));
832 loadallg(startGeneration,genFile);
833 cgen=startGeneration;
834 mutation=mutation-startGeneration*mutationdecay;
835 if (mutation<final_mrate) mutation=final_mrate;
839 for(gn=startGeneration;gn<nogenerations;gn++) {
844 if (numThreads <= 1) {
848 for(
id=0;
id<popSize;
id++) {
853 if (averageIndividualFitnessOverGenerations) {
863 copyGenes(
id, popSize,1);
865 ntfitness[popSize]=0;
870 if (averageIndividualFitnessOverGenerations) {
871 tfitness[popSize] += fit;
872 ntfitness[popSize]++;
874 tfitness[popSize] = fit;
875 ntfitness[popSize] = 1;
884 for(
int wi=0;wi<popSize;wi++) {
885 if (ntfitness[wi] == 0.0) {
888 mfit=tfitness[wi]/ntfitness[wi];
895 if ((tfitness[popSize]/ntfitness[popSize])>minfit) {
896 copyGenes(popSize, minid,0);
897 tfitness[minid]=tfitness[popSize];
898 ntfitness[minid]=ntfitness[popSize];
907 for (
int i = 0; i < popSize; i++) {
908 evaluators[i]->getExperiment()->initGeneration(gn);
913 for (
int i = 0; i < popSize; i++) {
914 evaluators[i]->setGenotype(i);
919 QFuture<void> evaluationFuture = QtConcurrent::map(evaluators, runEvaluatorThreadForEvoga);
920 evaluationFuture.waitForFinished();
924 for (
int i = 0; i < popSize; i++) {
925 if (averageIndividualFitnessOverGenerations) {
926 tfitness[evaluators[i]->getGenotypeId()] += evaluators[i]->getFitness();
927 ntfitness[evaluators[i]->getGenotypeId()]++;
929 tfitness[evaluators[i]->getGenotypeId()] = evaluators[i]->getFitness();
930 ntfitness[evaluators[i]->getGenotypeId()] = 1;
936 for (
int i = 0; i < popSize; i++) {
937 copyGenes(i, popSize + i, 1);
938 tfitness[popSize + i] = 0;
939 ntfitness[popSize + i] = 0;
940 evaluators[i]->setGenotype(popSize + i);
945 evaluationFuture = QtConcurrent::map(evaluators, runEvaluatorThreadForEvoga);
946 evaluationFuture.waitForFinished();
950 for (
int i = 0; i < popSize; i++) {
951 if (averageIndividualFitnessOverGenerations) {
952 tfitness[evaluators[i]->getGenotypeId()] += evaluators[i]->getFitness();
953 ntfitness[evaluators[i]->getGenotypeId()]++;
955 tfitness[evaluators[i]->getGenotypeId()] = evaluators[i]->getFitness();
956 ntfitness[evaluators[i]->getGenotypeId()] = 1;
962 for (
int i = 0; i < popSize; i++) {
963 evaluators[i]->getExperiment()->endGeneration(gn);
971 QVector<FitnessAndId> parents(popSize);
972 for (
int i = 0; i < popSize; i++) {
973 parents[i].fitness = tfitness[i] / ntfitness[i];
976 QVector<FitnessAndId> children(popSize);
977 for (
int i = 0; i < popSize; i++) {
978 children[i].fitness = tfitness[popSize + i] / ntfitness[popSize + i];
979 children[i].id = popSize + i;
987 for (
int i = 0; i < popSize; i++) {
988 if (parents[p].fitness > children[c].fitness) {
993 copyGenes(children[c].
id, parents[popSize - 1 - c].
id, 0);
994 tfitness[parents[popSize - 1 - c].id] = tfitness[children[c].id];
995 ntfitness[parents[popSize - 1 - c].id] = ntfitness[children[c].id];
1010 if (mutation > final_mrate) {
1011 mutation -= mutationdecay;
1013 mutation = final_mrate;
1016 if ((savePopulationEachNGenerations != 0) && (gn % savePopulationEachNGenerations == 0)) {
1020 Logger::info(QString(
"Generation %1 took %2 minutes").arg(gn+1).arg((
double)evotimer.elapsed()/60000.0, 0,
'f', 2));
1027 for (
int i = 0; i < evaluators.size(); i++) {
1028 delete evaluators[i];
1041 int startGeneration=0;
1046 genome.resize(popSize);
1048 for(rp=0;rp<nreplications;rp++) {
1051 resetGenerationCounter();
1065 DataChunk statTest(QString(
"stattest"),Qt::blue,2000,
false);
1066 if (statTest.loadRawData(QString(statfile),0)) {
1067 startGeneration=statTest.getIndex();
1069 Logger::info(
"Recovering from startGeneration: " + QString::number(startGeneration));
1071 loadallg(startGeneration,genFile);
1075 for(gn=startGeneration;gn<nogenerations;gn++) {
1079 for(
id=0;
id<popSize;
id++) {
1093 if(savePopulationEachNGenerations!=0 && gn%savePopulationEachNGenerations == 0)
1096 Logger::info(QString(
"Generation %1 took %2 minutes").arg(gn+1).arg((
double)evotimer.elapsed()/60000.0, 0,
'f', 2));
1106 unsigned int generateRandomSeed() {
1109 unsigned long int stackMem = (
unsigned long int)( generateRandomSeed );
1112 unsigned long int startTime = GetTickCount();
1114 unsigned long int startTime = time(NULL);
1117 unsigned long int randSeed = 0;
1119 stackMem=stackMem-startTime; stackMem=stackMem-randSeed; stackMem=stackMem^(randSeed >> 13);
1120 startTime=startTime-randSeed; startTime=startTime-stackMem; startTime=startTime^(stackMem << 8);
1121 randSeed=randSeed-stackMem; randSeed=randSeed-startTime; randSeed=randSeed^(startTime >> 13);
1122 stackMem=stackMem-startTime; stackMem=stackMem-randSeed; stackMem=stackMem^(randSeed >> 12);
1123 startTime=startTime-randSeed; startTime=startTime-stackMem; startTime=startTime^(stackMem << 16);
1124 randSeed=randSeed-stackMem; randSeed=randSeed-startTime; randSeed=randSeed^(startTime >> 5);
1125 stackMem=stackMem-startTime; stackMem=stackMem-randSeed; stackMem=stackMem^(randSeed >> 3);
1126 startTime=startTime-randSeed; startTime=startTime-stackMem; startTime=startTime^(stackMem << 10);
1127 randSeed=randSeed-stackMem; randSeed=randSeed-startTime; randSeed=randSeed^(startTime >> 15);
1129 return randSeed%10000;
1138 if ( evolutionType !=
"steadyState" && evolutionType !=
"generational" ) {
1139 Logger::error(
"Evoga - evolutionType has been wrongly setted. It can assume only 'steadyState' or 'generational' values" );
1140 evolutionType =
"steadyState";
1148 if ( checkSeed ==
"auto" ) {
1149 seed = generateRandomSeed();
1151 seed = checkSeed.toInt();
1153 Logger::info( QString(
"Evoga - Random seed setted to ")+QString::number(seed) );
1159 averageIndividualFitnessOverGenerations =
ConfigurationHelper::getBool(params, prefix +
"averageIndividualFitnessOverGenerations",
true);
1172 Logger::info(
"Created EvoRobotExperiment " + params.
getValue(prefix+
"Experiment/type") +
" from group " + prefix +
"Experiment" );
1176 savedConfigurationParameters = params;
1177 savedExperimentPrefix = prefix +
"Experiment";
1190 d.
describeInt(
"nreplications" ).
def(10).
limits(1,
MaxInteger).
help(
"The number of which the evolution process will be replicated with a different random initial population");
1191 d.
describeInt(
"nreproducing" ).
def(20).
limits(1,
MaxInteger).
help(
"The number of individual allowed to produce offsprings; The size of populazion will be nreproducing x noffspring");
1192 d.
describeInt(
"noffspring" ).
def(5).
limits(1,
MaxInteger).
help(
"The number of offsprings generated by an individual; The size of populazion will be nreproducing x noffspring");
1193 d.
describeInt(
"seed" ).
def(1234).
limits(0,
MaxInteger).
help(
"The number used to initialize the random number generator; when a new replication will start, this value will be incremented by one to guarantee a truly different initial population for the next replica");
1197 d.
describeInt(
"savePopulationEachNGenerations").
def(0).
limits(0,
MaxInteger).
help(
"If is zero only the population of the last generation are saved into a file; otherwise it saves the population each N generations done");
1198 d.
describeReal(
"mutation_rate").
def(0.05).
limits(0,100).
help(
"The rate at a mutation will occur during a genotype copy; a real value below 1 (i.e. 0.12) is considered as a rate (i.e. 0.12 correspond to 12% of mutation); a value egual or above 1 is considered as a percentage of mutation (i.e. 25 correspond to 25% of mutation, or 0.25 rate of mutation)");
1199 d.
describeReal(
"mutation_decay").
def(0.01).
limits(0,1).
help(
"At first generation the mutation rate will be always 0.5, and at each generation done the mutation rate will be decreased by this value until it reachs the mutation_rate value");
1200 d.
describeReal(
"initial_mutation").
def(0.5).
limits(0,1).
help(
"The initial value of the mutation rate in case of the steadyState evolution type");
1202 d.
describeBool(
"averageIndividualFitnessOverGenerations").
def(
true).
help(
"Whether to average the current fitness with the previous one or not");
1213 statfit =
new double*[nogenerations];
1215 for(
int i = 0; i < nogenerations; i++) {
1216 statfit[i] =
new double[3];
1221 mutations =
new float[glen];
1222 for(
int mi = 0; mi < glen; mi++) {
1228 popSize = noffspring * nreproducing;
1231 genome.setGenomeLength(glen);
1232 genome.resize(popSize);
1233 for (
int i = 0; i < genome.size(); i++) {
1234 for (
int r = 0; r < glen; r++) {
1240 bestgenome.setGenomeLength(glen);
1241 bestgenome.resize(nreproducing);
1248 for (
int i = 0; i < nogenerations; i++) {
1249 statfit[i][0] = 0.0;
1250 statfit[i][1] = 0.0;
1251 statfit[i][2] = 0.0;
1254 Logger::info(
"Evoga Configured - Number of genes: " + QString::number(glen));
1259 stopEvolution =
false;
1260 if ( evolutionType ==
"steadyState" ) {
1262 }
else if ( evolutionType ==
"generational" ) {
1265 Logger::error( QString(
"Evoga - request to execute a unrecognized evolution type: %1").arg(evolutionType) );
1270 stopEvolution =
true;
1271 waitForNextStep.wakeAll();
1275 if ( isStepByStep && !stopEvolution ) {
1277 mutexStepByStep.lock();
1278 waitForNextStep.wait( &mutexStepByStep );
1279 mutexStepByStep.unlock();
1281 return stopEvolution;
1285 return stopEvolution;
1289 stopEvolution =
false;
1293 isStepByStep = enable;
1296 waitForNextStep.wakeAll();
1301 return isStepByStep;
1305 waitForNextStep.wakeAll();
1315 QVector<EvoRobotExperiment*> v;
1337 return nreplications;
1341 return nogenerations;
1349 mutation = mutation_rate;
1354 return loadallg(-1, filename.toAscii().data());
1359 return loadedIndividuals;
1364 return getGenes(
id);
1369 return "statS" + QString::number(seed) + QString(
".fit");
1374 return "B0S" + QString::number(seed) + QString(
".gen");
1384 return "G" + QString::number(generation) +
"S" + QString::number(seed) + QString(
".gen");
1400 #if defined(_MSC_VER)
1401 #pragma warning(pop)