25 #include "evodataviewer.h"
27 #include "randomgenerator.h"
28 #include <configurationhelper.h>
30 #include <QThreadPool>
31 #include <QtConcurrentMap>
32 #include <QtAlgorithms>
41 #pragma warning(disable:4996)
147 void runEvaluatorThreadForEvoga(EvaluatorThreadForEvoga* e)
194 loadedIndividuals = 1;
196 savePopulationEachNGenerations = 0;
197 stopEvolution =
false;
198 averageIndividualFitnessOverGenerations =
true;
199 isStepByStep =
false;
207 if (statfit != NULL) {
208 for(
int i = 0; i < nogenerations; i++) {
227 return (
double)rand()/(double)RAND_MAX;
238 return drand()*nrange+minn;
248 for(ii=0;ii < 8;ii++) {
252 for(ii=0;ii < 8;ii++) {
273 if (tobestgenome < this->nreproducing) {
274 for (
int i = 0; i < this->glen; i++) {
275 bestgenome[tobestgenome][i] = genome[fromgenome][i];
284 for(
int i = 0; i < this->glen; i++) {
286 genome[togenome][i] = bestgenome[frombestgenome][i];
289 genome[togenome][i] =
mutate(bestgenome[frombestgenome][i], mutation);
291 genome[togenome][i] =
mutate(bestgenome[frombestgenome][i], mutations[i]);
299 for(
int i = 0; i < this->glen; i++) {
301 genome[to][i] = genome[from][i];
304 genome[to][i] =
mutate(genome[from][i], mutation);
306 genome[to][i] =
mutate(genome[from][i], mutations[i]);
328 for(bi=0;bi<this->nreproducing;bi++) {
331 for(i=0;i< this->popSize;i++) {
341 if ((bi+1)<=this->savebest && cgen< this->nogenerations) {
342 sprintf(sbuffer,
"B%dS%d.gen",bi+1,this->currentSeed);
344 if ((fp=fopen(sbuffer,
"w")) == NULL) {
345 Logger::error(QString(
"I cannot open file B%1S%2.gen").arg(bi+1).arg(this->currentSeed));
348 if ((fp=fopen(sbuffer,
"a")) == NULL) {
349 Logger::error(QString(
"I cannot open file B%1S%2.gen").arg(bi+1).arg(this->currentSeed));
353 fprintf(fp,
"**NET : s%d_%d.wts\n",cgen,bx);
358 tfitness[bx]=-9999.0;
363 for(bi=0;bi<this->nreproducing;bi++)
364 for(i =0;i< this->noffspring;i++) {
365 if(this->elitism && bi==0)
374 for (i=0;i<this->popSize;i++) tfitness[i]=0.0;
392 sprintf(sbuffer,
"B%dS%d.gen",bi+1,this->currentSeed);
394 if ((fp=fopen(sbuffer,
"w")) == NULL) {
395 Logger::error(QString(
"I cannot open file B%1S%2.gen").arg(bi+1).arg(this->currentSeed));
398 if ((fp=fopen(sbuffer,
"a")) == NULL) {
399 Logger::error(QString(
"I cannot open file B%1S%2.gen").arg(bi+1).arg(this->currentSeed));
404 for(i=0;i<this->popSize;i++) {
405 ffit=this->tfitness[i]/this->ntfitness[i];
413 fprintf(fp,
"**NET : s%d_%d.wts\n",cgen,bi);
435 for(bi=0;bi<this->nreproducing;bi++) {
438 for(i=0;i< this->popSize;i++) {
448 if ((bi+1)<=this->savebest && cgen< this->nogenerations) {
449 sprintf(sbuffer,
"B%dS%d.gen",bi+1,this->currentSeed);
451 if ((fp=fopen(sbuffer,
"w")) == NULL) {
452 Logger::error(QString(
"I cannot open file B%1S%2.gen").arg(bi+1).arg(this->currentSeed));
455 if ((fp=fopen(sbuffer,
"a")) == NULL) {
456 Logger::error(QString(
"I cannot open file B%1S%2.gen").arg(bi+1).arg(this->currentSeed));
460 fprintf(fp,
"**NET : s%d_%d.wts\n",cgen,bx);
470 for(bi=0;bi<this->nreproducing;bi++)
471 for(i =0;i< this->noffspring;i++) {
472 if(this->elitism && bi==0)
481 for (i=0;i<this->popSize;i++) tfitness[i]=9999.0;
489 for(
int i = 0; i < this->popSize; i++) {
490 QString output = QString(
"Fit %1 | ").arg(tfitness[i]);
491 for(
int l = 0; l < this->glen; l++) {
492 output += QString(
"%1 ").arg(this->genome[i][l]);
500 for(
int i = 0; i < bestgenome.size(); i++) {
501 QString output = QString(
"Best %d | ").arg(i);
502 for (
int s = 0; s < this->glen; s++) {
503 output += QString(
"%1 ").arg(this->bestgenome[i][s]);
517 for(i=0;i<this->popSize;i++) {
518 if(tfitness[i]<min) min=tfitness[i];
519 if(tfitness[i]>max) max=tfitness[i];
522 this->faverage=av/(double)this->popSize;
525 this->statfit[this->cgen][0]=this->fmax;
526 this->statfit[this->cgen][1]=this->faverage;
527 this->statfit[this->cgen][2]=this->fmin;
541 for(i=0;i<this->popSize;i++) {
542 if((tfitness[i]/ntfitness[i])<min) {
543 min=tfitness[i]/ntfitness[i];
545 if((tfitness[i]/ntfitness[i])>max) max=tfitness[i]/ntfitness[i];
546 av+=(tfitness[i]/ntfitness[i]);
548 this->faverage=av/(double)this->popSize;
551 this->statfit[this->cgen][0]=this->fmax;
552 this->statfit[this->cgen][1]=this->faverage;
553 this->statfit[this->cgen][2]=this->fmin;
559 fprintf(fp,
"DYNAMICAL NN\n");
560 for (j=0; j < this->glen; j++)
561 fprintf(fp,
"%d\n", this->genome[ind][j]);
562 fprintf(fp,
"END\n");
572 sprintf(filename,
"G%dS%d.gen",cgen,currentSeed);
573 if ((fp=fopen(filename,
"w+")) == NULL) {
577 for(i=0;i<this->popSize;i++) {
578 fprintf(fp,
"**NET : %d_%d_%d.wts\n",cgen,0,i);
589 sprintf(sbuffer,
"statS%d.fit",currentSeed);
591 fp=fopen(sbuffer ,
"w");
593 fp=fopen(sbuffer ,
"a");
596 fprintf(fp,
"%.3f %.3f %.3f\n",fmax,faverage,fmin);
613 fscanf(fp,
"DYNAMICAL NN\n");
614 for (j=0; j <this->glen; j++) {
615 fscanf(fp,
"%d\n",&v);
616 this->genome[ind][j]=v;
629 sprintf(filename,
"G%dS%d.gen", gen, seed);
631 sprintf(filename,
"%s", filew);
634 if ((fp = fopen(filename,
"r")) != NULL) {
638 fscanf(fp,
"%s : %s\n", flag, message);
639 if (strcmp(flag,
"**NET") == 0) {
645 Logger::info(QString(
"Loaded ind: %1").arg(genome.size()));
648 Logger::error(QString(
"File %1 could not be opened").arg(filename));
651 loadedIndividuals = genome.size();
653 return genome.size();
666 if ((fp=fopen(filename,
"r")) != NULL) {
667 while(fscanf(fp,
"%f %f %f\n",&max,&av,&min)!=EOF) {
668 this->statfit[i][0]=
max;
669 this->statfit[i][1]=av;
670 this->statfit[i][2]=
min;
684 for (
int i = 0; i < genome.size(); i++) {
685 for(
int g = 0; g < glen; g++) {
686 genome[i][g] =
mrand(256);
696 for(i=0; i<genome.size(); i++)
697 for(g=0; g<glen; g++)
700 genome[i][g] =
mrand(256);
702 genome[i][g] = ge[g];
709 for(
int i=0; i<glen; i++)
710 mutations[i] = mut[i];
715 #if defined(__GNUC__) && defined(DEVELOPER_WARNINGS)
716 #warning CONTROLLARE INDICE? ALLE VOLTE CRASHA SE NELLA GUI SI SELEZIONA UN INDICE OLTRE IL MASSIMO
718 return this->genome[ind];
723 return this->bestgenome[ind];
735 Evonet* evonet = getResource<Evonet>(
"evonet" );
738 Evonet* evonet = getResource<Evonet>(
"evonet" );
758 Evonet* evonet = getResource<Evonet>(
"evonet" );
762 for (
int i = 0; i<glen; i++) {
787 int startGeneration=0;
793 genome.resize(popSize * 2);
795 final_mrate = mutation;
797 Logger::info(
"Number of replications: " + QString::number(nreplications));
800 QVector<EvaluatorThreadForEvoga*> evaluators(popSize, NULL);
801 if (numThreads > 1) {
802 for (
int i = 0; i < evaluators.size(); i++) {
807 QThreadPool::globalInstance()->setMaxThreadCount(numThreads);
810 for(rp=0;rp<nreplications;rp++) {
811 mutation=initial_mutation;
825 for (
int i=0;i<popSize+1;i++) {
832 DataChunk statTest(QString(
"stattest"),Qt::blue,2000,
false);
833 if (statTest.loadRawData(QString(statfile),0)) {
834 startGeneration=statTest.getIndex();
836 Logger::info(
"Recovering from startGeneration: " + QString::number(startGeneration));
839 cgen=startGeneration;
840 mutation=mutation-startGeneration*mutationdecay;
841 if (mutation<final_mrate) mutation=final_mrate;
843 genome.resize(popSize * 2);
847 for(gn=startGeneration;gn<nogenerations;gn++) {
852 if (numThreads <= 1) {
856 for(
id=0;
id<popSize;
id++) {
861 if (averageIndividualFitnessOverGenerations) {
873 ntfitness[popSize]=0;
878 if (averageIndividualFitnessOverGenerations) {
879 tfitness[popSize] += fit;
880 ntfitness[popSize]++;
882 tfitness[popSize] = fit;
883 ntfitness[popSize] = 1;
892 for(
int wi=0;wi<popSize;wi++) {
893 if (ntfitness[wi] == 0.0) {
896 mfit=tfitness[wi]/ntfitness[wi];
903 if ((tfitness[popSize]/ntfitness[popSize])>minfit) {
905 tfitness[minid]=tfitness[popSize];
906 ntfitness[minid]=ntfitness[popSize];
915 for (
int i = 0; i < popSize; i++) {
916 evaluators[i]->getExperiment()->initGeneration(gn);
921 for (
int i = 0; i < popSize; i++) {
922 evaluators[i]->setGenotype(i);
927 QFuture<void> evaluationFuture = QtConcurrent::map(evaluators, runEvaluatorThreadForEvoga);
928 evaluationFuture.waitForFinished();
932 for (
int i = 0; i < popSize; i++) {
933 if (averageIndividualFitnessOverGenerations) {
934 tfitness[evaluators[i]->getGenotypeId()] += evaluators[i]->getFitness();
935 ntfitness[evaluators[i]->getGenotypeId()]++;
937 tfitness[evaluators[i]->getGenotypeId()] = evaluators[i]->getFitness();
938 ntfitness[evaluators[i]->getGenotypeId()] = 1;
944 for (
int i = 0; i < popSize; i++) {
946 tfitness[popSize + i] = 0;
947 ntfitness[popSize + i] = 0;
948 evaluators[i]->setGenotype(popSize + i);
953 evaluationFuture = QtConcurrent::map(evaluators, runEvaluatorThreadForEvoga);
954 evaluationFuture.waitForFinished();
958 for (
int i = 0; i < popSize; i++) {
959 if (averageIndividualFitnessOverGenerations) {
960 tfitness[evaluators[i]->getGenotypeId()] += evaluators[i]->getFitness();
961 ntfitness[evaluators[i]->getGenotypeId()]++;
963 tfitness[evaluators[i]->getGenotypeId()] = evaluators[i]->getFitness();
964 ntfitness[evaluators[i]->getGenotypeId()] = 1;
970 for (
int i = 0; i < popSize; i++) {
971 evaluators[i]->getExperiment()->endGeneration(gn);
979 QVector<FitnessAndId> parents(popSize);
980 for (
int i = 0; i < popSize; i++) {
981 parents[i].fitness = tfitness[i] / ntfitness[i];
984 QVector<FitnessAndId> children(popSize);
985 for (
int i = 0; i < popSize; i++) {
986 children[i].fitness = tfitness[popSize + i] / ntfitness[popSize + i];
987 children[i].id = popSize + i;
995 for (
int i = 0; i < popSize; i++) {
996 if (parents[p].fitness > children[c].fitness) {
1001 copyGenes(children[c].
id, parents[popSize - 1 - c].
id, 0);
1002 tfitness[parents[popSize - 1 - c].id] = tfitness[children[c].id];
1003 ntfitness[parents[popSize - 1 - c].id] = ntfitness[children[c].id];
1018 if (mutation > final_mrate) {
1019 mutation -= mutationdecay;
1021 mutation = final_mrate;
1028 if ((savePopulationEachNGenerations == 0) || (gn>1 && ((gn-1) % (savePopulationEachNGenerations) != 0))) {
1030 sprintf(filename,
"G%dS%d.gen",gn,currentSeed);
1031 if(!QFile::remove(filename)) {
1032 Logger::warning(QString(
"Error deleting temporary gen file: ") + QString::fromStdString(filename));
1036 Logger::info(QString(
"Generation %1 took %2 minutes").arg(gn+1).arg((
double)evotimer.elapsed()/60000.0, 0,
'f', 2));
1043 for (
int i = 0; i < evaluators.size(); i++) {
1044 delete evaluators[i];
1057 int startGeneration=0;
1062 genome.resize(popSize);
1064 for(rp=0;rp<nreplications;rp++) {
1081 DataChunk statTest(QString(
"stattest"),Qt::blue,2000,
false);
1082 if (statTest.loadRawData(QString(statfile),0)) {
1083 startGeneration=statTest.getIndex();
1085 Logger::info(
"Recovering from startGeneration: " + QString::number(startGeneration));
1091 for(gn=startGeneration;gn<nogenerations;gn++) {
1095 for(
id=0;
id<popSize;
id++) {
1109 if(savePopulationEachNGenerations!=0 && gn%savePopulationEachNGenerations == 0)
1112 Logger::info(QString(
"Generation %1 took %2 minutes").arg(gn+1).arg((
double)evotimer.elapsed()/60000.0, 0,
'f', 2));
1122 unsigned int generateRandomSeed() {
1125 unsigned long int stackMem = (
unsigned long int)( generateRandomSeed );
1128 unsigned long int startTime = GetTickCount();
1130 unsigned long int startTime = time(NULL);
1133 unsigned long int randSeed = 0;
1135 stackMem=stackMem-startTime; stackMem=stackMem-randSeed; stackMem=stackMem^(randSeed >> 13);
1136 startTime=startTime-randSeed; startTime=startTime-stackMem; startTime=startTime^(stackMem << 8);
1137 randSeed=randSeed-stackMem; randSeed=randSeed-startTime; randSeed=randSeed^(startTime >> 13);
1138 stackMem=stackMem-startTime; stackMem=stackMem-randSeed; stackMem=stackMem^(randSeed >> 12);
1139 startTime=startTime-randSeed; startTime=startTime-stackMem; startTime=startTime^(stackMem << 16);
1140 randSeed=randSeed-stackMem; randSeed=randSeed-startTime; randSeed=randSeed^(startTime >> 5);
1141 stackMem=stackMem-startTime; stackMem=stackMem-randSeed; stackMem=stackMem^(randSeed >> 3);
1142 startTime=startTime-randSeed; startTime=startTime-stackMem; startTime=startTime^(stackMem << 10);
1143 randSeed=randSeed-stackMem; randSeed=randSeed-startTime; randSeed=randSeed^(startTime >> 15);
1145 return randSeed%10000;
1154 if ( evolutionType !=
"steadyState" && evolutionType !=
"generational" ) {
1155 Logger::error(
"Evoga - evolutionType has been wrongly setted. It can assume only 'steadyState' or 'generational' values" );
1156 evolutionType =
"steadyState";
1164 if ( checkSeed ==
"auto" ) {
1165 seed = generateRandomSeed();
1167 seed = checkSeed.toInt();
1169 Logger::info( QString(
"Evoga - Random seed setted to ")+QString::number(seed) );
1175 averageIndividualFitnessOverGenerations =
ConfigurationHelper::getBool(params, prefix +
"averageIndividualFitnessOverGenerations",
true);
1188 Logger::info(
"Created EvoRobotExperiment " + params.
getValue(prefix+
"Experiment/type") +
" from group " + prefix +
"Experiment" );
1192 savedConfigurationParameters = params;
1193 savedExperimentPrefix = prefix +
"Experiment";
1206 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");
1207 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");
1208 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");
1209 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");
1213 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");
1214 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)");
1215 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");
1216 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");
1218 d.
describeBool(
"averageIndividualFitnessOverGenerations").
def(
true).
help(
"Whether to average the current fitness with the previous one or not");
1229 statfit =
new double*[nogenerations];
1231 for(
int i = 0; i < nogenerations; i++) {
1232 statfit[i] =
new double[3];
1237 mutations =
new float[glen];
1238 for(
int mi = 0; mi < glen; mi++) {
1244 popSize = noffspring * nreproducing;
1247 genome.setGenomeLength(glen);
1248 genome.resize(popSize);
1249 for (
int i = 0; i < genome.size(); i++) {
1250 for (
int r = 0; r < glen; r++) {
1256 bestgenome.setGenomeLength(glen);
1257 bestgenome.resize(nreproducing);
1264 for (
int i = 0; i < nogenerations; i++) {
1265 statfit[i][0] = 0.0;
1266 statfit[i][1] = 0.0;
1267 statfit[i][2] = 0.0;
1270 Logger::info(
"Evoga Configured - Number of genes: " + QString::number(glen));
1275 stopEvolution =
false;
1276 if ( evolutionType ==
"steadyState" ) {
1278 }
else if ( evolutionType ==
"generational" ) {
1281 Logger::error( QString(
"Evoga - request to execute a unrecognized evolution type: %1").arg(evolutionType) );
1286 stopEvolution =
true;
1287 waitForNextStep.wakeAll();
1291 if ( isStepByStep && !stopEvolution ) {
1293 mutexStepByStep.lock();
1294 waitForNextStep.wait( &mutexStepByStep );
1295 mutexStepByStep.unlock();
1297 return stopEvolution;
1301 return stopEvolution;
1305 stopEvolution =
false;
1309 isStepByStep = enable;
1312 waitForNextStep.wakeAll();
1317 return isStepByStep;
1321 waitForNextStep.wakeAll();
1331 QVector<EvoRobotExperiment*> v;
1353 return nreplications;
1357 return nogenerations;
1365 mutation = mutation_rate;
1370 return loadallg(-1, filename.toLatin1().data());
1375 return loadedIndividuals;
1385 return "statS" + QString::number(seed) + QString(
".fit");
1390 return "B0S" + QString::number(seed) + QString(
".gen");
1400 return "G" + QString::number(generation) +
"S" + QString::number(seed) + QString(
".gen");
1416 #if defined(_MSC_VER)
1417 #pragma warning(pop)