evoga.cpp
1  /********************************************************************************
2  * FARSA Experiments Library *
3  * Copyright (C) 2007-2012 *
4  * Stefano Nolfi <stefano.nolfi@istc.cnr.it> *
5  * Onofrio Gigliotta <onofrio.gigliotta@istc.cnr.it> *
6  * Gianluca Massera <emmegian@yahoo.it> *
7  * Tomassino Ferrauto <tomassino.ferrauto@istc.cnr.it> *
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  * This program is distributed in the hope that it will be useful, *
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
17  * GNU General Public License for more details. *
18  * *
19  * You should have received a copy of the GNU General Public License *
20  * along with this program; if not, write to the Free Software *
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
22  ********************************************************************************/
23 
24 #include "evoga.h"
25 #include "evodataviewer.h"
26 #include "logger.h"
27 #include "randomgenerator.h"
28 #include <configurationhelper.h>
29 #include <QVector>
30 #include <QThreadPool>
31 #include <QtConcurrentMap>
32 #include <QtAlgorithms>
33 #include <QTime>
34 #include <QFile>
35 
36 #include <cmath>
37 
38 #include <Eigen/Core>
39 #include <Eigen/Dense>
40 #include <unsupported/Eigen/MatrixFunctions>
41 
42 #include <exception>
43 
44 // All the suff below is to avoid warnings on Windows about the use of unsafe
45 // functions. This should be only a temporary workaround, the solution is stop
46 // using C string and file functions...
47 #if defined(_MSC_VER)
48  #pragma warning(push)
49  #pragma warning(disable:4996)
50 #endif
51 
52 namespace farsa {
53 
56 {
57 public:
66  m_ga(ga),
67  m_exp(exp)
68  {
69  }
70 
75  {
76  delete m_exp;
77  }
78 
84  void setGenotype(int id)
85  {
86  m_id = id;
87  m_exp->setNetParameters(m_ga->getGenes(id));
88  }
89 
95  int getGenotypeId() const
96  {
97  return m_id;
98  }
99 
103  void run()
104  {
105  m_exp->doAllTrialsForIndividual(m_id);
106  m_fitness = m_exp->getFitness();
107  }
108 
114  double getFitness() const
115  {
116  return m_fitness;
117  }
118 
125  {
126  return m_exp;
127  }
128 
129 private:
133  Evoga *const m_ga;
134 
138  EvoRobotExperiment *const m_exp;
139 
143  int m_id;
144 
148  double m_fitness;
149 };
150 
155 void runEvaluatorThreadForEvoga(EvaluatorThreadForEvoga* e)
156 {
157  e->run();
158 }
159 
162 {
163 public:
172  m_ga(ga),
173  m_exp(exp)
174  {
175  }
176 
181  {
182  delete m_exp;
183  }
184 
191  void setGenotype(int id, float* genes)
192  {
193  m_id = id;
194  m_exp->setNetParameters(genes);
195  }
196 
202  int getGenotypeId() const
203  {
204  return m_id;
205  }
206 
210  void run()
211  {
212  m_exp->doAllTrialsForIndividual(m_id);
213  m_fitness = m_exp->getFitness();
214  m_error = m_exp->getError();
215  }
216 
222  double getFitness() const
223  {
224  return m_fitness;
225  }
226 
232  double getError() const
233  {
234  return m_error;
235  }
236 
243  {
244  return m_exp;
245  }
246 
247 private:
251  Evoga *const m_ga;
252 
256  EvoRobotExperiment *const m_exp;
257 
261  int m_id;
262 
266  double m_fitness;
267 
271  double m_error;
272 };
273 
278 void runEvaluatorThreadForXnes(EvaluatorThreadForXnes* e)
279 {
280  e->run();
281 }
282 
288 {
292  float fitness;
293 
297  int id;
298 };
299 
303 bool operator<(FitnessAndId first, FitnessAndId second)
304 {
305  return (first.fitness < second.fitness);
306 }
307 
308 int Evoga::mrand(int i)
309 {
310  int r;
311 
312  r = rand();
313  r = r % (int) i;
314  return r;
315 
316 }
317 
319  : exp(NULL)
320  , popSize(1)
321  , glen(0)
322  , elitism(false)
323  , nreproducing(1)
324  , noffspring(1)
325  , genome()
326  , bestgenome()
327  , loadedIndividuals(1)
328  , tfitness(NULL)
329  , ntfitness(NULL)
330  , statfit(NULL)
331  , evolutionType()
332  , nogenerations(0)
333  , nreplications(1)
334  , seed(1)
335  , currentSeed(1)
336  , mutation(0.05)
337  , mutationdecay(0.01)
338  , initial_mutation(0.05)
339  , mutations(NULL)
340  , cgen(0)
341  , savebest(1)
342  , fmin(0.0)
343  , fmax(0.0)
344  , faverage(0.0)
345  , fbest(0.0)
346  , fbestgen(0)
347  , ccycle(0)
348  , stopEvolution(false)
349  , isStepByStep(false)
350  , mutexStepByStep()
351  , waitForNextStep()
352  , numThreads(1)
353  , savePopulationEachNGenerations(0)
354  , averageIndividualFitnessOverGenerations(true)
355  , savedConfigurationParameters()
356  , savedExperimentPrefix()
357 {
358 }
359 
361 {
362  delete exp;
363  delete[] tfitness;
364  delete[] terror;
365  if (statfit != NULL) {
366  for(int i = 0; i < nogenerations; i++) {
367  delete[] statfit[i];
368  }
369  }
370  delete[] statfit;
371  delete[] ntfitness;
372  delete[] mutations;
373 }
374 
375 void Evoga::setSeed(int s)
376 {
377  srand(s);
378  globalRNG->setSeed( s );
379  currentSeed = s;
380 }
381 
382 //return a random value between 0-1
383 double Evoga::drand()
384 {
385  return (double)rand()/(double)RAND_MAX;
386 }
387 
388 double Evoga::getNoise(double minn, double maxn)
389 {
390  double nrange;
391  if(maxn>minn)
392  nrange=maxn-minn;
393  else
394  nrange=minn-maxn;
395 
396  return drand()*nrange+minn;
397 }
398 
399 int Evoga::mutate(int w, double mut)
400 {
401  int b[8];
402  int val;
403  int ii;
404 
405  val = w;
406  for(ii=0;ii < 8;ii++) {
407  b[ii] = val % 2;
408  val = val / 2;
409  }
410  for(ii=0;ii < 8;ii++) {
411  //if (mrand(100) < percmut)
412  if(drand()<mut) {
413  b[ii] =(b[ii]+1)%2; // con questa modifica il bit switcha //mrand(2);
414  }
415  }
416  w = 0;
417  w += b[0] * 1;
418  w += b[1] * 2;
419  w += b[2] * 4;
420  w += b[3] * 8;
421  w += b[4] * 16;
422  w += b[5] * 32;
423  w += b[6] * 64;
424  w += b[7] * 128;
425 
426  return(w);
427 }
428 
429 void Evoga::putGenome(int fromgenome, int tobestgenome)
430 {
431  if (tobestgenome < this->nreproducing) {
432  for (int i = 0; i < this->glen; i++) {
433  bestgenome[tobestgenome][i] = genome[fromgenome][i];
434  }
435  } else {
436  Logger::error("putGenomeError!");
437  }
438 }
439 
440 void Evoga::getGenome(int frombestgenome, int togenome, int mut)
441 {
442  for(int i = 0; i < this->glen; i++) {
443  if (mut == 0) {
444  genome[togenome][i] = bestgenome[frombestgenome][i];
445  } else {
446  if (mutations[i] == Evonet::DEFAULT_VALUE) { //standard mutation
447  genome[togenome][i] = mutate(bestgenome[frombestgenome][i], mutation);
448  } else { //specific mutation
449  genome[togenome][i] = mutate(bestgenome[frombestgenome][i], mutations[i]);
450  }
451  }
452  }
453 }
454 
455 void Evoga::copyGenes(int from, int to, int mut)
456 {
457  for(int i = 0; i < this->glen; i++) {
458  if (mut == 0) {
459  genome[to][i] = genome[from][i];
460  } else {
461  if (mutations[i] == Evonet::DEFAULT_VALUE) { //standard mutation
462  genome[to][i] = mutate(genome[from][i], mutation);
463  } else { //specific mutation
464  genome[to][i] = mutate(genome[from][i], mutations[i]);
465  }
466  }
467  }
468 }
469 
470 //Reproduce individuals with higher ranking
472 {
473  //to do
474  //selecting best fathers
475  int i;
476  int bi,bx;
477  double bn;
478 
479  char sbuffer[64];
480  FILE *fp;
481 
482  //first of all we compute fitness stat
483  this->computeFStat();
484 
485 
486  for(bi=0;bi<this->nreproducing;bi++) {
487  bn=-9999.0;
488  bx=-1; //individual to be copied
489  for(i=0;i< this->popSize;i++) {
490  if(tfitness[i]>bn) {
491  bn=tfitness[i];
492  bx=i;
493  }
494  }
495 
496  this->putGenome(bx,bi);
497 
498  //here we save best genome
499  if ((bi+1)<=this->savebest && cgen< this->nogenerations) {
500  sprintf(sbuffer,"B%dS%d.gen",bi+1,this->currentSeed);
501  if (cgen==0) {
502  if ((fp=fopen(sbuffer, "w")) == NULL) {
503  Logger::error(QString("I cannot open file B%1S%2.gen").arg(bi+1).arg(this->currentSeed));
504  }
505  } else {
506  if ((fp=fopen(sbuffer, "a")) == NULL) {
507  Logger::error(QString("I cannot open file B%1S%2.gen").arg(bi+1).arg(this->currentSeed));
508  }
509  }
510 
511  fprintf(fp,"**NET : s%d_%d.wts\n",cgen,bx);
512  saveagenotype(fp,bx);
513  fflush(fp);
514  fclose(fp);
515  }
516  tfitness[bx]=-9999.0;
517  }
518 
519  //reproducing best
520  bx=0;
521  for(bi=0;bi<this->nreproducing;bi++)
522  for(i =0;i< this->noffspring;i++) {
523  if(this->elitism && bi==0)
524  this->getGenome(bi,bx,0);
525  else
526  this->getGenome(bi,bx,1);// 1 mette mutazione
527 
528  bx++;
529  }
530 
531  //resetting fitness
532  for (i=0;i<this->popSize;i++) tfitness[i]=0.0;
533  this->saveFStat();
534  cgen++;
535 }
536 
538 {
539  //to do
540  //selecting best fathers
541  int i;
542  int bi;
543  double bn, ffit;
544  bn=-999999.0;// it was 0 possible source of bug in case of negsative fitness
545  bi=-1;
546 
547  char sbuffer[64];
548  FILE *fp;
549 
550  sprintf(sbuffer,"B%dS%d.gen",bi+1,this->currentSeed);
551  if (cgen==0) {
552  if ((fp=fopen(sbuffer, "w")) == NULL) {
553  Logger::error(QString("I cannot open file B%1S%2.gen").arg(bi+1).arg(this->currentSeed));
554  }
555  } else {
556  if ((fp=fopen(sbuffer, "a")) == NULL) {
557  Logger::error(QString("I cannot open file B%1S%2.gen").arg(bi+1).arg(this->currentSeed));
558  }
559  }
560 
561  //finding the best simply the best, one individual
562  for(i=0;i<this->popSize;i++) {
563  ffit=this->tfitness[i]/this->ntfitness[i];
564  if(ffit>bn) {
565  bn=ffit;
566  bi=i;
567  }
568  }
569 
570  //now saving
571  fprintf(fp,"**NET : s%d_%d.wts\n",cgen,bi);
572  saveagenotype(fp,bi);
573  fflush(fp);
574  fclose(fp);
575 }
576 
577 void Evoga::saveBestTeam(QVector< QVector<int> > teams, QVector<double> fitness)
578 {
579  //to do
580  //selecting best fathers
581  int i;
582  int bi;
583  double bn, ffit;
584  bn=-999999.0;// it was 0 possible source of bug in case of negsative fitness
585  bi=-1;
586  double max;
587  int indMax;
588 
589  char sbuffer[64];
590  FILE *fp;
591 
592  sprintf(sbuffer,"B%dS%d.G%d.gen",bi+1,this->currentSeed,cgen);
593  if ((fp=fopen(sbuffer, "w")) == NULL) {
594  Logger::error(QString("I cannot open file B%1S%2.G%3.gen").arg(bi+1).arg(this->currentSeed).arg(cgen));
595  }
596 
597  max = fitness[0];
598  indMax = 0;
599  for(int i=1;i<fitness.size();i++){
600  if(fitness[i]>max){
601  max = fitness[i];
602  indMax = i;
603  }
604  }
605 
606  for(int i=0;i<numModules;i++){
607  //now saving
608  fprintf(fp,"**NET : s%d_%d.wts\n",cgen,teams[indMax][i]);
609  saveagenotype(fp,teams[indMax][i]);
610  }
611  fclose(fp);
612  fflush(fp);
613 }
614 
615 
616 //Reproduce individuals with higher ranking
618 {
619  //to do
620  //selecting best fathers
621  int i;
622  int bi,bx;
623  double bn;
624 
625  char sbuffer[64];
626  FILE *fp;
627 
628  //first of all we compute fitness stat
629  this->computeFStat();
630 
631 
632  for(bi=0;bi<this->nreproducing;bi++) {
633  bn=9999.0;
634  bx=-1; //individual to be copied
635  for(i=0;i< this->popSize;i++) {
636  if(tfitness[i]<bn) {
637  bn=tfitness[i];
638  bx=i;
639  }
640  }
641 
642  this->putGenome(bx,bi);
643 
644  //here we save best genome
645  if ((bi+1)<=this->savebest && cgen< this->nogenerations) {
646  sprintf(sbuffer,"B%dS%d.gen",bi+1,this->currentSeed);
647  if (cgen==0) {
648  if ((fp=fopen(sbuffer, "w")) == NULL) {
649  Logger::error(QString("I cannot open file B%1S%2.gen").arg(bi+1).arg(this->currentSeed));
650  }
651  } else {
652  if ((fp=fopen(sbuffer, "a")) == NULL) {
653  Logger::error(QString("I cannot open file B%1S%2.gen").arg(bi+1).arg(this->currentSeed));
654  }
655  }
656 
657  fprintf(fp,"**NET : s%d_%d.wts\n",cgen,bx);
658  saveagenotype(fp,bx);
659  fflush(fp);
660  fclose(fp);
661  }
662  tfitness[bx]=9999.0;
663  }
664 
665  //reproducing best
666  bx=0;
667  for(bi=0;bi<this->nreproducing;bi++)
668  for(i =0;i< this->noffspring;i++) {
669  if(this->elitism && bi==0)
670  this->getGenome(bi,bx,0);
671  else
672  this->getGenome(bi,bx,1);
673 
674  bx++;
675  }
676 
677  //resetting fitness
678  for (i=0;i<this->popSize;i++) tfitness[i]=9999.0;
679  this->saveFStat();
680  cgen++;
681 }
682 
683 
685 {
686  for(int i = 0; i < this->popSize; i++) {
687  QString output = QString("Fit %1 | ").arg(tfitness[i]);
688  for(int l = 0; l < this->glen; l++) {
689  output += QString("%1 ").arg(this->genome[i][l]);
690  }
691  Logger::info(output);
692  }
693 }
694 
696 {
697  for(int i = 0; i < bestgenome.size(); i++) {
698  QString output = QString("Best %d | ").arg(i);
699  for (int s = 0; s < this->glen; s++) {
700  output += QString("%1 ").arg(this->bestgenome[i][s]);
701  }
702  Logger::info(output);
703  }
704 }
705 
707 {
708  int i;
709  double min, max, av;
710 
711  min=max=tfitness[0];
712  av=0.0;
713 
714  for(i=0;i<this->popSize;i++) {
715  if(tfitness[i]<min) min=tfitness[i];
716  if(tfitness[i]>max) max=tfitness[i];
717  av+=tfitness[i];
718  }
719  this->faverage=av/(double)this->popSize;
720  this->fmax=max;
721  this->fmin=min;
722  this->statfit[this->cgen][0]=this->fmax;
723  this->statfit[this->cgen][1]=this->faverage;
724  this->statfit[this->cgen][2]=this->fmin;
725 
726  if (this->fmax > this->fbest) {
727  this->fbest = this->fmax;
728  this->fbestgen = this->cgen;
729  }
730 }
731 
733 {
734  int i;
735  double min, max, av;
736 
737  //min=max=tfitness[0]/ntfitness[0];
738  //try to fix a problem
739  min=9999.00;
740  max=-9999.00;
741  av=0.0;
742 
743  for(i=0;i<this->popSize;i++) {
744  if((tfitness[i]/ntfitness[i])<min) {
745  min=tfitness[i]/ntfitness[i];
746  }
747  if((tfitness[i]/ntfitness[i])>max) max=tfitness[i]/ntfitness[i];
748  av+=(tfitness[i]/ntfitness[i]);
749  }
750  this->faverage=av/(double)this->popSize;
751  this->fmax=max;
752  this->fmin=min;
753  this->statfit[this->cgen][0]=this->fmax;
754  this->statfit[this->cgen][1]=this->faverage;
755  this->statfit[this->cgen][2]=this->fmin;
756 
757  if (this->fmax > this->fbest) {
758  this->fbest = this->fmax;
759  this->fbestgen = this->cgen;
760  }
761 }
762 
763 void Evoga::saveagenotype(FILE *fp, int ind)
764 {
765  int j;
766  fprintf(fp, "DYNAMICAL NN\n");
767  for (j=0; j < this->glen; j++)
768  fprintf(fp, "%d\n", this->genome[ind][j]);
769  fprintf(fp, "END\n");
770 }
771 
772 //save all current generation
774 {
775  FILE *fp;
776  char filename[64];
777  int i;
778 
779  sprintf(filename,"G%dS%d.gen",cgen,currentSeed);
780  if ((fp=fopen(filename, "w+")) == NULL) {
781  Logger::error(QString("Cannot open file %1").arg(filename));
782  } else {
783  //we save
784  for(i=0;i<this->popSize;i++) {
785  fprintf(fp,"**NET : %d_%d_%d.wts\n",cgen,0,i);
786  this->saveagenotype(fp,i);
787  }
788  fclose( fp );
789  }
790 }
791 
792 void Evoga::saveallgComposed(QVector< QVector<int> > composedGen)
793 {
794  FILE *fp;
795  char filename[64];
796  int i;
797 
798  sprintf(filename,"G%dS%d.composed.gen",cgen,currentSeed);
799  if ((fp=fopen(filename, "w+")) == NULL) {
800  Logger::error(QString("Cannot open file %1").arg(filename));
801  } else {
802  //we save
803  for(i=0;i<composedGen.size();i++) {
804  fprintf(fp,"**TEAM : %d_%d_%d.wts\n",cgen,0,i);
805  for(int j=0;j<numModules;j++)
806  fprintf(fp,"%d ",composedGen[i][j]);
807 
808  fprintf(fp, "\nEND\n");
809  }
810  fclose( fp );
811  }
812 }
813 
814 
816 {
817  FILE *fp;
818  char sbuffer[128];
819  sprintf(sbuffer,"statS%d.fit",currentSeed);
820  if (cgen == 0)
821  fp=fopen(sbuffer , "w");
822  else
823  fp=fopen(sbuffer , "a");
824 
825  if (fp != NULL) {
826  fprintf(fp,"%.3f %.3f %.3f\n",fmax,faverage,fmin);
827  fclose(fp);
828  } else
829  Logger::error("unable to save statistics on a file");
830 }
831 
832 void Evoga::saveRStat(QVector<int> subsVec)
833 {
834  FILE *fp;
835  char sbuffer[128];
836  sprintf(sbuffer,"statS%d.ret",currentSeed);
837 
838  if (cgen == 0)
839  fp=fopen(sbuffer , "w");
840  else
841  fp=fopen(sbuffer , "a");
842 
843  if(fp!=NULL){
844  for(int i=0;i<subsVec.size();i++){
845  fprintf(fp,"%i ",subsVec[i]);
846  }
847  fprintf(fp,"\n");
848  fclose(fp);
849  } else
850  Logger::error("unable to save statistics of retentions on a file");
851 }
852 
853 void Evoga::getLastFStat( double &min, double &max, double &average ) {
854  min = fmin;
855  max = fmax;
856  average = faverage;
857 }
858 
859 void Evoga::loadgenotype(FILE *fp, int ind)
860 {
861  int j;
862  int v;
863 
864  fscanf(fp, "DYNAMICAL NN\n");
865  for (j=0; j <this->glen; j++) {
866  fscanf(fp,"%d\n",&v);//this->genome[ind][j]);
867  this->genome[ind][j]=v;
868  }
869  fscanf(fp, "END\n");
870 }
871 
872 int Evoga::loadallg(int gen, const char *filew)
873 {
874  FILE *fp;
875  char filename[512];//[64];
876  char message[512];//[128];
877  char flag[512];//[64];
878 
879  if (gen >= 0) {
880  sprintf(filename, "G%dS%d.gen", gen, seed);
881  } else {
882  sprintf(filename, "%s", filew);//in case of B%P$S.gen
883  }
884 
885  if ((fp = fopen(filename, "r")) != NULL) {
886  genome.clear();
887  while (true) {
888  flag[0] = '\0'; //sprintf(flag,""); //flag = NULL;
889  fscanf(fp, "%s : %s\n", flag, message);
890  if (strcmp(flag, "**NET") == 0) {
891  loadgenotype(fp, genome.addOne());
892  } else {
893  break;
894  }
895  }
896  Logger::info(QString("Loaded ind: %1").arg(genome.size()));
897  fclose(fp);
898  } else {
899  Logger::error(QString("File %1 could not be opened").arg(filename));
900  }
901 
902  loadedIndividuals = genome.size();
903 
904  return genome.size();
905 }
906 
907 void Evoga::loadallTeams(int gen, const char *filew, QVector< QVector<int> > &teams)
908 {
909  FILE *fp;
910  char filename[512];//[64];
911  char message[512];//[128];
912  char flag[512];//[64];
913 
914  if (gen >= 0) {
915  sprintf(filename, "G%dS%d.composed.gen", gen, seed);
916  } else {
917  sprintf(filename, "%s", filew);//in case of B%P$S.gen
918  }
919 
920  if ((fp = fopen(filename, "r")) != NULL) {
921  int teamInd=0;
922  while (true) {
923  if(teams.size()<teamInd+1){
924  teams.resize(teamInd+1);
925  teams[teamInd].resize(numModules);
926  }
927  flag[0] = '\0'; //sprintf(flag,""); //flag = NULL;
928  fscanf(fp, "%s : %s\n", flag, message);
929  if (strcmp(flag, "**TEAM") == 0) {
930  for(int i=0;i<numModules;i++){
931 
932  fscanf(fp,"%i",&teams[teamInd][i]);
933 
934  int w=0;
935  }
936  fscanf(fp,"\n");
937  fscanf(fp, "END\n");
938  teamInd++;
939  } else {
940  break;
941  }
942  }
943  Logger::info(QString("Loaded teams: %1").arg(teamInd));
944  fclose(fp);
945  } else {
946  Logger::error(QString("File %1 could not be opened").arg(filename));
947  }
948 
949 }
950 
951 /*
952  * load a .fit file (return the number loaded individuals, 0 if the file does not exists)
953  */
954 int Evoga::loadStatistics(char *filename)
955 {
956  FILE *fp;
957  int loaded=0;
958  int i=0;
959  float max,av,min;
960  max=min=av=-1;
961  if ((fp=fopen(filename, "r")) != NULL) {
962  while(fscanf(fp,"%f %f %f\n",&max,&av,&min)!=EOF) {
963  this->statfit[i][0]=max;
964  this->statfit[i][1]=av;
965  this->statfit[i][2]=min;
966  i++;
967  }
968  loaded=i;
969  fflush(fp);
970  fclose(fp);
971  return(loaded);
972  } else {
973  return(0);
974  }
975 }
976 
978 {
979  for (int i = 0; i < genome.size(); i++) {
980  for(int g = 0; g < glen; g++) {
981  genome[i][g] = mrand(256);
982  }
983  }
984 }
985 
987 {
988  int i,g;
989 
990  //fill genome with .phe parameters
991  for(i=0; i<genome.size(); i++)
992  for(g=0; g<glen; g++)
993  {
994  if(ge[g] == Evonet::DEFAULT_VALUE)
995  genome[i][g] = mrand(256);
996  else
997  genome[i][g] = ge[g];
998  }
999 }
1000 
1001 void Evoga::setMutations(float* mut)
1002 {
1003  //fill mutation vector
1004  for(int i=0; i<glen; i++)
1005  mutations[i] = mut[i];
1006 }
1007 
1008 int* Evoga::getGenes(int ind)
1009 {
1010 #if defined(__GNUC__) && defined(DEVELOPER_WARNINGS)
1011  #warning CONTROLLARE INDICE? ALLE VOLTE CRASHA SE NELLA GUI SI SELEZIONA UN INDICE OLTRE IL MASSIMO
1012 #endif
1013  return this->genome[ind];
1014 }
1015 
1016 int* Evoga::getBestGenes(int ind)
1017 {
1018  return this->bestgenome[ind];
1019 }
1020 
1022 {
1023  this->cgen=0;
1024 }
1025 
1027 {
1028  ResourcesLocker locker(this);
1029 
1030  Evonet* evonet = getResource<Evonet>( "evonet" );
1031  if (evonet->pheFileLoaded()) {
1032  //temporary mutations vector
1033  Evonet* evonet = getResource<Evonet>( "evonet" );
1034  float* muts = new float[evonet->freeParameters()];
1035  int* pheParams = new int[evonet->freeParameters()];
1036 
1037  //setting the mutation vector
1038  evonet->getMutations(muts); //taking it from the net
1039  setMutations(muts); //pushing it inside GA
1040 
1041  //setting initial genome
1042  evonet->copyPheParameters(pheParams); //copy *phe parameters
1043  setInitialPopulation(pheParams); //put *phe parameters inside genome
1044 
1045  delete[] muts;
1046  delete[] pheParams;
1047  }
1048 }
1049 
1051 
1052  ResourcesLocker locker(this);
1053  Evonet* evonet = getResource<Evonet>( "evonet" );
1054 
1055  float wrange = evonet->getWrange();
1056 
1057  for (int i = 0; i<glen; i++) {
1058  genome[ind][i] = -(evonet->getFreeParameter(i)-wrange)/(2*wrange)*255;
1059  }
1060  /*
1061  printf("%s : %d : ",__PRETTY_FUNCTION__,ind);
1062  for (int i = 0; i<glen; i++) {
1063  printf("%d ",genome[ind][i]);
1064  }
1065  printf("\n");
1066  */
1067 }
1068 
1069 QString Evoga::getEvolutionType()
1070 {
1071  return evolutionType;
1072 }
1073 
1074 float* Evoga::xnesGetGenes(int ind)
1075 {
1076  return genotypes[ind];
1077 }
1078 
1079 void Evoga::saveBestFitness()
1080 {
1081  FILE *fp;
1082  char sbuffer[128];
1083  sprintf(sbuffer, "bestgenS%d.fit", currentSeed);
1084  if (cgen == 0)
1085  {
1086  fp = fopen(sbuffer, "w");
1087  }
1088  else
1089  {
1090  fp = fopen(sbuffer, "a");
1091  }
1092 
1093  if (fp != NULL)
1094  {
1095  fprintf(fp, "%d %.3f\n", fbestgen, fbest);
1096  fclose(fp);
1097  }
1098  else
1099  {
1100  Logger::error("unable to save best generation statistics on a file");
1101  }
1102 }
1103 
1104 void Evoga::xnesComputeStats()
1105 {
1106  int i;
1107  double min, max, av;
1108 
1109  min = 9999.00;
1110  max = -9999.00;
1111  av = 0.0;
1112 
1113  for(i = 0; i < genotypes.size(); i++)
1114  {
1115  if((tfitness[i] / ntfitness[i]) < min)
1116  {
1117  min = tfitness[i] / ntfitness[i];
1118  }
1119  if((tfitness[i] / ntfitness[i]) > max)
1120  {
1121  max = tfitness[i] / ntfitness[i];
1122  }
1123  av += (tfitness[i] / ntfitness[i]);
1124  }
1125  this->faverage = av / (double)genotypes.size();
1126  this->fmax = max;
1127  this->fmin = min;
1128  this->statfit[this->cgen][0] = this->fmax;
1129  this->statfit[this->cgen][1] = this->faverage;
1130  this->statfit[this->cgen][2] = this->fmin;
1131 
1132  if (this->fmax > this->fbest) {
1133  this->fbest = this->fmax;
1134  this->fbestgen = this->cgen;
1135  }
1136 }
1137 
1138 void Evoga::xnesSaveStats()
1139 {
1140  FILE *fp;
1141  char sbuffer[128];
1142  sprintf(sbuffer, "statS%d.fit", currentSeed);
1143  if (cgen == 0)
1144  {
1145  fp = fopen(sbuffer, "w");
1146  }
1147  else
1148  {
1149  fp = fopen(sbuffer, "a");
1150  }
1151 
1152  if (fp != NULL)
1153  {
1154  fprintf(fp, "%.3f %.3f %.3f\n", fmax, faverage, fmin);
1155  fclose(fp);
1156  }
1157  else
1158  {
1159  Logger::error("unable to save statistics on a file");
1160  }
1161 }
1162 
1163 void Evoga::xnesSaveGen(FILE *fp, float* genotype)
1164 {
1165  int j;
1166  fprintf(fp, "DYNAMICAL NN\n");
1167  for (j = 0; j < this->glen; j++)
1168  {
1169  fprintf(fp, "%lf\n", genotype[j]);
1170  }
1171  fprintf(fp, "END\n");
1172 }
1173 
1174 void Evoga::xnesSaveAllGen()
1175 {
1176  FILE *fp;
1177  char filename[64];
1178  int i;
1179 
1180  sprintf(filename, "G%dS%d.gen", cgen, currentSeed);
1181  if ((fp = fopen(filename, "w+")) == NULL)
1182  {
1183  Logger::error(QString("Cannot open file %1").arg(filename));
1184  }
1185  else
1186  {
1187  //we save
1188  for(i = 0; i < genotypes.size(); i++)
1189  {
1190  fprintf(fp, "**NET : %d_%d_%d.wts\n", cgen, 0, i);
1191  this->xnesSaveGen(fp, genotypes[i]);
1192  }
1193  fclose(fp);
1194  }
1195 }
1196 
1197 void Evoga::xnesSaveBest(int bi)
1198 {
1199  char sbuffer[64];
1200  FILE *fp;
1201 
1202  sprintf(sbuffer, "B%dS%d.gen", 0, this->currentSeed);
1203  if (cgen==0)
1204  {
1205  if ((fp = fopen(sbuffer, "w")) == NULL)
1206  {
1207  Logger::error(QString("I cannot open file B%1S%2.gen").arg(0).arg(this->currentSeed));
1208  }
1209  }
1210  else
1211  {
1212  if ((fp=fopen(sbuffer, "a")) == NULL)
1213  {
1214  Logger::error(QString("I cannot open file B%1S%2.gen").arg(0).arg(this->currentSeed));
1215  }
1216  }
1217 
1218  //now saving
1219  fprintf(fp, "**NET : s%d_%d.wts\n", cgen, bi);
1220  xnesSaveGen(fp, genotypes[bi]);
1221  fflush(fp);
1222  fclose(fp);
1223 }
1224 
1225 void Evoga::xnesSaveBestPhe(int gen, int bi)
1226 {
1227  char sbuffer[64];
1228  sprintf(sbuffer, "BestPheG%dS%d.phe", gen, this->currentSeed);
1229  exp->getNeuralNetwork()->save_net_blocks(sbuffer, 1);
1230 }
1231 
1232 void Evoga::xnesLoadGen(FILE *fp, int ind)
1233 {
1234  int j;
1235  float v;
1236 
1237  fscanf(fp, "DYNAMICAL NN\n");
1238  for (j = 0; j < this->glen; j++)
1239  {
1240  fscanf(fp, "%f\n", &v);
1241  //printf("Read %lf\n", v);
1242  genotypes[ind][j] = v;
1243  }
1244  fscanf(fp, "END\n");
1245 }
1246 
1247 int Evoga::xnesLoadAllGen(int gen, const char *filew)
1248 {
1249  FILE *fp;
1250  char filename[512];
1251  char message[512];
1252  char flag[512];
1253  int index;
1254 
1255  if (gen >= 0)
1256  {
1257  sprintf(filename, "G%dS%d.gen", gen, seed);
1258  }
1259  else
1260  {
1261  sprintf(filename, "%s", filew);//in case of B%P$S.gen
1262  }
1263 
1264  if ((fp = fopen(filename, "r")) != NULL)
1265  {
1266  genotypes.clear();
1267  while (true)
1268  {
1269  //printf("size of genotypes: %d\n", genotypes.size());
1270  flag[0] = '\0';
1271  fscanf(fp, "%s : %s\n", flag, message);
1272  if (strcmp(flag, "**NET") == 0)
1273  {
1274  genotypes.append(new float[glen]);
1275  index = genotypes.size() - 1;
1276  xnesLoadGen(fp, index);
1277  }
1278  else
1279  {
1280  break;
1281  }
1282  }
1283  Logger::info(QString("Loaded ind: %1").arg(index));
1284  fclose(fp);
1285  }
1286  else
1287  {
1288  Logger::error(QString("File %1 could not be opened").arg(filename));
1289  }
1290 
1291  loadedIndividuals = genotypes.size();
1292 
1293  return genotypes.size();
1294 }
1295 
1296 /*
1297  * Main function of the xNES algorithm (exponential Natural Evolution Strategies)
1298  */
1300 {
1301  // ALL VARIABLES ARE INITIALIZED TO AVOID NUMERICAL PROBLEMS
1302 
1303  int rp; //replication
1304  int gn; //generation
1305  const float genLen = (const float)glen; // Floating point genome length
1306  float offspringSize = 4.0 + floor(3.0 * log(genLen)); // Floating point number of offspring generated by the individual
1307  // If xnes must be combined with backpropagation in the experimental way,
1308  // add an element to the offspring population (the one obtained by applying backpropagation)
1309  if (xnesCombination)
1310  {
1311  if (xnesCombinationType > 0)
1312  {
1313  offspringSize += 1.0;
1314  }
1315  }
1316  const int offSize = (const int)floor(offspringSize); // Number of offspring generated by the individual
1317  Eigen::VectorXf ind(glen); // The individual from which the offspring will be generated
1318  Eigen::VectorXf dInd(glen); // The update of the individual
1319  Eigen::MatrixXf covMatrix(glen,glen); // Covariance Matrix
1320  Eigen::MatrixXf dCovM(glen,glen); // The update of the covariance matrix
1321  Eigen::MatrixXf expCovM(glen,glen); // Exponential matrix of CovM
1322  float etaInd; // Learning rate for the individual
1323  float etaCovM; // Learning rate for the covariance matrix
1324  Eigen::VectorXf utility(offSize); // Array containing the utility values
1325  float utilSum; // Sum of utility values
1326  float tmp; // Temporary variable
1327  Eigen::VectorXf orderedUtility(offSize); // Array containing the ordered utilities (i.e. the best individual has the highest utility value)
1328  float ordUtilSum; // Sum of ordered utility values (it shall be equal to 1.0)
1329  QVector<float> f(offSize); // Array containing the fitness of the offspring
1330  Eigen::VectorXf ordf(offSize); // Array containing the ordered fitness of the offspring
1331  QVector<int> ordoff(offSize); // Array containing the ordered indices of the offspring
1332  float* currOffspring = new float[glen]; // Current offspring
1333  Eigen::MatrixXf eye(glen,glen); // Identity matrix
1334  // Indices
1335  int i = 0;
1336  int j = 0;
1337  // Start generation index
1338  int startGeneration;
1339  // File descriptors
1340  char statfile[128];
1341  char genFile[128];
1342  char filename[64];
1343  // Default mutation range (it is used only if the <useGaussian> flag is set to false;
1344  // it defines the default interval for mutation values).
1345  const double defaultMutationRange = 0.5;
1346  // Use <variableStdDev> flag to se the initial value
1347  bool startVariableStdDev;
1348  double startOffspringStdDev = offspringStdDev;
1349  // Decay of standard deviation used to generate offspring
1350  // (this variable is used to reduce the fitness search space)
1351  const double stdDevDecay = 0.05;
1352  // Matrix of freeps (it is needed to compute and save the best phenotype)
1353  float** offspringFreep = new float*[offSize];
1354  for (j = 0; j < offSize; j++)
1355  {
1356  offspringFreep[j] = new float[glen];
1357  for (i = 0; i < glen; i++)
1358  {
1359  offspringFreep[j][i] = 0.0;
1360  }
1361  }
1362  // Array of backpropagation weight update
1363  float* backpropfreep = new float[glen];
1364  float* oldbackpropfreep = new float[glen];
1365  // File descriptors
1366  FILE *fp;
1367  FILE *backpropfp;
1368  FILE *offspringfp;
1369  Eigen::VectorXf oldInd(glen); // The individual from which the offspring will be generated
1370  for (i = 0; i < glen; i++)
1371  {
1372  // Initialize the old individual
1373  oldInd[i] = 0.0;
1374  // Initialize the backpropagation update and its old value
1375  backpropfreep[i] = 0.0;
1376  oldbackpropfreep[i] = 0.0;
1377  }
1378  Eigen::MatrixXf parents(numStartInd,glen); // To avoid seed dependency, try different parents and choose the best one
1379  float* parentFitness = new float[numStartInd];
1380 
1381  for (j = 0; j < numStartInd; j++)
1382  {
1383  // Initialize parents and their fitnesses
1384  parentFitness[j] = 0.0;
1385  for (i = 0; i < glen; i++)
1386  {
1387  parents(j,i) = 0.0;
1388  }
1389  }
1390 
1391  // Flags whether to print value for debugging
1392  const bool debugPrint = debugPrintInfoToFile;
1393 
1394  // Data for the last generation
1395  float* lastGenInd = new float[glen];
1396  for (int i = 0; i < glen; i++)
1397  {
1398  lastGenInd[i] = 0.0;
1399  }
1400  float lastGenIndFit;
1401 
1402  // Resize genotypes
1403  genotypes.resize(offSize);
1404 
1405  Logger::info("EVOLUTION: xNES");
1406  Logger::info("Number of replications: " + QString::number(nreplications));
1407 
1408  startGeneration = 0;
1409 
1410  // Initialize XNES parameters
1411  etaInd = 1.0;
1412  if (standardNes)
1413  {
1414  // Standard value (i.e. the one described in the paper)
1415  etaCovM = (9.0 + 3.0 * log(genLen)) / (5.0 * genLen * sqrt(genLen));
1416  }
1417  else
1418  {
1419  // Value retrieved from MATLAB implementation
1420  etaCovM = 0.25;
1421  if (etaCovM > 1.0 / genLen)
1422  {
1423  etaCovM = 1.0 / genLen;
1424  }
1425  etaCovM *= 0.5;
1426  }
1427  utilSum = 0.0;
1428  // Calculate the utility values before normalization
1429  for (j = 0; j < offSize; j++)
1430  {
1431  // u[j] is equal to the uttermost between 0 and (log(lambda / 2 + 1) - log(j))
1432  tmp = log(offspringSize / 2.0 + 1.0) - log((float)j + 1.0); // Remember that log(0) = -Inf, so 1 is added to index i
1433  if (tmp < 0.0)
1434  {
1435  tmp = 0.0;
1436  }
1437  utility[j] = tmp;
1438  // Update the sum of utility values
1439  utilSum += utility[j];
1440  }
1441  // Normalize the utility values
1442  for (j = 0; j < offSize; j++)
1443  {
1444  if (utilSum != 0.0)
1445  {
1446  utility[j] /= utilSum;
1447  }
1448  if (standardNes)
1449  {
1450  utility[j] -= 1.0 / genLen; // In the standard version, utility values might be negative
1451  }
1452  }
1453 
1454  for (i = 0; i < glen; i++)
1455  {
1456  // Define the identity matrix
1457  eye(i,i) = 1.0;
1458  for (j = 0; j < glen; j++)
1459  {
1460  if (i != j)
1461  {
1462  eye(i,j) = 0.0;
1463  }
1464  // Initialize covariance matrix, its update and its exponential
1465  covMatrix(i,j) = 0.0;
1466  dCovM(i,j) = 0.0;
1467  expCovM(i,j) = 0.0;
1468  }
1469  // Initialize individual and its update
1470  ind[i] = 0.0;
1471  dInd[i] = 0.0;
1472  // Initialize the current offspring
1473  currOffspring[i] = 0.0;
1474  }
1475 
1476  if (!useGaussian)
1477  {
1478  // Set mutation range to default value if it is equal to 0
1479  // (this parameter is used only in case the <useGaussian>
1480  // flag is set to false)
1481  if (mutationRange == 0.0)
1482  {
1483  mutationRange = defaultMutationRange;
1484  }
1485  if (offspringMutRange == 0.0)
1486  {
1487  offspringMutRange = defaultMutationRange;
1488  }
1489  }
1490 
1491  // Creating evaluator objects in case of a multithread simulation. Also setting the actual number of threads used
1492  QVector<EvaluatorThreadForXnes*> evaluators(offSize, NULL);
1493  if (numThreads > 1) {
1494  for (int i = 0; i < evaluators.size(); i++) {
1496  newExp->setEvoga(this);
1497  evaluators[i] = new EvaluatorThreadForXnes(this, newExp);
1498  }
1499  QThreadPool::globalInstance()->setMaxThreadCount(numThreads);
1500  }
1501 
1502  for(rp = 0; rp < nreplications; rp++) { // replications
1503  setSeed(getStartingSeed() + rp);
1504  Logger::info(QString("Replication %1, seed: %2").arg(rp + 1).arg(getStartingSeed() + rp));
1506  // --- section runnable only if there is an Evonet object
1507  if ( hasResource( "evonet" ) ) {
1509  }
1510  emit startingReplication( rp );
1511 
1512  // Set fbest to a very low value
1513  this->fbest = -99999.0;
1514 
1515  // Resetting seed in experiments
1517  if (numThreads > 1) {
1518  for (int i = 0; i < evaluators.size(); i++) {
1519  evaluators[i]->getExperiment()->newGASeed(getCurrentSeed());
1520  }
1521  }
1522 
1523  QTime evotimer;
1524  evotimer.start();
1525  // Initialization of fitnesses
1526  for (j = 0; j < offSize; j++) {
1527  tfitness[j] = 0.0;
1528  ntfitness[j] = 0.0;
1529  terror[j] = 0.0;
1530  }
1531 
1532  //code to recovery a previous evolution: Experimental
1533  sprintf(statfile,"statS%d.fit", getStartingSeed() + rp);
1534  //now check if the file exists
1535  DataChunk statTest(QString("stattest"),Qt::blue,2000,false);
1536  if (statTest.loadRawData(QString(statfile),0)) {
1537  startGeneration=statTest.getIndex();
1538  sprintf(genFile,"G%dS%d.gen", startGeneration, getStartingSeed() + rp);
1539  Logger::info("Recovering from startGeneration: " + QString::number(startGeneration));
1540  Logger::info(QString("Loading file: ") + genFile);
1541  loadallg(-1, genFile);
1542  cgen = startGeneration;
1543  emit recoveredInterruptedEvolution( QString(statfile) );
1544  } //end evolution recovery code
1545 
1546  double oldIndVariation = 0.0;
1547 
1548  // Test <numStartInd> parents and find out the best one (this is the starting "individual")
1549 
1550  // Initialize parents
1551  for (j = 0; j < numStartInd; j++)
1552  {
1553  for (i = 0; i < glen; i++)
1554  {
1555  // The initialization depends on the type of random numbers to be extracted
1556  if (useGaussian)
1557  {
1559  }
1560  else
1561  {
1562  parents(j,i) = globalRNG->getDouble(-mutationRange, mutationRange);
1563  }
1564  }
1565  }
1566 
1567  // Test parents
1568  for (j = 0; j < numStartInd; j++)
1569  {
1570  for (i = 0; i < glen; i++)
1571  {
1572  currOffspring[i] = parents(j,i); // To avoid the definition of an additional pointer variable
1573  }
1574  // Set the ANN parameters
1575  exp->setNetParameters(currOffspring);
1576  // Perform trials for the individual (i.e. the offspring)
1578  // Calculate the fitness of the individual (i.e. the offspring)
1579  parentFitness[j] = exp->getFitness();
1580  }
1581 
1582  // Find out the best parent
1583  int bestParent = 0;
1584  double bestParentFitness = parentFitness[0];
1585  for (j = 1; j < numStartInd; j++)
1586  {
1587  if (parentFitness[j] > bestParentFitness)
1588  {
1589  // Update the best parent
1590  bestParent = j;
1591  bestParentFitness = parentFitness[j];
1592  }
1593  }
1594 
1595  // ADD CODE TO EVOLVE BEST PARENT WITH SOME STEPS OF XNES
1596  // N.B.: TO DO THIS, A FUNCTION FOR EXECUTING XNES COMPUTATION
1597  // OUTSIDE XNES MAIN FUNCTION SHALL BE DEFINED
1598 
1599  // Initialize the individual for this replication
1600  for (i = 0; i < glen; i++)
1601  {
1602  ind[i] = parents(bestParent,i);
1603  // Reset the current offspring (to avoid numerical issues)
1604  currOffspring[i] = 0.0;
1605  }
1606 
1607  // Initialize Covariance Matrix
1608  for (i = 0; i < glen; i++)
1609  {
1610  for (j = 0; j < glen; j++)
1611  {
1612  covMatrix(i,j) = 0.0;
1613  expCovM(i,j) = 0.0;
1614  }
1615  }
1616 
1617  // Initialize fitnesses, ordered offspring and ordered utilities
1618  for (j = 0; j < offSize; j++) // Remember that the last slot is reserved for the parent
1619  {
1620  f[j] = 0.0;
1621  ordf[j] = 0.0;
1622  ordoff[j] = 0.0;
1623  orderedUtility[j] = 0.0;
1624  }
1625 
1626  // Initialize the matrix of offspring freeps
1627  for (j = 0; j < offSize; j++)
1628  {
1629  for (i = 0; i < glen; i++)
1630  {
1631  offspringFreep[j][i] = 0.0;
1632  }
1633  }
1634 
1635  // CODE TO PRINT SOME DEBUG INFORMATION (i.e. THE INDIVIDUAL AT THE BEGINNING OF THE EVOLUTIONARY PROCESS)
1636  if (debugPrint)
1637  {
1638  sprintf(filename,"freepS%d.txt", currentSeed);
1639  if ((fp = fopen(filename, "a")) == NULL)
1640  {
1641  Logger::error(QString("I cannot open file freep.txt"));
1642  }
1643  for (i = 0; i < glen; i++)
1644  {
1645  fprintf(fp, "%.2f\t", ind[i]);
1646  }
1647  fprintf(fp, "\n");
1648  fflush(fp);
1649  }
1650 
1651  // Initialise <startVariableStdDev> flag
1652  startVariableStdDev = variableStdDev;
1653  offspringStdDev = startOffspringStdDev;
1654 
1655  for(gn = startGeneration; gn < nogenerations; gn++) { // generations
1656  evotimer.restart();
1657  Logger::info("Generation " + QString::number(gn));
1658  //Logger::info("Generation " + QString::number(gn + 1));
1659 
1660  // Calculate the matrix exponential
1661  Eigen::MatrixExponential<Eigen::MatrixXf>(covMatrix).compute(expCovM);
1662 
1663  // Extracting samples (i.e. generate offspring of current individual)
1664  Eigen::MatrixXf samples(glen,offSize);
1665  Eigen::MatrixXf trSamples(glen,offSize);
1666  Eigen::MatrixXf offspring(glen,offSize);
1667 
1668  for (i = 0; i < glen; i++)
1669  {
1670  for (j = 0; j < offSize; j++)
1671  {
1672  // The initialization depends on the type of random numbers to be extracted
1673  if (useGaussian)
1674  {
1676  }
1677  else
1678  {
1680  }
1681  }
1682  }
1683 
1684  if (xnesCombination && (xnesCombinationType > 0))
1685  {
1686  for (i = 0; i < glen; i++)
1687  {
1688  // The last slot is reserved to backpropagation offspring,
1689  // thus the current sample values are useless
1690  samples(i,offSize - 1) = 0.0;
1691  }
1692  }
1693 
1694  exp->initGeneration(gn);
1695 
1696  if (xnesCombination)
1697  {
1698  // Firstly test the parent
1699 
1700  for (i = 0; i < glen; i++)
1701  {
1702  currOffspring[i] = ind[i]; // This statement might sound strange (I use currOffspring to avoid defining another pointer variable)
1703  }
1704 
1705  // Set the ANN parameters
1706  exp->setNetParameters(currOffspring);
1707  // Perform trials for the individual (i.e. the offspring)
1708  exp->doAllTrialsForIndividual(offSize - 1);
1709 
1710  // If it is the last generation, save the fitness of the parent
1711  if ((gn + 1) == nogenerations)
1712  {
1713  for (i = 0; i < glen; i++)
1714  {
1715  lastGenInd[i] = exp->getNeuralNetwork()->getFreeParameter(i);
1716  }
1717  lastGenIndFit = exp->getFitness();
1718  }
1719 
1720  // Getting the backpropvector for the parent
1721  backpropfreep = exp->getNeuralNetwork()->getCopyBackPropFreep();
1722  float maxVal = backpropfreep[0];
1723  float minVal = backpropfreep[0];
1724  for (i = 1; i < glen; i++)
1725  {
1726  if (backpropfreep[i] < minVal)
1727  {
1728  minVal = backpropfreep[i];
1729  }
1730  if (backpropfreep[i] > maxVal)
1731  {
1732  maxVal = backpropfreep[i];
1733  }
1734  }
1735  // Determine which is the normalization factor for the array
1736  float normFactor = 1.0;
1737  float factor;
1738  if (fabs(minVal) > fabs(maxVal))
1739  {
1740  factor = fabs(minVal);
1741  }
1742  else
1743  {
1744  factor = fabs(maxVal);
1745  }
1746  // Compute the normalization factor for the array
1747  // N.B.: if factor is outside the range, <normFactor>
1748  // restores backprop values in the range. If factor is
1749  // inside the range, <normFactor> increases backprop
1750  // values so that at least one entry is set to range
1751  normFactor = fabs(mutationLearningRate) / factor;
1752  // Check the amplitude of the backpropagation weight update
1753  for (i = 0; i < glen; i++)
1754  {
1755  backpropfreep[i] = backpropfreep[i] * normFactor;
1756  }
1757 
1758  // CODE TO PRINT DEBUG INFORMATION ABOUT THE BACKPROPAGATION OFFSPRING
1759  if (debugPrint)
1760  {
1761  sprintf(filename,"backpropfreepS%d.txt", currentSeed);
1762  if ((backpropfp = fopen(filename, "a")) == NULL)
1763  {
1764  Logger::error(QString("I cannot open file backpropfreep.txt"));
1765  }
1766  double backpropoffset = 0.0;
1767  for (i = 0; i < glen; i++)
1768  {
1769  backpropoffset += fabs(backpropfreep[i] - oldbackpropfreep[i]);
1770  fprintf(backpropfp, "%.2f\t", backpropfreep[i]);
1771  oldbackpropfreep[i] = backpropfreep[i];
1772  }
1773  fprintf(backpropfp, "\n");
1774  fprintf(backpropfp, "offset %.2f \n", backpropoffset);
1775  fflush(backpropfp);
1776  }
1777 
1778  if (isStopped()) { // stop evolution
1779  return;
1780  }
1781 
1782  if (xnesCombinationType > 0)
1783  {
1784  // Stores the backpropagation vector in the <samples> matrix
1785  for (i = 0; i < glen; i++)
1786  {
1787  samples(i,offSize - 1) = backpropfreep[i];
1788  }
1789  // Debug information to display the offspring and the range of values
1790  // (it is useless for comparison purposes)
1791  if (debugPrint)
1792  {
1793  sprintf(filename,"offspringS%d.txt", currentSeed);
1794  if ((offspringfp = fopen(filename, "a")) == NULL)
1795  {
1796  Logger::error(QString("I cannot open file offsrping.txt"));
1797  }
1798  fprintf(offspringfp, "generation %d\n", gn);
1799  for (j = 0; j < offSize; j++)
1800  {
1801  double sampleSum = 0.0;
1802  double maxVal = -99999.0;
1803  double minVal = 99999.0;
1804  for (i = 0; i < glen; i++)
1805  {
1806  fprintf(offspringfp, "%.2f\t", samples(i,j));
1807  sampleSum += samples(i,j);
1808  if (samples(i,j) > maxVal)
1809  {
1810  maxVal = samples(i,j);
1811  }
1812  if (samples(i,j) < minVal)
1813  {
1814  minVal = samples(i,j);
1815  }
1816  }
1817  fprintf(offspringfp, "sum of values %.2f\t", sampleSum);
1818  fprintf(offspringfp, "min value %.2f\t", minVal);
1819  fprintf(offspringfp, "max value %.2f\t", maxVal);
1820  fprintf(offspringfp, "\n");
1821  }
1822  fflush(offspringfp);
1823  fclose(offspringfp);
1824  }
1825  }
1826  }
1827 
1828  // Create the offspring
1829  trSamples = expCovM * samples;
1830  for (j = 0; j < offSize; j++)
1831  {
1832  for (i = 0; i < glen; i++)
1833  {
1834  offspring(i,j) = ind[i] + trSamples(i,j);
1835  }
1836  }
1837 
1838  if (numThreads <= 1) {
1839  // Fill the current offspring
1840  for (j = 0; j < offSize; j++)
1841  {
1842  Logger::info("Offspring " + QString::number(j));
1843  for (i = 0; i < glen; i++)
1844  {
1845  currOffspring[i] = offspring(i,j);
1846  // Save offspring genotypes
1847  genotypes[j][i] = currOffspring[i];
1848  }
1849  // Set the ANN parameters
1850  exp->setNetParameters(currOffspring);
1851  // Perform trials for the individual (i.e. the offspring)
1853  // Extract the freeps for the offspring j
1854  for (i = 0; i < glen; i++)
1855  {
1856  offspringFreep[j][i] = exp->getNeuralNetwork()->getFreeParameter(i);
1857  }
1858  // Calculate the fitness of the individual (i.e. the offspring)
1859  f[j] = exp->getFitness();
1860  // Compute the error of the individual
1861  terror[j] = exp->getError();
1862 
1864  tfitness[j] += f[j];
1865  ntfitness[j]++;
1866  } else {
1867  tfitness[j] = f[j];
1868  ntfitness[j] = 1;
1869  }
1870  if (isStopped()) { // stop evolution
1871  return;
1872  }
1873  }
1874  }
1875  else
1876  {
1877  // Fill the genotypes
1878  for (j = 0; j < offSize; j++)
1879  {
1880  for (i = 0; i < glen; i++)
1881  {
1882  genotypes[j][i] = offspring(i,j);
1883  }
1884  }
1885  float* cOffspring = new float[glen];
1886  // We first evaluate all parents, so setting genotypes of parents (we have as many evaluators as individuals)
1887  for (j = 0; j < offSize; j++)
1888  {
1889  for (i = 0; i < glen; i++)
1890  {
1891  cOffspring[i] = offspring(i,j);
1892  }
1893  evaluators[j]->setGenotype(j, cOffspring);
1894  }
1895 
1896  if (commitStep()) return; // stop the evolution process
1897 
1898  // Now starting parallel evaluation of parents and wating for it to finish
1899  QFuture<void> evaluationFuture = QtConcurrent::map(evaluators, runEvaluatorThreadForXnes);
1900  evaluationFuture.waitForFinished();
1901 
1902  if (commitStep()) return; // stop the evolution process
1903 
1904  // Retrieve the free parameters
1905  for (j = 0; j < offSize; j++)
1906  {
1907  for (i = 0; i < glen; i++)
1908  {
1909  offspringFreep[j][i] = evaluators[j]->getExperiment()->getNeuralNetwork()->getFreeParameter(i);
1910  }
1911  f[j] = evaluators[j]->getFitness();
1912  // Compute the error of the individual
1913  terror[evaluators[j]->getGenotypeId()] = evaluators[j]->getError();
1914  }
1915 
1916  // We have finished evaluating parents, updating the fitness vectors
1917  for (j = 0; j < offSize; j++)
1918  {
1920  {
1921  tfitness[evaluators[j]->getGenotypeId()] += f[j];
1922  ntfitness[evaluators[j]->getGenotypeId()]++;
1923  }
1924  else
1925  {
1926  tfitness[evaluators[j]->getGenotypeId()] = f[j];
1927  ntfitness[evaluators[j]->getGenotypeId()] = 1;
1928  }
1929  }
1930  if (commitStep()) return; // stop the evolution process
1931  }
1932 
1933  if (xnesCombination && (xnesCombinationType > 0))
1934  {
1935  // Increase the fitness of the backpropagation offspring if the
1936  // corresponding flag is set to true
1938  {
1939  f[offSize - 1] += backPropOffspringFitnessIncreasePercentage * f[offSize - 1];
1940  }
1941  }
1942 
1943  // Write to a file the offset of the fitness of the backpropagation offspring
1944  // with the fitness of the best offspring (different from the backpropagation)
1945  if (debugPrint)
1946  {
1947  char backpropFitnessOffset[64];
1948  FILE* bfo;
1949  sprintf(backpropFitnessOffset,"backpropagationFitnessOffset.txt");
1950  bfo = fopen(backpropFitnessOffset, "a");
1951  if (bfo != NULL)
1952  {
1953  // Look for the best fitness;
1954  float bestFit = f[0];
1955  for (j = 1; j < offSize - 1; j++)
1956  {
1957  if (f[j] > bestFit)
1958  {
1959  bestFit = f[j];
1960  }
1961  }
1962  const float fitOffset = bestFit - f[offSize - 1];
1963  fprintf(bfo, "Best fitness\t%lf\tBack-propagation fitness\t%lf\tOffset\t%lf\n", bestFit, f[offSize - 1], fitOffset);
1964  fclose(bfo);
1965  }
1966  }
1967 
1968  // Now fitnesses have to be ordered in descending order
1969  // (in the original XNES, fitnesses are ordered in ascending order)
1970  int startIndex = 0;
1971  QVector<bool> examined(offSize);
1972  for (j = 0; j < offSize; j++)
1973  {
1974  examined[j] = false;
1975  }
1976  int countExamined = 0;
1977  while (countExamined < offSize)
1978  {
1979  bool found = false;
1980  i = 0;
1981  float minf;
1982  int indMinf;
1983  float maxf;
1984  int indMaxf;
1985  float minerr;
1986  while (i < offSize && !found)
1987  {
1988  if (!examined[i])
1989  {
1990  if (minimization)
1991  {
1992  minf = f[i];
1993  indMinf = i;
1994  }
1995  else
1996  {
1997  maxf = f[i];
1998  indMaxf = i;
1999  }
2000  minerr = terror[i];
2001  found = true;
2002  }
2003  i++;
2004  }
2005  for (j = 0; j < offSize; j++)
2006  {
2007  if (!specialUtilityRanking)
2008  {
2009  // Use the standard method to compute the utility ranking
2010  if (minimization)
2011  {
2012  if (f[j] < minf && !examined[j])
2013  {
2014  minf = f[j];
2015  indMinf = j;
2016  }
2017  }
2018  else
2019  {
2020  if (f[j] > maxf && !examined[j])
2021  {
2022  maxf = f[j];
2023  indMaxf = j;
2024  }
2025  }
2026  }
2027  else
2028  {
2029  // Use the special method to compute the utility ranking
2030  if ((countExamined % 2) == 0)
2031  {
2032  // Find the best individual depending on the fitness
2033  if (minimization)
2034  {
2035  if (f[j] < minf && !examined[j])
2036  {
2037  minf = f[j];
2038  minerr = terror[j];
2039  indMinf = j;
2040  }
2041  }
2042  else
2043  {
2044  if (f[j] > maxf && !examined[j])
2045  {
2046  maxf = f[j];
2047  minerr = terror[j];
2048  indMaxf = j;
2049  }
2050  }
2051  }
2052  else
2053  {
2054  // Find the best individual depending on the similarity error
2055  if (terror[j] < minerr && !examined[j])
2056  {
2057  if (minimization)
2058  {
2059  minf = f[j];
2060  indMinf = j;
2061  }
2062  else
2063  {
2064  maxf = f[j];
2065  indMaxf = j;
2066  }
2067  minerr = terror[j];
2068  }
2069  }
2070  }
2071  }
2072  if (xnesCombination && (xnesCombinationType > 0))
2073  {
2074  // If the combination type is 1, the backpropagation
2075  // offspring is forced to be "useful" except for the
2076  // case in which the backpropagation offspring is
2077  // actually the best/fittest
2078  if ((countExamined == backPropOffspringUtilityRank) && !examined[offSize - 1])
2079  {
2080  if (minimization)
2081  {
2082  indMinf = offSize - 1;
2083  }
2084  else
2085  {
2086  indMaxf = offSize - 1;
2087  }
2088  }
2089  }
2090  if (minimization)
2091  {
2092  ordf[startIndex] = minf;
2093  ordoff[startIndex] = indMinf;
2094  examined[indMinf] = true;
2095  }
2096  else
2097  {
2098  ordf[startIndex] = maxf;
2099  ordoff[startIndex] = indMaxf;
2100  examined[indMaxf] = true;
2101  }
2102  countExamined++;
2103  startIndex++;
2104  }
2105 
2106  // Initialize the sum of ordered utility values
2107  ordUtilSum = 0.0;
2108  // Now fill the array with the utility values
2109  for (j = 0; j < offSize; j++)
2110  {
2111  orderedUtility[ordoff[j]] = utility[j];
2112  ordUtilSum += orderedUtility[ordoff[j]];
2113  }
2114 
2115  // Compute the natural gradient for both the individual and the covariance matrix
2116 
2117  // Create a matrix whose rows contain weights * samples
2118  Eigen::MatrixXf ordUtil(glen,offSize);
2119  Eigen::MatrixXf ordUtilSamples(glen,offSize);
2120  Eigen::MatrixXf Z(offSize,glen);
2121 
2122  for (i = 0; i < glen; i++)
2123  {
2124  for (j = 0; j < offSize; j++)
2125  {
2126  ordUtil(i,j) = orderedUtility[j];
2127  }
2128  }
2129 
2130  for (i = 0; i < glen; i++)
2131  {
2132  for (j = 0; j < offSize; j++)
2133  {
2134  ordUtilSamples(i,j) = ordUtil(i,j) * samples(i,j);
2135  Z(j,i) = samples(i,j);
2136  }
2137  }
2138 
2139  // If you want to dissociate the effect of back-propagation on the
2140  // update of the covariance matrix, reset the corresponding entry
2141  if (dissociateCovMatrix)
2142  {
2143  for (i = 0; i < glen; i++)
2144  {
2145  ordUtilSamples(i, offSize - 1) = 0.0;
2146  Z(offSize - 1, i) = 0.0;
2147  }
2148  }
2149 
2150  Eigen::MatrixXf G = ordUtilSamples * Z - ordUtilSum * eye;
2151 
2152  // If you want to dissociate the effect of back-propagation on the
2153  // update of the individual, reset the corresponding entry
2154  if (dissociateInd)
2155  {
2156  /*for (i = 0; i < glen; i++)
2157  {
2158  samples(i, offSize - 1) = 0.0;
2159  }*/
2160  orderedUtility[offSize - 1] = 0.0;
2161  }
2162 
2163  // Define transpose matrices for both samples and ordered utilities
2164  // (they are necessary to perform the calculation of gradients)
2165  Eigen::MatrixXf ordUtilTr(offSize,1);
2166  Eigen::MatrixXf v(glen,1);
2167  for (j = 0; j < offSize; j++)
2168  {
2169  ordUtilTr(j,0) = orderedUtility[j];
2170  }
2171 
2172  v = etaInd * expCovM * samples * ordUtilTr;
2173  for (i = 0; i < glen; i++)
2174  {
2175  dInd[i] = v(i,0);
2176  }
2177  dCovM = etaCovM * G;
2178  // Update the individual and the covariance matrix
2179  for (i = 0; i < glen; i++)
2180  {
2181  ind[i] += dInd[i];
2182  if (xnesCombination && (xnesCombinationType == 0))
2183  {
2184  ind[i] += backpropfreep[i];
2185  }
2186  }
2187  covMatrix += dCovM;
2188 
2189  exp->endGeneration(gn);
2190 
2191  // Debug information to check how much the individual is changed across two generations
2192  if (debugPrint)
2193  {
2194  double indOffset = 0.0;
2195  for (i = 0; i < glen; i++)
2196  {
2197  indOffset += fabs(ind[i] - oldInd[i]);
2198  fprintf(fp, "%.2f\t", ind[i]);
2199  oldInd[i] = ind[i];
2200  }
2201  fprintf(fp, "offset %.2f \n", indOffset);
2202  fflush(fp);
2203  }
2204 
2205  if ( commitStep() ) { return; }
2206 
2207  // Save the best individual (in terms of its fitness) among the offspring
2208  xnesSaveBest(ordoff[0]);
2209  // Compute and save statistics
2210  xnesComputeStats();
2211  xnesSaveStats();
2212  // Each <pheGen> generations, save the best phenotype (i.e. the one of the best individual)
2213  if (pheGen > 0)
2214  {
2215  if ((gn + 1) % pheGen == 0)
2216  {
2217  int bestInd = ordoff[0];
2218  if ((gn + 1) == nogenerations)
2219  {
2220  // During the last generation, the individual is also tested
2221  // and it might be the best
2222  if (lastGenIndFit > ordf[0])
2223  {
2224  exp->setNetParameters(lastGenInd);
2225  xnesSaveBestPhe(gn, offSize);
2226  }
2227  else
2228  {
2229  exp->setNetParameters(offspringFreep[bestInd]);
2230  xnesSaveBestPhe(gn, bestInd);
2231  }
2232  }
2233  else
2234  {
2235  exp->setNetParameters(offspringFreep[bestInd]);
2236  xnesSaveBestPhe(gn, bestInd);
2237  }
2238  }
2239  }
2240  else
2241  {
2242  // If <pheGen> == 0, save the best phenotype at the end of each replication
2243  if ((gn + 1) == nogenerations)
2244  {
2245  int bestInd = ordoff[0];
2246  if ((gn + 1) == nogenerations)
2247  {
2248  // During the last generation, the individual is also tested
2249  // and it might be the best
2250  if (lastGenIndFit > f[bestInd])
2251  {
2252  exp->setNetParameters(lastGenInd);
2253  xnesSaveBestPhe(gn, offSize);
2254  }
2255  }
2256  else
2257  {
2258  exp->setNetParameters(offspringFreep[bestInd]);
2259  xnesSaveBestPhe(gn, bestInd);
2260  }
2261  }
2262  }
2263 
2264  emit endGeneration( cgen, fmax, faverage, fmin );
2265  if (commitStep()) {
2266  return; // stop the evolution process
2267  }
2268 
2269  cgen++;
2270 
2271  //always save in order to be able to resume the evolution process, but keep only the last gen file unless it has to be saved by the param savePopulationEachNGenerations
2272  xnesSaveAllGen();
2273 
2274  //remove the previous genfile unless it has to be kept because of the savePopulationEachNGenerations param
2275  if ((savePopulationEachNGenerations == 0) || (gn>1 && ((gn-1) % (savePopulationEachNGenerations) != 0))) {
2276  //EX: gn 998 = G999S1.gen --- gn 999 = G1000S1.gen --- gn = 1000 = G1001S1.gen --- gn 1001 = G1002S1.gen
2277  sprintf(filename,"G%dS%d.gen",gn,currentSeed);
2278  if(remove(filename) != 0) {
2279  //if(!QFile::remove(filename)) {
2280  Logger::warning(QString("Error deleting temporary gen file: ") + QString::fromStdString(filename));
2281  }
2282  }
2283 
2284  Logger::info(QString("Generation %1 took %2 minutes").arg(gn).arg((double)evotimer.elapsed()/60000.0, 0, 'f', 2));
2285  fflush(stdout);
2286 
2287  // Reset weights and fitnesses once used
2288  for (j = 0; j < offSize; j++)
2289  {
2290  f[j] = 0.0;
2291  orderedUtility[j] = 0.0;
2292  tfitness[j] = 0.0;
2293  ntfitness[j] = 0;
2294  terror[j] = 0.0;
2295  }
2296  // Reset matrix exponential
2297  for (i = 0; i < glen; i++)
2298  {
2299  for (j = 0; j < glen; j++)
2300  {
2301  expCovM(i,j) = 0.0;
2302  }
2303  }
2304 
2305  // Reset current offspring
2306  for (i = 0; i < glen; i++)
2307  {
2308  currOffspring[i] = 0.0;
2309  }
2310 
2311  // Reset the offspring freeps
2312  for (j = 0; j < offSize; j++)
2313  {
2314  for (i = 0; i < glen; i++)
2315  {
2316  offspringFreep[j][i] = 0.0;
2317  }
2318  }
2319 
2320  // If the <variableStdDev> flag is set to true,
2321  // reduce the <offspringStdDev> until it reaches
2322  // the lower bound of 0.1
2323  if (startVariableStdDev)
2324  {
2325  double indVariation = 0.0;
2326  for (i = 0; i < glen; i++)
2327  {
2328  indVariation += fabs(ind[i] - oldInd[i]);
2329  }
2330  // The variation (increase/decrease) of the offspring standard deviation
2331  // depends on the variation of the individual across two consecutive generations:
2332  // - if the variation is too big, <offspringStdDev> is halved;
2333  // - if the variation is too small, <offspringStdDev> is doubled;
2334  // - if the variation is limited, <offspringStdDev> is increased/decreased by a constant decay value.
2335  if (indVariation <= 1.0)
2336  {
2337  offspringStdDev *= 2.0;
2338  if (offspringStdDev > 1.0)
2339  {
2340  offspringStdDev = 1.0;
2341  }
2342  }
2343  else if (indVariation >= 10.0)
2344  {
2345  offspringStdDev /= 2.0;
2346  if (offspringStdDev < 0.1)
2347  {
2348  offspringStdDev = 0.1;
2349  }
2350  }
2351  else
2352  {
2353  int multiplier = (indVariation >= oldIndVariation) ? 1 : -1;
2354  offspringStdDev += multiplier * stdDevDecay;
2355  if (offspringStdDev > 1.0)
2356  {
2357  offspringStdDev = 1.0;
2358  }
2359  if (offspringStdDev < 0.1)
2360  {
2361  offspringStdDev = 0.1;
2362  }
2363  }
2364  // Update the individual variation
2365  oldIndVariation = indVariation;
2366  }
2367  }
2368  xnesSaveAllGen();
2369  // Save the best generation fitness statistics
2370  saveBestFitness();
2371  }
2372 
2373  // Deleting all evaluators
2374  for (int i = 0; i < evaluators.size(); i++) {
2375  delete evaluators[i];
2376  }
2377 }
2378 
2379 /*
2380  * Main function of the Genetic Algorithm (Steady State Version)
2381  */
2383 {
2384  int rp; //replication
2385  int gn; //generation
2386  int id; //individuals
2387  double fit;
2388  double minfit=9999;
2389  int minid=-1;
2390  double mfit;
2391  float final_mrate;
2392  int startGeneration=0;
2393  char statfile[128];
2394  char genFile[128];
2395  char filename[64];
2396  QVector< int > subsVec;
2397  double currentRetentionRate;
2398 
2399  subsVec.resize(popSize);
2400  // Resizing genome
2401  genome.resize(popSize * 2);
2402 
2403  final_mrate = mutation;
2404  Logger::info("EVOLUTION: steady state");
2405  Logger::info("Number of replications: " + QString::number(nreplications));
2406 
2407  // Creating evaluator objects in case of a multithread simulation. Also setting the actual number of threads used
2408  QVector<EvaluatorThreadForEvoga*> evaluators(popSize, NULL);
2409  if (numThreads > 1) {
2410  for (int i = 0; i < evaluators.size(); i++) {
2412  newExp->setEvoga(this);
2413  evaluators[i] = new EvaluatorThreadForEvoga(this, newExp);
2414  }
2415  QThreadPool::globalInstance()->setMaxThreadCount(numThreads);
2416  }
2417 
2418  for(rp=0;rp<nreplications;rp++) { // replications
2419  startGeneration = 0;
2420  limitationFactor = 1.0;
2421  mutation=initial_mutation; // initially mutation (default 50%)
2422  //setSeed(getSeed());
2423  setSeed(getStartingSeed()+rp);
2424  Logger::info(QString("Replication %1, seed: %2").arg(rp+1).arg(getStartingSeed()+rp));
2426  randomizePop();
2427  // --- section runnable only if there is an Evonet object
2428  if ( hasResource( "evonet" ) ) {
2430  }
2431 
2432  // Set fbest to a very low value
2433  this->fbest = -99999.0;
2434 
2435  emit startingReplication( rp );
2436 
2437  // Resetting seed in experiments
2439  if (numThreads > 1) {
2440  for (int i = 0; i < evaluators.size(); i++) {
2441  evaluators[i]->getExperiment()->newGASeed(getCurrentSeed());
2442  }
2443  }
2444 
2445  QTime evotimer;
2446  evotimer.start();
2447  for (int i=0;i<popSize+1;i++) {
2448  tfitness[i]=0.0;
2449  ntfitness[i]=0.0;
2450  }
2451  //code to recovery a previous evolution: Experimental
2452  sprintf(statfile,"statS%d.fit", getStartingSeed()+rp);
2453  //now check if the file exists
2454  DataChunk statTest(QString("stattest"),Qt::blue,2000,false);
2455  if (statTest.loadRawData(QString(statfile),0)) {
2456  startGeneration=statTest.getIndex();
2457  sprintf(genFile,"G%dS%d.gen",startGeneration,getStartingSeed()+rp);
2458  Logger::info("Recovering from startGeneration: " + QString::number(startGeneration));
2459  Logger::info(QString("Loading file: ") + genFile);
2460  loadallg(-1,genFile);
2461  cgen=startGeneration;
2462  mutation=mutation-startGeneration*mutationdecay;
2463  if (mutation<final_mrate) mutation=final_mrate;
2464  // Resizing genome the loading process changed the genome size = popSize
2465  genome.resize(popSize * 2);
2466  emit recoveredInterruptedEvolution( QString(statfile) );
2467  } //end evolution recovery code
2468 
2469  for(gn=startGeneration;gn<nogenerations;gn++) { // generations
2470  evotimer.restart();
2471  currentRetentionRate = 0.0;
2472  Logger::info(" Generation " + QString::number(gn+1));
2473  // Here we do this to avoid too many complications: if we have to run no threads, we use the old
2474  // code, otherwise we go for the multithread code below
2475  if (numThreads <= 1) {
2476  exp->initGeneration(gn);
2477  if ( commitStep() ) { return; }
2478  // Not running with multiple threads, using the old code
2479  for(id=0;id<popSize;id++) { //individuals
2480  fit=0.0;
2481  exp->setNetParameters(getGenes(id)); // get the free parameters from the genotype
2483  fit = exp->getFitness();
2485  tfitness[id] += fit;
2486  ntfitness[id]++;
2487  } else {
2488  tfitness[id] = fit;
2489  ntfitness[id] = 1;
2490  }
2491  if (isStopped()) { // stop evolution
2492  return;
2493  }
2494  copyGenes(id, popSize+id,1); //generate a variation by duplicating and mutating
2495  tfitness[popSize+id]=0;
2496  ntfitness[popSize+id]=0;
2497 
2498  exp->setNetParameters(getGenes(popSize)); // get the free parameters from the genotype
2499  exp->doAllTrialsForIndividual(popSize + id);
2500  fit = exp->getFitness();
2502  tfitness[popSize+id] += fit;
2503  ntfitness[popSize+id]++;
2504  } else {
2505  tfitness[popSize+id] = fit;
2506  ntfitness[popSize+id] = 1;
2507  }
2508  if (isStopped()) { // stop evolution
2509  return;
2510  }
2511 
2512  }
2513  exp->endGeneration(gn);
2514  if ( commitStep() ) { return; }
2515  } else {
2516  // Multithread code
2517 
2518  // Calling initGeneration on all evaluator
2519  for (int i = 0; i < popSize; i++) {
2520  evaluators[i]->getExperiment()->initGeneration(gn);
2521  }
2522  if (commitStep()) return; // stop the evolution process
2523 
2524  // We first evaluate all parents, so setting genotypes of parents (we have as many evaluators as individuals)
2525  for (int i = 0; i < popSize; i++) {
2526  evaluators[i]->setGenotype(i);
2527  }
2528  if (commitStep()) return; // stop the evolution process
2529 
2530  // Now starting parallel evaluation of parents and wating for it to finish
2531  QFuture<void> evaluationFuture = QtConcurrent::map(evaluators, runEvaluatorThreadForEvoga);
2532  evaluationFuture.waitForFinished();
2533  if (commitStep()) return; // stop the evolution process
2534 
2535  // We have finished evaluating parents, updating the fitness vectors
2536  for (int i = 0; i < popSize; i++) {
2538  tfitness[evaluators[i]->getGenotypeId()] += evaluators[i]->getFitness();
2539  ntfitness[evaluators[i]->getGenotypeId()]++;
2540  } else {
2541  tfitness[evaluators[i]->getGenotypeId()] = evaluators[i]->getFitness();
2542  ntfitness[evaluators[i]->getGenotypeId()] = 1;
2543  }
2544  }
2545  if (commitStep()) return; // stop the evolution process
2546 
2547  // Now we can generate all children for all individuals and set them in the evaluators
2548  for (int i = 0; i < popSize; i++) {
2549  copyGenes(i, popSize + i, 1); //generate a variation by duplicating and mutating
2550  tfitness[popSize + i] = 0;
2551  ntfitness[popSize + i] = 0;
2552  evaluators[i]->setGenotype(popSize + i);
2553  }
2554  if (commitStep()) return; // stop the evolution process
2555 
2556  // Now starting parallel evaluation of children and wating for it to finish
2557  evaluationFuture = QtConcurrent::map(evaluators, runEvaluatorThreadForEvoga);
2558  evaluationFuture.waitForFinished();
2559  if (commitStep()) return; // stop the evolution process
2560 
2561  // We have finished evaluating parents, updating the fitness vectors
2562  for (int i = 0; i < popSize; i++) {
2564  tfitness[evaluators[i]->getGenotypeId()] += evaluators[i]->getFitness();
2565  ntfitness[evaluators[i]->getGenotypeId()]++;
2566  } else {
2567  tfitness[evaluators[i]->getGenotypeId()] = evaluators[i]->getFitness();
2568  ntfitness[evaluators[i]->getGenotypeId()] = 1;
2569  }
2570  }
2571  if (commitStep()) return; // stop the evolution process
2572 
2573  // Calling endGeneration on all evaluator
2574  for (int i = 0; i < popSize; i++) {
2575  evaluators[i]->getExperiment()->endGeneration(gn);
2576  }
2577  if (commitStep()) return; // stop the evolution process
2578 
2579  }
2580 
2581  // ========= Selection part ========== //
2582  // Finally, we look for the worst individuals (parents) and substitute them with best children.
2583  // What we do is: we order both the parents and the children in descending order, then we take the
2584  // popSize best individuals. This is not the same as what is done in the sequential version of
2585  // the algorithm, but should be similar. We overwrite the worst parents with the best children
2586  QVector<FitnessAndId> parents(popSize);
2587  for (int i = 0; i < popSize; i++) {
2588  parents[i].fitness = tfitness[i] / ntfitness[i];
2589  parents[i].id = i;
2590  }
2591  QVector<FitnessAndId> children(popSize);
2592  for (int i = 0; i < popSize; i++) {
2593  children[i].fitness = tfitness[popSize + i] / ntfitness[popSize + i];
2594  children[i].id = popSize + i;
2595  }
2596  // Sorting both parents and children. They are sorted in ascending order but we need the best
2597  // individuals (those with the highest fitness) first
2598  qSort(parents);
2599  qSort(children);
2600  int p = popSize - 1;
2601  int c = popSize - 1;
2602  for (int i = 0; i < popSize; i++) {
2603  if(limitRetention)
2604  children[c].fitness *= limitationFactor;
2605  if (parents[p].fitness > children[c].fitness) {
2606  // No need to swap, parents are already in the population vector
2607  p--;
2608  } else {
2609  // Swapping with one of the worst parents (we know for sure that p + c = popSize)
2610  copyGenes(children[c].id, parents[popSize - 1 - c].id, 0);
2611  tfitness[parents[popSize - 1 - c].id] = tfitness[children[c].id];
2612  ntfitness[parents[popSize - 1 - c].id] = ntfitness[children[c].id];
2613  subsVec[children[c].id-popSize] = parents[popSize - 1 - c].id;
2614  c--;
2615  currentRetentionRate += 1.0/popSize;
2616  }
2617  }
2618  for (int i=0; i<=c;i++)
2619  subsVec[children[i].id-popSize] = -1;
2620 
2621  saveBestInd();
2622  computeFStat2();
2623  saveFStat();
2624 
2625  if(saveRetStat)
2626  saveRStat(subsVec);
2627 
2628  emit endGeneration( cgen, fmax, faverage, fmin );
2629  if (commitStep()) {
2630  return; // stop the evolution process
2631  }
2632 
2633  cgen++;
2634  if (mutation > final_mrate) {
2636  } else {
2637  mutation = final_mrate;
2638  }
2639 
2640  limitationFactor += (targetRetentionRate-currentRetentionRate)/10.0;
2641  if (limitationFactor > 1.0)
2642  limitationFactor = 1.0;
2643 
2644  //always save in order to be able to resume the evolution process, but keep only the last gen file unless it has to be saved by the param savePopulationEachNGenerations
2645  saveallg();
2646 
2647  //remove the previous genfile unless it has to be kept because of the savePopulationEachNGenerations param
2648  if ((savePopulationEachNGenerations == 0) || (gn>1 && ((gn-1) % (savePopulationEachNGenerations) != 0))) {
2649  //EX: gn 998 = G999S1.gen --- gn 999 = G1000S1.gen --- gn = 1000 = G1001S1.gen --- gn 1001 = G1002S1.gen
2650  sprintf(filename,"G%dS%d.gen",gn,currentSeed);
2651  if(!QFile::remove(filename)) {
2652  Logger::warning(QString("Error deleting temporary gen file: ") + QString::fromStdString(filename));
2653  }
2654  }
2655 
2656  Logger::info(QString("Generation %1 took %2 minutes - Best fitness = %3").arg(gn+1).arg((double)evotimer.elapsed()/60000.0, 0, 'f', 2).arg(fmax));
2657  if(limitRetention)
2658  Logger::info(QString(" --- Target retention rate: %1; current rate: %2; fitness limitation factor: %3").arg(targetRetentionRate).arg(currentRetentionRate).arg(limitationFactor));
2659  fflush(stdout);
2660  }
2661  saveallg();
2662 
2663  // Save the best generation fitness statistics
2664  saveBestFitness();
2665  }
2666 
2667  // Deleting all evaluators
2668  for (int i = 0; i < evaluators.size(); i++) {
2669  delete evaluators[i];
2670  }
2671 }
2672 
2673 /*
2674  * Main function of the Genetic Algorithm (generational version with truncation selection)
2675  */
2677 {
2678  int rp; //replication
2679  int gn; //generation
2680  int id; //individuals
2681  double fit;
2682  int startGeneration=0;
2683  char statfile[128];
2684  char genFile[128];
2685 
2686  // Resizing genome
2687  genome.resize(popSize);
2688 
2689  for(rp=0;rp<nreplications;rp++) {// replications
2690  startGeneration = 0;
2691  setSeed(getStartingSeed()+rp);
2692  Logger::info(QString("Replication %1 seed: %2").arg(rp+1).arg(getStartingSeed()));
2694  randomizePop();
2695  // --- section runnable only if there is an Evonet object
2696  if ( hasResource( "evonet" ) ) {
2698  }
2699 
2700  // Set fbest to a very low value
2701  this->fbest = -99999.0;
2702 
2703  emit startingReplication( rp );
2704 
2705  // Resetting seed in experiments
2707 
2708  QTime evotimer;
2709  evotimer.start();
2710 
2711  //code to recovery a previous evolution: Experimental
2712  sprintf(statfile,"statS%d.fit", getStartingSeed()+rp);
2713  //now check if the file exists
2714  DataChunk statTest(QString("stattest"),Qt::blue,2000,false);
2715  if (statTest.loadRawData(QString(statfile),0)) {
2716  startGeneration=statTest.getIndex();
2717  sprintf(genFile,"G%dS%d.gen",startGeneration,getStartingSeed()+rp);
2718  Logger::info("Recovering from startGeneration: " + QString::number(startGeneration));
2719  Logger::info(QString("Loading file: ") + genFile);
2720  loadallg(startGeneration,genFile);
2721  emit recoveredInterruptedEvolution( QString(statfile) );
2722  } //end evolution recovery code
2723 
2724  for(gn=startGeneration;gn<nogenerations;gn++) { // generations
2725  evotimer.restart();
2726  Logger::info(" Generation " + QString::number(gn+1));
2727  exp->initGeneration( gn );
2728  for(id=0;id<popSize;id++) { //individuals
2729  exp->setNetParameters(getGenes(id)); // get the free parameters from the genotype
2731  fit = exp->getFitness();
2732  tfitness[id]=fit;
2733  if (commitStep()) { // stop evolution
2734  return;
2735  }
2736  }
2737  reproduce();
2738 
2739  emit endGeneration( gn, fmax, faverage, fmin );
2740  exp->endGeneration( gn );
2741 
2743  saveallg();
2744 
2745  Logger::info(QString("Generation %1 took %2 minutes").arg(gn+1).arg((double)evotimer.elapsed()/60000.0, 0, 'f', 2));
2746  fflush(stdout);
2747  }
2748 
2749  saveallg();
2750 
2751  // Save the best generation fitness statistics
2752  saveBestFitness();
2753  }
2754 }
2755 
2756 
2757 // this function generate a random seed for initialize the random number generator
2758 unsigned int generateRandomSeed() {
2759  // this number is always different amongs processes because this function
2760  // is on the stack of the process
2761  unsigned long int stackMem = (unsigned long int)( generateRandomSeed );
2762  // time on which the process has been started
2763 #ifdef FARSA_WIN
2764  unsigned long int startTime = GetTickCount();
2765 #else
2766  unsigned long int startTime = time(NULL);
2767 #endif
2768  // the seed is generated mixing the values above
2769  unsigned long int randSeed = 0;
2770 
2771  stackMem=stackMem-startTime; stackMem=stackMem-randSeed; stackMem=stackMem^(randSeed >> 13);
2772  startTime=startTime-randSeed; startTime=startTime-stackMem; startTime=startTime^(stackMem << 8);
2773  randSeed=randSeed-stackMem; randSeed=randSeed-startTime; randSeed=randSeed^(startTime >> 13);
2774  stackMem=stackMem-startTime; stackMem=stackMem-randSeed; stackMem=stackMem^(randSeed >> 12);
2775  startTime=startTime-randSeed; startTime=startTime-stackMem; startTime=startTime^(stackMem << 16);
2776  randSeed=randSeed-stackMem; randSeed=randSeed-startTime; randSeed=randSeed^(startTime >> 5);
2777  stackMem=stackMem-startTime; stackMem=stackMem-randSeed; stackMem=stackMem^(randSeed >> 3);
2778  startTime=startTime-randSeed; startTime=startTime-stackMem; startTime=startTime^(stackMem << 10);
2779  randSeed=randSeed-stackMem; randSeed=randSeed-startTime; randSeed=randSeed^(startTime >> 15);
2780 
2781  return randSeed%10000;
2782 }
2783 
2784 void Evoga::configure(ConfigurationParameters& params, QString prefix)
2785 {
2786  genome.clear();
2787  bestgenome.clear();
2788 
2789  evolutionType = ConfigurationHelper::getString(params, prefix + "evolutionType", "steadyState");
2790  if ( evolutionType != "steadyState" && evolutionType != "generational" && evolutionType != "xnes" && evolutionType != "specializerSteadyState") {
2791  Logger::error( "Evoga - evolutionType has been wrongly setted. It can assume only 'steadyState', 'generational', 'xnes' or 'specializerSteadyState' values" );
2792  evolutionType = "steadyState";
2793  }
2794  nogenerations = ConfigurationHelper::getInt(params, prefix + "ngenerations", 100); //number of generations
2795  nreplications = ConfigurationHelper::getInt(params, prefix + "nreplications", 10); //number of replications
2796  nreproducing = ConfigurationHelper::getInt(params, prefix + "nreproducing", 20); //number of father
2797  noffspring = ConfigurationHelper::getInt(params, prefix + "noffspring", 5); //number of sons
2798  // starting seed - if not specified (or setted as 'auto') it auto generate a seed
2799  QString checkSeed = ConfigurationHelper::getString(params, prefix + "seed", "auto");
2800  if ( checkSeed == "auto" ) {
2801  seed = generateRandomSeed();
2802  } else {
2803  seed = checkSeed.toInt();
2804  }
2805  Logger::info( QString("Evoga - Random seed setted to ")+QString::number(seed) );
2806  //seed = ConfigurationHelper::getInt(params, prefix + "seed", 1234); //starting seed
2807  savebest = ConfigurationHelper::getInt(params, prefix + "savenbest", 1); //saving best n genotype
2808  elitism = ConfigurationHelper::getBool(params, prefix + "elitism", false); //activate elitism
2809  numThreads = ConfigurationHelper::getInt(params, prefix + "numThreads", 1); //number of concurrent threads to use
2810  savePopulationEachNGenerations = ConfigurationHelper::getInt(params, prefix + "savePopulationEachNGenerations", 0);
2811  averageIndividualFitnessOverGenerations = ConfigurationHelper::getBool(params, prefix + "averageIndividualFitnessOverGenerations", true);
2812  saveRetStat = ConfigurationHelper::getBool(params, prefix + "saveRetetionStatistics", false);
2813 
2814  limitRetention = ConfigurationHelper::getBool(params, prefix + "limitRetention", false);
2815  targetRetentionRate = ConfigurationHelper::getDouble(params, prefix + "targetRetentionRate", false);
2816  numModules = ConfigurationHelper::getInt(params, prefix + "numModules", 1);
2817 
2818  crossRate = ConfigurationHelper::getDouble(params, prefix + "crossoverRate", 0.05);;
2819  modulesMutationRate = ConfigurationHelper::getDouble(params, prefix + "modulesMutationRate", 0.25);
2820  overwriteRate = ConfigurationHelper::getDouble(params, prefix + "overwriteWrite", 0.05);
2821  mutateOnlyRelatives = ConfigurationHelper::getBool(params, prefix + "mutateOnlyRelatives", true);
2822  rankBasedProb = ConfigurationHelper::getDouble(params, prefix + "rankBasedProbability", 0.75);
2823  selectionType = ConfigurationHelper::getString(params, prefix + "selectionType", "rankBased");
2824  if ( selectionType != "rankBased" && selectionType != "species") {
2825  Logger::error( "Evoga - selectionType has been wrongly setted. It can assume only 'rankBased' or 'species' values. 'rankBased' will be used as default value." );
2826  evolutionType = "rankBased";
2827  }
2828 
2829 
2830  //mutation rate can be written both as int or as double
2831  mutation = ConfigurationHelper::getDouble(params, prefix + "mutation_rate", mutation); //mutation rate
2832  if(mutation >= 1) {
2833  mutation /= 100;
2834  }
2835  //speed of decay (only valid for steady-state GA)
2836  mutationdecay = ConfigurationHelper::getDouble(params, prefix + "mutation_decay", 0.01);
2837  initial_mutation = ConfigurationHelper::getDouble(params, prefix + "initial_mutation", 0.5);
2838 
2839  mutationRange = ConfigurationHelper::getDouble(params, prefix + "mutationRange", 0.0);
2840  offspringMutRange = ConfigurationHelper::getDouble(params, prefix + "offspringMutRange", 0.0);
2841  useGaussian = ConfigurationHelper::getBool(params, prefix + "useGaussian", false);
2842  gaussianMean = ConfigurationHelper::getDouble(params, prefix + "gaussianMean", 0.0);
2843  gaussianStdDev = ConfigurationHelper::getDouble(params, prefix + "gaussianStdDev", 1.0);
2844  offspringStdDev = ConfigurationHelper::getDouble(params, prefix + "offspringStdDev", 1.0);
2845  variableStdDev = ConfigurationHelper::getBool(params, prefix + "variableStdDev", false);
2846  numStartInd = ConfigurationHelper::getInt(params, prefix + "numStartInd", 1);
2847  mutationLearningRate = ConfigurationHelper::getDouble(params, prefix + "mutationLearningRate", 1.0);
2848  xnesCombination = ConfigurationHelper::getBool(params, prefix + "xnesCombination", false);
2849  xnesCombinationType = ConfigurationHelper::getInt(params, prefix + "xnesCombinationType", 0);
2850  if ( xnesCombinationType < 0 || xnesCombinationType > 1) {
2851  Logger::error( "Evoga - xnesCombinationType has been wrongly setted. It can assume only 0 or 1 values" );
2852  xnesCombinationType = 0;
2853  }
2854  backPropOffspringUtilityRank = ConfigurationHelper::getInt(params, prefix + "backPropOffspringUtilityRank", 255);
2855  backPropOffspringFitnessIncrease = ConfigurationHelper::getBool(params, prefix + "backPropOffspringFitnessIncrease", false);
2856  backPropOffspringFitnessIncreasePercentage = ConfigurationHelper::getDouble(params, prefix + "backPropOffspringFitnessIncreasePercentage", 0.1);
2857  if (backPropOffspringFitnessIncreasePercentage < 0.0 || backPropOffspringFitnessIncreasePercentage > 1.0)
2858  {
2859  Logger::error( "Evoga - backPropOffspringFitnessIncreasePercentage has been wrongly setted. It must be within the range [0,1] (it is a percentage!!!)" );
2861  }
2862  pheGen = ConfigurationHelper::getInt(params, prefix + "pheGen", 0);
2863  standardNes = ConfigurationHelper::getBool(params, prefix + "standardNes", false);
2864  minimization = ConfigurationHelper::getBool(params, prefix + "minimization", false);
2865  debugPrintInfoToFile = ConfigurationHelper::getBool(params, prefix + "debugPrintInfoToFile", false);
2866  dissociateInd = ConfigurationHelper::getBool(params, prefix + "dissociateInd", false);
2867  dissociateCovMatrix = ConfigurationHelper::getBool(params, prefix + "dissociateCovMatrix", false);
2868  specialUtilityRanking = ConfigurationHelper::getBool(params, prefix + "specialUtilityRanking", false);
2869 
2870  exp = params.getObjectFromGroup<EvoRobotExperiment>(prefix + "Experiment", false);
2871  exp->setEvoga(this);
2872  Logger::info( "Created EvoRobotExperiment " + params.getValue(prefix+"Experiment/type") + " from group " + prefix + "Experiment" );
2873 
2874  // Copying the ConfigurationParameters object and the prefix: we will need them to create new instances of the experiment for
2875  // multithreading evolution
2877  savedExperimentPrefix = prefix + "Experiment";
2878 }
2879 
2881 {
2882  Logger::error("NOT IMPLEMENTED (Evoga::save)");
2883  abort();
2884 }
2885 
2886 void Evoga::describe( QString type ) {
2887  Descriptor d = addTypeDescription( type, "Implements the genetic algorithm developed by Stefano Nolfi" );
2888  d.describeEnum( "evolutionType" ).def("steadyState").values( QStringList() << "steadyState" << "generational" << "xnes" << "specializerSteadyState").props( IsMandatory ).help("Specify the type of evolution process to execute");
2889  d.describeInt( "ngenerations" ).def(100).limits(0,MaxInteger).help("Number of generations");
2890  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");
2891  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");
2892  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");
2893  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");
2894  d.describeInt("savenbest").def(1).limits(1,MaxInteger).help("The number of best genotypes to save each generation");
2895  d.describeBool("elitism").def(false).help("If use elitism or not");
2896  d.describeInt("numThreads").def(1).limits(1,MaxInteger).help("The number of thread used to parallelize the evaluation of individuals");
2897  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");
2898  d.describeReal("mutation_rate").def(0.05).limits(0,100).help("The mutation rate", "The rate at which 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)");
2899  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");
2900  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");
2901  d.describeSubgroup( "Experiment" ).props(IsMandatory).type("EvoRobotExperiment").help("The object delegated to simulate and to evaluate the fitness of an individual");
2902  d.describeBool("averageIndividualFitnessOverGenerations").def(true).help("Whether to average the current fitness with the previous one or not");
2903  d.describeBool("saveRetetionStatistics").def(false).help("Whether to save the retetions statistics or not");
2904  d.describeReal("mutationRange").def(0.0).help("The mutation range used to generate the individual in case of the xnes evolution type");
2905  d.describeReal("offspringMutRange").def(0.0).help("The mutation range used to generate the offspring in case of the xnes evolution type");
2906  d.describeBool("useGaussian").def(false).help("Whether to use a gaussian distribution or not in order to generate offspring in case of the xnes evolution type");
2907  d.describeReal("gaussianMean").def(0.0).help("The mean of the gaussian distribution used to generate both parent and offspring in case of the xnes evolution type");
2908  d.describeReal("gaussianStdDev").def(1.0).help("The standard deviation of the gaussian distribution used to generate parent in case of the xnes evolution type");
2909  d.describeReal("offspringStdDev").def(1.0).help("The standard deviation of the gaussian distribution used to generate offspring in case of the xnes evolution type");
2910  d.describeBool("variableStdDev").def(false).help("Whether the standard deviation of the gaussian distribution used to generate offspring is variable or constant");
2911  d.describeInt("numStartInd").def(1).limits(1,MaxInteger).help("The number of individuals to be tested so to find the starting individual in case of the xnes evolution type");
2912  d.describeReal("mutationLearningRate").def(0.0).help("The learning rate used to generate \"mutated\" offspring in case of the xnes evolution type");
2913  d.describeBool("xnesCombination").def(false).help("Whether to combine xnes with backpropagation algorithm or not");
2914  d.describeInt("xnesCombinationType").def(0).limits(0,MaxInteger).help("Type of combination between xnes and backpropagation algorithms");
2915  d.describeInt("backPropOffspringUtilityRank").def(255).limits(0,MaxInteger).help("The utility rank of the backpropagation algorithm in case of the second type of combination with xnes");
2916  d.describeBool("backPropOffspringFitnessIncrease").def(false).help("Whether to increase the fitness of the backpropagation offspring in case of the second type of combination with xnes");
2917  d.describeReal("backPropOffspringFitnessIncreasePercentage").def(0.1).help("Percentage of increase of the backpropagation offspring fitness value in case of the second type of combination with xnes");
2918  d.describeInt("pheGen").def(0).limits(1,MaxInteger).help("How often the best phenotype must be saved");
2919  d.describeBool("standardNes").def(false).help("Whether to use standard version of xnes or not");
2920  d.describeBool("minimization").def(false).help("Whether the fitness function corresponds to a minimization problem");
2921  d.describeBool("debugPrintInfoToFile").def(false).help("Whether to print debug information to file");
2922  d.describeBool("dissociateInd").def(false).help("Whether to dissociate back-propagation effect on xNES individual update");
2923  d.describeBool("dissociateCovMatrix").def(false).help("Whether to dissociate back-propagation effect on xNES covariance matrix update");
2924  d.describeBool("specialUtilityRanking").def(false).help("Whether to use a special version to compute the utility ranking");
2925  d.describeInt("numModules").def(1).limits(0,MaxInteger).help("The number of modules that will compose the genotype");
2926 
2927  d.describeReal("crossoverRate").def(0.05).help("The probability that a crossover will occur in an offspring team");
2928  d.describeReal("modulesMutationRate").def(0.25).help("The probability that a module will be mutated on a team");
2929  d.describeBool("mutateOnlyRelatives").def(true).help("Wheater a module should be replace by its own offsprings or by any offspring");
2930  d.describeReal("overwriteRate").def(0.05).help("The learning rate used to generate \"mutated\" offsprings in case of the xnes evolution type");
2931  d.describeBool("limitRetention").def(false).help("Wheater the retention should be limited or not");
2932  d.describeReal("targetRetentionRate").def(0.2).help("The rate in which retention should be limited");
2933  d.describeBool("saveRetetionStatistics").def(false).help("Whether to save the retetions statistics or not");
2934  d.describeEnum( "selectionType" ).def("rankBased").values( QStringList() << "rankBased" << "species").props( IsMandatory ).help("Specify the type of selection that will be used to define which individuals will survive");
2935  d.describeReal("rankBasedProbability").def(0.75).help("The probability that the individuals with high fitness will be selected");
2936 }
2937 
2939 {
2940  // Sharing resources and declaring which ones we will access
2942  usableResources(QStringList() << "evonet");
2943 
2944  // Allocating memory
2945  tfitness = new double[MAXINDIVIDUALS];
2946  statfit = new double*[nogenerations];
2947  ntfitness = new double[MAXINDIVIDUALS]; //used with super ag implementation
2948  for(int i = 0; i < nogenerations; i++) {
2949  statfit[i] = new double[3];
2950  }
2951  terror = new double[MAXINDIVIDUALS];
2952 
2953  //allocating memory for the mutation vector
2954  glen = exp->getGenomeLength();
2955  mutations = new float[glen];
2956  for(int mi = 0; mi < glen; mi++) {
2958  }
2959 
2960  //now we allocate memory for genome and best genome
2961  cgen = 0;
2963 
2964  //dynamic allocation of genome
2965  genome.setGenomeLength(glen);
2966  genome.resize(popSize); // An initial set of individuals just to avoid problems...
2967  for (int i = 0; i < genome.size(); i++) {
2968  for (int r = 0; r < glen; r++) {
2969  genome[i][r] = i;//mrand(256);test
2970  }
2971  }
2972 
2973  //dynamic allocation of bestgenome
2974  bestgenome.setGenomeLength(glen);
2975  bestgenome.resize(nreproducing);
2976 
2977  // Only for XNES algorithm
2978  if (evolutionType == "xnes")
2979  {
2980  float gs = 4.0 + 3.0 * floor(log((float)glen));
2981  if (xnesCombination && (xnesCombinationType > 0))
2982  {
2983  gs += 1.0;
2984  }
2985  int genSize = (int)floor(gs);
2986  genotypes.resize(genSize);
2987  for (int i = 0; i < genSize; i++)
2988  {
2989  genotypes[i] = new float[glen];
2990  for (int j = 0; j < glen; j++)
2991  {
2992  genotypes[i][j] = 0.0;
2993  }
2994  }
2995  }
2996 
2997  if (evolutionType == "specializerSteadyState"){
2998  nreproducing *= numModules;
3000  }
3001 
3002  //resetting fitness
3003  for (int i = 0; i < MAXINDIVIDUALS; i++) {
3004  tfitness[i] = 0.0;//
3005  }
3006 
3007  for (int i = 0; i < nogenerations; i++) {
3008  statfit[i][0] = 0.0; //Average fitness of population
3009  statfit[i][1] = 0.0; //max fitness
3010  statfit[i][2] = 0.0; //min fitness
3011  }
3012 
3013  Logger::info("Evoga Configured - Number of genes: " + QString::number(glen));
3014 }
3015 
3017 {
3018  stopEvolution = false;
3019  if ( evolutionType == "steadyState" ) {
3021  } else if ( evolutionType == "generational" ) {
3023  } else if ( evolutionType == "xnes" ) {
3024  xnes();
3025  } else if ( evolutionType == "specializerSteadyState" ) {
3026  if(numModules==1)
3028  else
3030  } else {
3031  Logger::error( QString("Evoga - request to execute a unrecognized evolution type: %1").arg(evolutionType) );
3032  }
3033 }
3034 
3035 void Evoga::stop() {
3036  stopEvolution = true;
3037  waitForNextStep.wakeAll();
3038 }
3039 
3041  if ( isStepByStep && !stopEvolution ) {
3042  // will block waiting the command for going ahead
3043  mutexStepByStep.lock();
3045  mutexStepByStep.unlock();
3046  }
3047  return stopEvolution;
3048 }
3049 
3051  return stopEvolution;
3052 }
3053 
3055  stopEvolution = false;
3056 }
3057 
3058 void Evoga::enableStepByStep( bool enable ) {
3059  isStepByStep = enable;
3060  // if disable the step-by-step it wake any eventually blocked commitStep
3061  if ( !enable ) {
3062  waitForNextStep.wakeAll();
3063  }
3064 }
3065 
3067  return isStepByStep;
3068 }
3069 
3071  waitForNextStep.wakeAll();
3072 }
3073 
3075 {
3076  return exp;
3077 }
3078 
3079 QVector<EvoRobotExperiment*> Evoga::getEvoRobotExperimentPool()
3080 {
3081  QVector<EvoRobotExperiment*> v;
3082  v.append(exp);
3083  return v;
3084 }
3085 
3087 {
3088  return cgen;
3089 }
3090 
3092 {
3093  return seed;
3094 }
3095 
3097 {
3098  return currentSeed;
3099 }
3100 
3102 {
3103  return nreplications;
3104 }
3105 
3107  return nogenerations;
3108 }
3109 
3111  return mutation;
3112 }
3113 
3114 void Evoga::setCurrentMutationRate( double mutation_rate ) {
3115  mutation = mutation_rate;
3116 }
3117 
3118 unsigned int Evoga::loadGenotypes(QString filename)
3119 {
3120  if (evolutionType == "xnes")
3121  {
3122  return xnesLoadAllGen(-1, filename.toLatin1().data());
3123  }
3124  else
3125  {
3126  return loadallg(-1, filename.toLatin1().data());
3127  }
3128 }
3129 
3130 unsigned int Evoga::numLoadedGenotypes() const
3131 {
3132  return loadedIndividuals;
3133 }
3134 
3135 int* Evoga::getGenesForIndividual(unsigned int id)
3136 {
3137  return getGenes(id);
3138 }
3139 
3140 float* Evoga::xnesGetGenesForIndividual(unsigned int id)
3141 {
3142  return xnesGetGenes(id);
3143 }
3144 
3145 QString Evoga::statisticsFilename(unsigned int seed)
3146 {
3147  return "statS" + QString::number(seed) + QString(".fit");
3148 }
3149 
3150 QString Evoga::bestsFilename(unsigned int seed)
3151 {
3152  return "B0S" + QString::number(seed) + QString(".gen");
3153 }
3154 
3156 {
3157  return "B0S*.gen";
3158 }
3159 
3160 QString Evoga::generationFilename(unsigned int generation, unsigned int seed)
3161 {
3162  return "G" + QString::number(generation) + "S" + QString::number(seed) + QString(".gen");
3163 }
3164 
3166 {
3167  return "G*S*.gen";
3168 }
3169 
3171 {
3172  numThreads = 1;
3173 }
3174 
3175 QString Evoga::retentionsFilename(unsigned int seed)
3176 {
3177  return "retentionS" + QString::number(seed) + QString(".stat");
3178 }
3179 
3180 
3181 //SPECIALIZER EVOLUTION METHODS
3182 /*
3183  * Main function of the Genetic Algorithm (Specializer Steady State Version)
3184  * --- at the moment works only for positive fitness values
3185  */
3186 
3188 { //SEQUENTIAL VERSION
3189  int rp; //replication
3190  int gn; //generation
3191  int id; //individuals
3192  double initFit;
3193  double minfit=9999;
3194  int minid=-1;
3195  double maxFit;
3196  int indMax;
3197  float final_mrate;
3198  int startGeneration=0;
3199  char statfile[128];
3200  char genFile[128];
3201  char filename[64];
3202  FILE * pFile;
3203  QVector< int* > actualTeam;
3204  QVector< int* > allIndividuals;
3205  QVector< double > subsFitness;
3206  int raffle,nEval;
3207  QVector< int > subsVec;
3208  double currentRetentionRate;
3209 
3210  subsVec.resize(popSize);
3211  actualTeam.resize(popSize);
3212  allIndividuals.resize(popSize*2);
3213  subsFitness.resize(popSize);
3214 
3215  final_mrate = mutation;
3216  Logger::info("EVOLUTION: specializer steady state (sequential)");
3217  Logger::info("Number of replications: " + QString::number(nreplications));
3218 
3219  // Creating evaluator objects in case of a multithread simulation. Also setting the actual number of threads used
3220  QVector<EvaluatorThreadForEvoga*> evaluators(popSize, NULL);
3221  if (numThreads > 1) {
3222  for (int i = 0; i < evaluators.size(); i++) {
3224  newExp->setEvoga(this);
3225  evaluators[i] = new EvaluatorThreadForEvoga(this, newExp);
3226  }
3227  QThreadPool::globalInstance()->setMaxThreadCount(numThreads);
3228  }
3229  for(rp=0;rp<nreplications;rp++) { // replications
3230  startGeneration=0;
3231  limitationFactor = 1.0;
3232  mutation=initial_mutation; // initially mutation (default 50%)
3233  //setSeed(getSeed());
3234  setSeed(getStartingSeed()+rp);
3235  Logger::info(QString("Replication %1, seed: %2").arg(rp+1).arg(getStartingSeed()+rp));
3237  randomizePop();
3238  // --- section runnable only if there is an Evonet object
3239  if ( hasResource( "evonet" ) ) {
3241  }
3242 
3243  emit startingReplication( rp );
3244  QTime evotimer;
3245  evotimer.start();
3246 
3247  //code to recovery a previous evolution
3248  sprintf(statfile,"statS%d.fit", getStartingSeed()+rp);
3249  //now check if the file exists
3250  DataChunk statTest(QString("stattest"),Qt::blue,2000,false);
3251  if (statTest.loadRawData(QString(statfile),0)) {
3252  startGeneration=statTest.getIndex();
3253  sprintf(genFile,"G%dS%d.gen",startGeneration,getStartingSeed()+rp);
3254  Logger::info("Recovering from startGeneration: " + QString::number(startGeneration));
3255  Logger::info(QString("Loading file: ") + genFile);
3256  loadallg(startGeneration,genFile);
3257  cgen=startGeneration;
3258  mutation=mutation-startGeneration*mutationdecay;
3259  if (mutation<final_mrate) mutation=final_mrate;
3260  emit recoveredInterruptedEvolution( QString(statfile) );
3261  }//end evolution recovery code
3262 
3263  // Resizing genome
3265  genome.resize(popSize * 2);
3266  for(gn=startGeneration;gn<nogenerations;gn++) { // generations
3267  evotimer.restart();
3268  Logger::info(QString("Generation %1").arg(gn+1));
3269  for (int i = 0; i < popSize; i++) { //produce the offsprings
3270  copyGenes(i, popSize + i, 1); //generate a variation by duplicating and mutating
3271  //evaluators[i]->setGenotype(popSize + i);
3272  allIndividuals[i]=actualTeam[i]=getGenesForIndividual(i);
3273  allIndividuals[i+popSize]=getGenesForIndividual(i+popSize);
3274  }
3275  //test the actual team of individuals - this should be done first of all so it is done in a monothread mode
3276  exp->initGeneration(gn);
3277  //copy here the individuals to be tested
3278  for(int i=0;i<popSize;i++)
3279  exp->m_weightIndividual[i] = actualTeam[i];
3280  if ( commitStep() ) { return; }
3281  initFit=0.0;
3282  exp->doAllTrialsForIndividual(-1); //-1 means that the team will be tested without any substitution
3283  initFit = exp->getFitness();
3284  if (isStopped()) { // stop evolution
3285  return;
3286  }
3287  exp->endGeneration(gn);
3288  if ( commitStep() ) { return; }
3289  //end evaluation the actual team
3290 
3291  for(int offspring=0;offspring<popSize;offspring++){
3292  if(numThreads>1){ //MULTITHREAD
3293  // Creating evaluator objects and setting the actual number of threads used
3294  for (int i = 0; i < evaluators.size(); i++) {
3295  evaluators[i]->getExperiment()->initGeneration(gn);
3296  evaluators[i]->getExperiment()->m_weightIndividual[i] = allIndividuals[offspring+popSize]; //change the individual i by the offspring being tested
3297  }
3298  QThreadPool::globalInstance()->setMaxThreadCount(numThreads);
3299  if (commitStep()) return; // stop the evolution process
3300 
3301  // Now starting parallel evaluation of parents and wating for it to finish
3302  QFuture<void> evaluationFuture;
3303  evaluationFuture = QtConcurrent::map(evaluators, runEvaluatorThreadForEvoga);
3304  evaluationFuture.waitForFinished();
3305  if (commitStep()) return; // stop the evolution process
3306  //get the fitness value for each substitution
3307  for (int i = 0; i < popSize; i++) {
3308  subsFitness[i] = evaluators[i]->getFitness();
3309  evaluators[i]->getExperiment()->m_weightIndividual[i] = actualTeam[i];
3310  }
3311 
3312  }else{ //MONOTHREAD
3313  for (int i = 0; i < popSize;i++) {
3314  exp->m_weightIndividual[i] = allIndividuals[offspring+popSize]; //change the individual i by the offspring being tested
3315  exp->doAllTrialsForIndividual(i); //the individual passed as parameter (i) is the substituted individual
3316  subsFitness[i] = exp->getFitness();
3317  exp->m_weightIndividual[i] = actualTeam[i]; //replace the individual substituted
3318  }
3319  }
3320 
3321  //HERE STARTS THE SELECTION PART - each should be done one offspring at a time
3322  currentRetentionRate = 0.0;
3323  maxFit = initFit;
3324  indMax = -1;
3325  for(int i=0;i<popSize;i++){ //search which substitution produces the greatest improvement
3326  if(limitRetention)
3327  subsFitness[i] *= limitationFactor;
3328  if(subsFitness[i]>maxFit){
3329  maxFit = subsFitness[i];
3330  indMax = i;
3331  }
3332  Logger::info(QString("Changing the policy %1 by the policy %2 produces a fitness of: %3 (original is %4)").arg(i).arg(offspring+popSize).arg(subsFitness[i]).arg(initFit));
3333  }
3334  if(indMax!=-1){ //if some substitution produces improvement, replace it with the offspring
3335  copyGenes(offspring+popSize, indMax, 0);
3336  actualTeam[indMax] = allIndividuals[offspring+popSize];
3337  Logger::info(QString("Substituting the policy %1 by the policy %2, and increasing the fitness by %3").arg(indMax).arg(offspring+popSize).arg(maxFit-initFit));
3338  initFit = maxFit;
3339  subsVec[offspring] = indMax;
3340  currentRetentionRate += 1.0/popSize;
3341  }else{
3342  Logger::info(QString("Policy %1 won't be used because it presents no performance improvement.").arg(offspring+popSize));
3343  subsVec[offspring] = -1;
3344  }
3345  }
3346 
3347  //statistics to keep compatibility -- set all values with the maxFitness of this generation
3348  statfit[cgen][0] = statfit[cgen][1] = statfit[cgen][2] = faverage = fmax = fmin = maxFit;
3349  saveFStat();
3350 
3351  if(saveRetStat)
3352  saveRStat(subsVec);
3353 
3354  emit endGeneration( cgen, fmax, faverage, fmin );
3355 
3356  if (commitStep()) {
3357  return; // stop the evolution process
3358  }
3359 
3360  cgen++;
3361  if (mutation > final_mrate) {
3363  } else {
3364  mutation = final_mrate;
3365  }
3366 
3367  limitationFactor += (targetRetentionRate-currentRetentionRate)/10.0;
3368  if (limitationFactor > 1.0)
3369  limitationFactor = 1.0;
3370 
3371  //always save in order to be able to resume the evolution process, but keep only the last gen file unless it has to be saved by the param savePopulationEachNGenerations
3372  saveallg();
3373 
3374  //remove the previous genfile unless it has to be kept because of the savePopulationEachNGenerations param
3375  if ((savePopulationEachNGenerations == 0) || (gn>1 && ((gn-1) % (savePopulationEachNGenerations) != 0))) {
3376  //EX: gn 998 = G999S1.gen --- gn 999 = G1000S1.gen --- gn = 1000 = G1001S1.gen --- gn 1001 = G1002S1.gen
3377  sprintf(filename,"G%dS%d.gen",gn,currentSeed);
3378  if(!QFile::remove(filename)) {
3379  Logger::warning(QString("Error deleting temporary gen file: ") + QString::fromStdString(filename));
3380  }
3381  }
3382 
3383  Logger::info(QString("Generation %1 took %2 minutes").arg(gn+1).arg((double)evotimer.elapsed()/60000.0, 0, 'f', 2));
3384  if(limitRetention)
3385  Logger::info(QString(" --- Target retention rate: %1; current rate: %2; fitness limitation factor: %3").arg(targetRetentionRate).arg(currentRetentionRate).arg(limitationFactor));
3386  fflush(stdout);
3387  //---------------------------------
3388  }
3389  saveallg();
3390  }
3391  if(numThreads>1){
3392  // Deleting all evaluators
3393  for (int i = 0; i < evaluators.size(); i++) {
3394  delete evaluators[i];
3395  }
3396  }
3397 }
3398 
3399 //SPECIALIZER EVOLUTION METHODS
3400 /*
3401  * Main function of the Genetic Algorithm (Specializer Steady State Version)
3402  *
3403  */
3404 
3406 { //TEAM VERSION
3407  int rp; //replication
3408  int gn; //generation
3409 
3410  float final_mrate;
3411  int startGeneration=0;
3412  char statfile[128];
3413  char genFile[128];
3414  char filename[64];
3415  double currentRetentionRate;
3416  int numTeams = popSize/numModules;
3417  int totalTeams = numTeams + numTeams*noffspring;
3418  QVector< int* > allIndividuals(popSize*2);
3419  QVector< QVector<int> > composedGen(totalTeams);
3420  QVector< double > parentFitVec(numTeams);
3421  QVector<FitnessAndId> allTeamsFitness(totalTeams);
3422  QVector<FitnessAndId> selectedTeamFitness(numTeams);
3423  QVector<FitnessAndId> parentFitness(numTeams);
3424  QVector<FitnessAndId> childrenFitness(numTeams*noffspring);
3425  QVector< QVector<int> > savedTeams(numTeams);
3426  QVector<int*> indivSelected(popSize);
3427  QVector<int> translatedIndiv(popSize*2),subsVec(numTeams);
3428  QVector< QVector<int> > translatedComposedTeams(totalTeams);
3429  int winner,overwrited,raffle,idOffspring,numSelected;
3430  bool flagModificated;
3431 
3432  for(int i=0;i<composedGen.size();i++)
3433  composedGen[i].resize(numModules);
3434 
3435  final_mrate = mutation;
3436  Logger::info("EVOLUTION: specializer steady state (team representation(modules))");
3437  Logger::info("Number of replications: " + QString::number(nreplications));
3438 
3439  // Creating evaluator objects in case of a multithread simulation. Also setting the actual number of threads used
3440  QVector<EvaluatorThreadForEvoga*> evaluators(numTeams, NULL);
3441  if (numThreads > 1) {
3442  for (int i = 0; i < evaluators.size(); i++) {
3444  newExp->setEvoga(this);
3445  evaluators[i] = new EvaluatorThreadForEvoga(this, newExp);
3446  }
3447  QThreadPool::globalInstance()->setMaxThreadCount(numThreads);
3448  }
3449  for(rp=0;rp<nreplications;rp++) { // replications
3450  startGeneration=0;
3451 
3452  //1-INITIALIZE PARENT RANDOM TEAMS
3453  for(int i=0;i<numTeams;i++){ //initializing random teams
3454  for(int j=0;j<numModules;j++)
3455  composedGen[i][j] = rand()%(popSize);
3456  }
3457 
3458 
3459  limitationFactor = 1.0;
3460  mutation=initial_mutation; // initially mutation (default 50%)
3461  //setSeed(getSeed());
3462  setSeed(getStartingSeed()+rp);
3463  Logger::info(QString("Replication %1, seed: %2").arg(rp+1).arg(getStartingSeed()+rp));
3465  randomizePop();
3466 
3467  // --- section runnable only if there is an Evonet object
3468  if ( hasResource( "evonet" ) ) {
3470  }
3471 
3472  emit startingReplication( rp );
3473  QTime evotimer;
3474  evotimer.start();
3475 
3476  //1.1-LOAD SAVED TEAMS IF THERE IS A PREVIOUS EVOLUTION
3477  //code to recovery a previous evolution
3478  sprintf(statfile,"statS%d.fit", getStartingSeed()+rp);
3479  //now check if the file exists
3480  DataChunk statTest(QString("stattest"),Qt::blue,2000,false);
3481  if (statTest.loadRawData(QString(statfile),0)) {
3482  startGeneration=statTest.getIndex();
3483  sprintf(genFile,"G%dS%d.gen",startGeneration,getStartingSeed()+rp);
3484  Logger::info("Recovering from startGeneration: " + QString::number(startGeneration));
3485  Logger::info(QString("Loading file: ") + genFile);
3486  loadallg(-1,genFile);
3487  sprintf(genFile,"G%dS%d.composed.gen",startGeneration,getStartingSeed()+rp);
3488  loadallTeams(-1,genFile,composedGen);
3489  cgen=startGeneration;
3490  mutation=mutation-startGeneration*mutationdecay;
3491  if (mutation<final_mrate) mutation=final_mrate;
3492  emit recoveredInterruptedEvolution( QString(statfile) );
3493 
3494  }//end evolution recovery code
3495 
3496  // Resizing genome
3498  genome.resize(popSize * 2);
3499 
3500  for(gn=startGeneration;gn<nogenerations;gn++) { // generations
3501  evotimer.restart();
3502  Logger::info(QString("Generation %1").arg(gn+1));
3503  for (int i = 0; i < popSize; i++) { //produce the individuals offsprings
3504  copyGenes(i, popSize + i, 1); //generate a variation by duplicating and mutating
3505  //evaluators[i]->setGenotype(popSize + i);
3506  allIndividuals[i]=getGenesForIndividual(i);
3507  allIndividuals[i+popSize]=getGenesForIndividual(i+popSize);
3508  }
3509 
3510  //2-EVALUATE PARENTS
3511  if(numThreads>1){ //MULTITHREAD
3512  // Creating evaluator objects and setting the actual number of threads used
3513  for (int i = 0; i < evaluators.size(); i++) {
3514  evaluators[i]->getExperiment()->initGeneration(gn);
3515  evaluators[i]->getExperiment()->m_weightIndividual.resize(numModules);
3516  for(int j=0;j<numModules;j++) //setting the weights of the team i to the evaluator
3517  evaluators[i]->getExperiment()->m_weightIndividual[j] = allIndividuals[composedGen[i][j]];
3518  }
3519  QThreadPool::globalInstance()->setMaxThreadCount(numThreads);
3520 
3521  if (commitStep()) return; // stop the evolution process
3522 
3523  // Now starting parallel evaluation of parents and wating for it to finish
3524  QFuture<void> evaluationFuture;
3525  evaluationFuture = QtConcurrent::map(evaluators, runEvaluatorThreadForEvoga);
3526  evaluationFuture.waitForFinished();
3527  if (commitStep()) return; // stop the evolution process
3528  //get fitness
3529  for (int i = 0; i < numTeams; i++) {
3530  parentFitVec[i] = evaluators[i]->getFitness();
3531  parentFitness[i].id = allTeamsFitness[i].id = i;
3532  parentFitness[i].fitness = allTeamsFitness[i].fitness = evaluators[i]->getFitness();
3533  }
3534  }else{ //MONOTHREAD
3535  exp->initGeneration(gn);
3536  for (int i = 0; i < numTeams;i++) { //test parents
3538  for(int j=0;j<numModules;j++)
3539  exp->m_weightIndividual[j] = allIndividuals[composedGen[i][j]];
3540 
3542  //get fitness
3543  parentFitVec[i] = exp->getFitness();
3544  parentFitness[i].id = allTeamsFitness[i].id = i;
3545  parentFitness[i].fitness = allTeamsFitness[i].fitness = exp->getFitness();
3546  }
3547  }
3548  //3-CROSSOVER, MUTATE AND DUPLICATE FOR GENERATING THE OFFSPRINGS
3549  for(int i=0;i<numTeams;i++){ //for each offspring to be generated
3550 
3551  //GENERATE ONE OFFSPRING
3552  for(int offspring=0;offspring<noffspring;offspring++){
3553  idOffspring = i*noffspring+numTeams+offspring;
3554  //copy all modules from the parent to the offspring
3555  for(int j=0;j<numModules;j++)
3556  composedGen[idOffspring][j] = composedGen[i][j];
3557 
3558  flagModificated = false;
3559 
3560  //3.1-CROSSOVER
3561  raffle = rand()%100;
3562  if(raffle/100.0<crossRate){
3563  //select an individual according to roulette wheel
3564  winner = rouletteWheel(parentFitVec);
3565  //select the crossover point
3566  raffle = rand()%(numModules-2);
3567  int initialPoint,finalPoint;
3568  if(rand()%2==0){ //define the order of the crossover: 1st parent then winner
3569  //copy the individuals from the winner individual
3570  initialPoint = (raffle+1);
3571  finalPoint = numModules;
3572  }else{//1st winner then parent
3573  //copy the individuals from the original parent
3574  initialPoint = 0;
3575  finalPoint = numModules;
3576  }
3577  for(int j=initialPoint;j<finalPoint;j++)
3578  composedGen[idOffspring][j] = composedGen[winner][j];
3579  flagModificated = true;
3580  }
3581 
3582  //3.2-MUTATION
3583  for(int j=0;j<numModules;j++){
3584  raffle = rand()%100;
3585  if(raffle/100.0<modulesMutationRate){ //check if this individual will be mutated
3586  if(mutateOnlyRelatives) //if yes, check if it should be substituted by its offspring, or any offspring
3587  composedGen[idOffspring][j] += popSize;
3588  else
3589  composedGen[idOffspring][j] = rand()%popSize+popSize;
3590  flagModificated = true;
3591  }
3592  }
3593 
3594  //3.3-DUPLICATION
3595  raffle = rand()%100;
3596  if(raffle/100.0<overwriteRate){
3597  winner = rand()%numModules;
3598  for(overwrited=rand()%numModules;overwrited==winner;overwrited=rand()%numModules);
3599  composedGen[idOffspring][overwrited] = composedGen[idOffspring][winner];
3600  flagModificated = true;
3601  }
3602 
3603  if(!flagModificated) //if the offspring is equal to the parent, repeat the process for this offspring
3604  offspring--;
3605  }
3606  }
3607 
3608  //4-EVALUATE CHILDREN
3609  if(numThreads>1){ //MULTITHREAD
3610 
3611  for(int offspring=0;offspring<noffspring;offspring++){
3612  // Creating evaluator objects and setting the actual number of threads used
3613  for (int i = 0; i < evaluators.size(); i++) {
3614  idOffspring = i*noffspring+numTeams+offspring;
3615  evaluators[i]->getExperiment()->m_weightIndividual.resize(composedGen[idOffspring].size());//for the case where teams can have different sizes
3616  for(int j=0;j<composedGen[idOffspring].size();j++) //setting the weights of the team i to the evaluator
3617  evaluators[i]->getExperiment()->m_weightIndividual[j] = allIndividuals[composedGen[idOffspring][j]];
3618  }
3619  QThreadPool::globalInstance()->setMaxThreadCount(numThreads);
3620 
3621  if (commitStep()) return; // stop the evolution process
3622 
3623  // Now starting parallel evaluation of children and wating for it to finish
3624  QFuture<void> evaluationFuture;
3625  evaluationFuture = QtConcurrent::map(evaluators, runEvaluatorThreadForEvoga);
3626  evaluationFuture.waitForFinished();
3627  if (commitStep()) return; // stop the evolution process
3628  //get fitness
3629  for (int i = 0; i < evaluators.size(); i++) {
3630  idOffspring = i*noffspring+numTeams+offspring;
3631  childrenFitness[i].id = allTeamsFitness[idOffspring].id = idOffspring;
3632  childrenFitness[i].fitness = allTeamsFitness[idOffspring].fitness = evaluators[i]->getFitness();
3633  if(limitRetention)
3634  childrenFitness[i].fitness *= limitationFactor;
3635  allTeamsFitness[idOffspring].fitness *= limitationFactor;
3636  }
3637  }
3638 
3639  // Calling endGeneration on all evaluator
3640  for (int i = 0; i < evaluators.size(); i++) {
3641  evaluators[i]->getExperiment()->endGeneration(gn);
3642  }
3643  if (commitStep()) return; // stop the evolution process
3644 
3645  }else{ //MONOTHREAD
3646  for (int i = 0; i < totalTeams - numTeams;i++) { //test children - testing all but the parents
3648  for(int j=0;j<numModules;j++)
3649  exp->m_weightIndividual[j] = allIndividuals[composedGen[numTeams+i][j]];
3650  exp->doAllTrialsForIndividual(i+numTeams);
3651  //get fitness
3652  childrenFitness[i].id = allTeamsFitness[i+numTeams].id = i+numTeams;
3653  childrenFitness[i].fitness = allTeamsFitness[i+numTeams].fitness = exp->getFitness();
3654  if(limitRetention){
3655  childrenFitness[i].fitness *= limitationFactor;
3656  allTeamsFitness[i+numTeams].fitness *= limitationFactor;
3657  }
3658  }
3659  exp->endGeneration(gn);
3660  }
3661 
3662  //5-SELECTION
3663 
3664  translatedIndiv.fill(-1);
3665  currentRetentionRate = 0.0;
3666  if(selectionType=="rankBased"){ //GET INDIVIDUALS WITH THE BEST FITNESS
3667  qSort(allTeamsFitness); //sort in ascending order
3668  numSelected = 0;
3669  for(int i=totalTeams-1;i>0;i--){ //now start with the teams with higher fitness - and proceed until numTeams were selected
3670 
3671  if((rand()%100)/100.0<rankBasedProb){//select the teams with greatest fitness with a probability defined by the user
3672  selectedTeamFitness[numSelected] = allTeamsFitness[i];
3673  parentFitVec[numSelected] = allTeamsFitness[i].fitness;
3674  numSelected++;
3675  }
3676 
3677  if(numSelected==numTeams)
3678  break;
3679  }
3680 
3681  for(int i=0;i<totalTeams;i++)
3682  Logger::info(QString("i=%3 id=%1; fitness=%2").arg(allTeamsFitness[i].id).arg(allTeamsFitness[i].fitness).arg(i));
3683 
3684  }else if(selectionType=="species"){ //substitute the parent by its offspring with the best fitness
3685  for(int i=0;i<numTeams;i++){
3686  Logger::info(QString("i=%3 id=%1; fitness=%2").arg(allTeamsFitness[i].id).arg(allTeamsFitness[i].fitness).arg(i));
3687  selectedTeamFitness[i] = allTeamsFitness[i]; //the parent is initially selected
3688  for(int offspring=0;offspring<noffspring;offspring++){ //check each offspring team and select it if its fitness is greater than actual selected one
3689  idOffspring = i*noffspring+numTeams+offspring;
3690  Logger::info(QString("Offsprings =======>i=%3 id=%1; fitness=%2").arg(allTeamsFitness[idOffspring].id).arg(allTeamsFitness[idOffspring].fitness).arg(idOffspring));
3691  if(selectedTeamFitness[i].fitness<allTeamsFitness[idOffspring].fitness){ //if some of its offspring has a better fitness, select it
3692  selectedTeamFitness[i] = allTeamsFitness[idOffspring];
3693  parentFitVec[i] = allTeamsFitness[idOffspring].fitness;
3694  }
3695  }
3696  }
3697  }
3698 
3699  //translating and completing selected individuals
3700  numSelected = 0;
3701  qSort(allTeamsFitness); //sort in ascending order
3702  FitnessAndId translateTeam;
3703  int ind = totalTeams-1;
3704  for(int i=0;i<totalTeams;i++){
3705  translatedComposedTeams[i].resize(numModules);
3706  if(i<numTeams){ //pick individuals from the selected teams vector
3707  translateTeam = selectedTeamFitness[i];
3708 
3709  if(selectedTeamFitness[i].id>=numTeams) //if the id is greater than the number of teams, it means that a parent was replaced
3710  currentRetentionRate += 1.0/numTeams;
3711 
3712  }else{ //if there were no sufficient individuals in the selected team vector, get individuals from the teams with higher fitness that weren't selected
3713  for(int i=0;i<numTeams;i++){
3714  if(allTeamsFitness[ind].id==selectedTeamFitness[i].id){ //if this team is already selected pick the next one and restart the check to see if the next is already selected or not
3715  ind--;
3716  i=-1;
3717  }
3718  }
3719  translateTeam = allTeamsFitness[ind];
3720  ind--;
3721  }
3722 
3723  for(int j=0;j<numModules;j++){ //since the individuals that participates in the teams with the better fitness value will be selected, it will be necessary to change(translate) their id
3724  if(translatedIndiv[composedGen[translateTeam.id][j]]==-1){
3725  translatedIndiv[composedGen[translateTeam.id][j]] = numSelected;
3726  copyGenes(composedGen[translateTeam.id][j], numSelected, 0);
3727  indivSelected[numSelected] = allIndividuals[composedGen[translateTeam.id][j]];
3728  numSelected++;
3729  }
3730  translatedComposedTeams[i][j] = translatedIndiv[composedGen[translateTeam.id][j]];
3731  if(numSelected==popSize)
3732  break;
3733  }
3734  if(numSelected==popSize)
3735  break;
3736  }
3737 
3738  //computing statistics and saving teams for the next generation
3739  faverage = 0;
3740  fmax = fmin = parentFitVec[0];
3741  for(int i=0;i<numTeams;i++){
3742  composedGen[i] = savedTeams[i] = translatedComposedTeams[i];
3743  subsVec[i] = selectedTeamFitness[i].id;
3744 
3745  faverage += parentFitVec[i];
3746  if(parentFitVec[i]>fmax)
3747  fmax = parentFitVec[i];
3748  else if(parentFitVec[i]<fmin)
3749  fmin = parentFitVec[i];
3750  }
3751  faverage /= numTeams;
3752  //END SELECTION
3753 
3754  //statistics to keep compatibility -- set all values with the maxFitness of this generation
3755  statfit[cgen][0]=fmax;
3756  statfit[cgen][1]=faverage;
3757  statfit[cgen][2]=fmin;
3758  saveFStat();
3759 
3760  if(saveRetStat)
3761  saveRStat(subsVec);
3762 
3763  emit endGeneration( cgen, fmax, faverage, fmin );
3764 
3765  if (commitStep()) {
3766  return; // stop the evolution process
3767  }
3768 
3769  cgen++;
3770  if (mutation > final_mrate) {
3772  } else {
3773  mutation = final_mrate;
3774  }
3775 
3776  limitationFactor += (targetRetentionRate-currentRetentionRate)/10.0;
3777  if (limitationFactor > 1.0)
3778  limitationFactor = 1.0;
3779 
3780 
3781  //always save in order to be able to resume the evolution process, but keep only the last gen file unless it has to be saved by the param savePopulationEachNGenerations
3782  saveallg();
3783  saveallgComposed(savedTeams);
3784  saveBestTeam(savedTeams,parentFitVec);
3785 
3786 
3787  //remove the previous genfile unless it has to be kept because of the savePopulationEachNGenerations param
3788  if ((savePopulationEachNGenerations == 0) || (gn>1 && ((gn-1) % (savePopulationEachNGenerations) != 0))) {
3789  //EX: gn 998 = G999S1.gen --- gn 999 = G1000S1.gen --- gn = 1000 = G1001S1.gen --- gn 1001 = G1002S1.gen
3790  sprintf(filename,"G%dS%d.gen",gn,currentSeed);
3791  if(!QFile::remove(filename)) {
3792  Logger::warning(QString("Error deleting temporary gen file: ") + QString::fromStdString(filename));
3793  }
3794 
3795  sprintf(filename,"G%dS%d.composed.gen",gn,currentSeed);
3796  if(!QFile::remove(filename)) {
3797  Logger::warning(QString("Error deleting temporary gen file: ") + QString::fromStdString(filename));
3798  }
3799 
3800  sprintf(filename,"B%dS%d.G%d.gen",0,this->currentSeed,gn);
3801  if(!QFile::remove(filename)) {
3802  Logger::warning(QString("Error deleting temporary gen file: ") + QString::fromStdString(filename));
3803  }
3804  }
3805 
3806  Logger::info(QString("Generation %1 took %2 minutes - best individual fitness %3").arg(gn+1).arg((double)evotimer.elapsed()/60000.0, 0, 'f', 2).arg(fmax));
3807  if(limitRetention)
3808  Logger::info(QString(" --- Target retention rate: %1; current rate: %2; fitness limitation factor: %3").arg(targetRetentionRate).arg(currentRetentionRate).arg(limitationFactor));
3809  fflush(stdout);
3810  //---------------------------------
3811  }
3812  if(savedTeams[0].size()!=0){
3813  saveallg();
3814  saveallgComposed(savedTeams);
3815  saveBestTeam(savedTeams,parentFitVec);
3816  }
3817  }
3818  if(numThreads>1){
3819  // Deleting all evaluators
3820  for (int i = 0; i < evaluators.size(); i++) {
3821  delete evaluators[i];
3822  }
3823  }
3824 }
3825 
3826 
3827 //END SPECIALIZER EVOLUTION METHODS
3828 
3829 int Evoga::rouletteWheel(QVector<double> candidates){
3830  long double raffle, sum = 0.0;
3831  int i;
3832  for(i=0;i<candidates.size();sum += candidates[i]+1,i++);
3833  raffle = (rand()%((int) sum*1000))/1000.0; //generating a random double with 3 decimal places
3834  for(i=0;raffle>0;raffle-=(candidates[i]+1),i++);
3835  return i-1;
3836 }
3837 
3838 } // end namespace farsa
3839 
3840 // All the suff below is to restore the warning state on Windows
3841 #if defined(_MSC_VER)
3842  #pragma warning(pop)
3843 #endif
bool useGaussian
Flag to decide whether using gaussian distribution to generate offspring.
Definition: evoga.h:789
void usableResources(QStringList resources)
int getGenotypeId() const
Returns the id of the genotype used in this experiment.
Definition: evoga.cpp:202
void mreproduce()
Identify the best individuals and copy their genotypes into the bestgenome Matrix It also save the be...
Definition: evoga.cpp:617
float getFreeParameter(int i)
return the value of the ith parameter (normalized in the range [-wrange, wrange]
Definition: evonet.cpp:1075
QVector< int * > m_weightIndividual
Added by Jonata for the SpecializerSteadyState GA.
bool minimization
Flags whether the fitness function is set to solve a minimization problem.
Definition: evoga.h:817
virtual void setCurrentMutationRate(double mutation_rate)
Set the current mutation rate to use.
Definition: evoga.cpp:3114
virtual QString generationFilename()
Returns the template name (regular expression) for "generation" files.
Definition: evoga.cpp:3165
QString savedExperimentPrefix
A copy of the prefix for experiment parameters.
Definition: evoga.h:869
int * getGenes(int ind)
Return a pointer to the genome of one individual of the current population.
Definition: evoga.cpp:1008
EvaluatorThreadForEvoga(Evoga *ga, EvoRobotExperiment *exp)
Constructor.
Definition: evoga.cpp:65
~EvaluatorThreadForEvoga()
Destructor.
Definition: evoga.cpp:74
QString evolutionType
specify the type of the evolution process to execute This string can only assume two values at the mo...
Definition: evoga.h:725
void recoveredInterruptedEvolution(QString statfile)
emitted when an interrupted evolution has been recovered and it's going to start from there ...
void getLastFStat(double &min, double &max, double &average)
return the last value of min, max and average fitness
Definition: evoga.cpp:853
FARSA_UTIL_API RandomGenerator * globalRNG
virtual void setNetParameters(float *genes)
Sets the free parameters of the neural network. This is done for all agents, even disabled ones...
static QString getString(ConfigurationParameters &params, QString paramPath, QString def=QString())
double * tfitness
A pointer to a vector used to store the sum of the fitness obtained during different evaluations of a...
Definition: evoga.h:714
EvoRobotExperiment * exp
the EvoRobotExperiment
Definition: evoga.h:598
virtual double getCurrentMutationRate()
Returns the current mutation rate.
Definition: evoga.cpp:3110
bool dissociateCovMatrix
Flags whether to dissociate back-propagation effect on the xNES covariance matrix update...
Definition: evoga.h:823
virtual void save(ConfigurationParameters &params, QString prefix)
Save the actual status of parameters into the ConfigurationParameters object passed.
Definition: evoga.cpp:2880
double mutation
The mutation rate can vary from 0 to 1 continuosly to express probability in the range [0...
Definition: evoga.h:735
virtual void initGeneration(int generation)
Called at the beginning of a generation. This function is NEVER called concurrently on different obje...
bool mutateOnlyRelatives
Wheater a module should be replace by its own offspring or by any offspring – specializerSteadyState...
Definition: evoga.h:840
float getWrange()
return the value of wrange (which also determine the range in which all parameters are normalized) ...
Definition: evonet.cpp:1162
void run()
Runs the experiment.
Definition: evoga.cpp:103
void doAllTrialsForIndividual(int individual)
Performs all trials for the given individual.
double modulesMutationRate
The probability that a module will be mutated on a team – specializerSteadyState.
Definition: evoga.h:837
bool isStopped()
return true if the evolution process has been stopped with stop()
Definition: evoga.cpp:3050
void evolveSteadyState()
Main function of the Genetic Algorithm (Steady State Version) Each individual of the population is al...
Definition: evoga.cpp:2382
double ** statfit
A matrix that store the statistics (average, min, and max fitness) for all generations.
Definition: evoga.h:718
virtual int * getGenesForIndividual(unsigned int id)
Returns the array of genes for the given individual.
Definition: evoga.cpp:3135
bool limitRetention
Wheather the retention should be limited or not.
Definition: evoga.h:831
void evolveSpecializerSteadyState2()
Main function of the Genetic Algorithm developed by Jonata - Team Version.
Definition: evoga.cpp:3405
void evolveGenerational()
Main function of the Genetic Algorithm (Generational, Truncation Selection Version) The size of the p...
Definition: evoga.cpp:2676
void resetGenerationCounter()
Reset the generation counter to 0.
Definition: evoga.cpp:1021
int nogenerations
The number of generations specified with the ngenerations parameter.
Definition: evoga.h:727
void saveRStat(QVector< int > subsVec)
Save the information regarding the offspring retention by appending a line to the retention statistic...
Definition: evoga.cpp:832
void copyPheParameters(int *pheGene)
transorm floating point parameters normalized in the range [-wrange,range] into integer parameters in...
Definition: evonet.cpp:1120
int fbestgen
fitness best generation (maximum)
Definition: evoga.h:753
void resetStop()
reset the stopped status to false
Definition: evoga.cpp:3054
int getGenotypeId() const
Returns the id of the genotype used in this experiment.
Definition: evoga.cpp:95
void reproduce()
Identify the best individuals and copy their genotypes into the bestgenome Matrix It also save the be...
Definition: evoga.cpp:471
void saveFStat()
Save the average, minimal and maximal fitness by appending a line to the statSd.fit file...
Definition: evoga.cpp:815
int glen
genome lenght (number of free parameters)
Definition: evoga.h:602
double getError() const
Returns the similarity error of the last run.
Definition: evoga.cpp:232
void printPop()
Print the fitness of the individuals of the current population.
Definition: evoga.cpp:684
int savePopulationEachNGenerations
How often (i.e. how many generations) we want to same the population genome in a .gen file.
Definition: evoga.h:767
int numStartInd
Number of possible individuals from which finding out the starting individual of XNES.
Definition: evoga.h:799
double fmin
fitness statistics (minimum, maximum, and average fitness)
Definition: evoga.h:749
virtual unsigned int getCurrentGeneration()
Returns the current generation.
Definition: evoga.cpp:3086
void setEvoga(Evoga *ga)
Set the Evoga on which this EvoRobotExperiment is used.
int numModules
The number of modules that a genotype should use.
Definition: evoga.h:582
bool elitism
if the Evoga will use elitism or not
Definition: evoga.h:604
FARSA_UTIL_TEMPLATE const T max(const T &t1, const U &t2)
EvoRobotExperiment * getExperiment()
Returns the experiment we run.
Definition: evoga.cpp:242
void evolveSpecializerSteadyState()
Main function of the Genetic Algorithm developed by Jonata.
Definition: evoga.cpp:3187
QString selectionType
The type of selection that will be used to define which individuals will survive. ...
Definition: evoga.h:846
void updateGenomeFromEvonet(int ind)
update the genome of the individual to match the current weights of Evonet
Definition: evoga.cpp:1050
int nreproducing
number of individuals allowed to reproduce
Definition: evoga.h:606
float fitness
Fitness.
Definition: evoga.cpp:292
int pheGen
How often (in terms of number of generations) the best phenotype must be saved.
Definition: evoga.h:813
bool stopEvolution
Flag used to request to end the evolutionary process.
Definition: evoga.h:757
virtual void shareResourcesWith(ResourcesUser *buddy)
unsigned int numThreads
The number of concurrent threads to use.
Definition: evoga.h:765
double mutationdecay
The amount of reduction of the mutation generations during the first generations until it reaches the...
Definition: evoga.h:739
ConfigurationParameters savedConfigurationParameters
A copy of the ConfigurationParameters object that was passed to our configure method.
Definition: evoga.h:862
double offspringMutRange
The mutation range used in XNES algorithm to generate the offspring.
Definition: evoga.h:787
void stop()
stop the running evolution process as soon as possible
Definition: evoga.cpp:3035
void setGenotype(int id)
Configures the experiment with the given genotype id.
Definition: evoga.cpp:84
int backPropOffspringUtilityRank
The utility rank of the backpropagation offspring in the second type of combination with xNES...
Definition: evoga.h:807
void run()
Runs the experiment.
Definition: evoga.cpp:210
double initial_mutation
The initial mutation rate setted when steadyState algorithm is used.
Definition: evoga.h:741
static const int MAXINDIVIDUALS
constant defining the maximimum number of individuals that Evoga can manage
Definition: evoga.h:73
double getFitness()
return the current value of the fitness
bool saveRetStat
Whether to save retentions statistics or not.
Definition: evoga.h:828
void putGenome(int fromgenome, int tobestgenome)
Copy the genome of one individual to the bestgenome matrix in a specific position.
Definition: evoga.cpp:429
virtual unsigned int getCurrentSeed()
Returns the current seed.
Definition: evoga.cpp:3096
void saveBestTeam(QVector< QVector< int > > teams, QVector< double > fitness)
Append the best team of the current population to the BdSd.composed.gen file.
Definition: evoga.cpp:577
this is an helper class for implementing multithread in Evoga
Definition: evoga.cpp:55
void setSeed(int seed)
double mutationRange
The mutation range used in XNES algorithm to initialize the individual.
Definition: evoga.h:785
static bool getBool(ConfigurationParameters &params, QString paramPath, bool def=false)
~Evoga()
Destructor.
Definition: evoga.cpp:360
void setGenotype(int id, float *genes)
Configures the experiment with the given genotype id.
Definition: evoga.cpp:191
int mrand(int i)
return a random integer generated with an uniform distribution in the range [0, i-1] ...
Definition: evoga.cpp:308
double offspringStdDev
Standard deviation to generate offspring.
Definition: evoga.h:795
double crossRate
The probability that a crossover will occur in an offspring team – specializerSteadyState.
Definition: evoga.h:834
void doNextStep()
Go ahead of one step if the EvoGa is in step-by-step modality, otherwise do nothing.
Definition: evoga.cpp:3070
int noffspring
number of sons
Definition: evoga.h:608
static void info(QString msg)
bool commitStep()
this method marks the point on which it is called as a commited step of evolution ...
Definition: evoga.cpp:3040
static void error(QString msg)
virtual unsigned int numLoadedGenotypes() const
Returns number of loaded genotypes.
Definition: evoga.cpp:3130
bool hasResource(QString name) const
double mutationLearningRate
The mutation learning rate used to generate offspring from backprop array.
Definition: evoga.h:801
void enableStepByStep(bool enable)
enable/disable the step-by-step modality of evolution process
Definition: evoga.cpp:3058
bool xnesCombination
Flag to decide whether combining xnes with backpropagation algorithm.
Definition: evoga.h:803
Evonet * getNeuralNetwork(int agentId=0)
Return the neural network used for the experiment.
int mutate(int w, double mut)
Mutate one gene Since genes are store as integer, this function first trasform them into 8 bits and t...
Definition: evoga.cpp:399
void randomizePop()
Randomize the genome of the population.
Definition: evoga.cpp:977
static void describe(QString type)
Add to Factory::typeDescriptions() the descriptions of all parameters and subgroups.
Definition: evoga.cpp:2886
virtual QString statisticsFilename(unsigned int seed)
Returns the name of the file with statistics (fitness) for the given seed.
Definition: evoga.cpp:3145
Genetic algorithm from evorobot more or less (spare parts)
Definition: evoga.h:50
double getFitness() const
Returns the fitness of the last run.
Definition: evoga.cpp:222
A simple structure keeping a fitness value and the id of a genotype.
Definition: evoga.cpp:287
int getGenomeLength()
Returns the length of the genome.
bool pheFileLoaded()
check whether a .phe file (with parameters description) has been loaded
Definition: evonet.cpp:1080
void getPheParametersAndMutationsFromEvonet()
transfer .phe info inside GA
Definition: evoga.cpp:1026
double getError()
return the current value of the error
int seed
The number used to initialized the seed of the first replication (successive replication use incremen...
Definition: evoga.h:731
float * mutations
vector of parameter-specific mutations
Definition: evoga.h:743
virtual QVector< EvoRobotExperiment * > getEvoRobotExperimentPool()
Returns a list of pointers to the EvoRobotExperiment objects used by the ga to evaluate agents...
Definition: evoga.cpp:3079
int savebest
save best savebest parents by default equals 1
Definition: evoga.h:747
void getMutations(float *mut)
set the mutation vector of the genetic algorithm that determine how parameters are mutated ...
Definition: evonet.cpp:1112
int * getBestGenes(int ind)
Return a pointer to the genome of one individual stored in the bestgenome matrix. ...
Definition: evoga.cpp:1016
virtual void configure(ConfigurationParameters &params, QString prefix)
Configures the object using a ConfigurationParameters object.
Definition: evoga.cpp:2784
virtual void endGeneration(int generation)
Called at the end of a generation. This function is NEVER called concurrently on different objects...
static double getDouble(ConfigurationParameters &params, QString paramPath, double def=0)
virtual QString retentionsFilename(unsigned int seed)
Returns the name of the file with statistics (retentions) for the given seed.
Definition: evoga.cpp:3175
static Descriptor addTypeDescription(QString type, QString shortHelp, QString longHelp=QString(""))
double gaussianStdDev
Standard deviation of the gaussian distribution.
Definition: evoga.h:793
QString getValue(QString path, bool alsoMatchParents=false) const
double targetRetentionRate
The target retention rate.
Definition: evoga.h:852
QWaitCondition waitForNextStep
the wait condition for waiting on step-by-step modality
Definition: evoga.h:763
void saveallgComposed(QVector< QVector< int > > composedGen)
Save the composed genome of the current population in a G?S?.composed.gen file.
Definition: evoga.cpp:792
virtual unsigned int getNumOfGenerations()
Returns the number of generations to do.
Definition: evoga.cpp:3106
bool specialUtilityRanking
Flags whether to use a special version to compute utility ranking.
Definition: evoga.h:825
this is an helper class for implementing multithread in xNES
Definition: evoga.cpp:161
virtual unsigned int loadGenotypes(QString filename)
Loads genotypes from the given file.
Definition: evoga.cpp:3118
int nreplications
The number of replications specified with the corresponding parameter.
Definition: evoga.h:729
double * ntfitness
A pointer to a vector used to store the total number of trials in which an unchanged individuals have...
Definition: evoga.h:716
Evoga()
Constructor.
Definition: evoga.cpp:318
void copyGenes(int from, int to, int mut)
Copy the genotype of an individual into the genotype of a second individual and introduce mutations T...
Definition: evoga.cpp:455
double rankBasedProb
The probability that the individuals with the highest fitness will be selected.
Definition: evoga.h:843
int currentSeed
The seed of the current generation (used for example to generate the name of the G?S?.gen files)
Definition: evoga.h:733
double fbest
fitness best
Definition: evoga.h:751
void newGASeed(int seed)
Called by the ga when the seed changes (e.g. in a new replication)
TypeToCreate * getObjectFromGroup(QString group, bool configure=true, bool forceObjectCreation=false)
bool dissociateInd
Flags whether to dissociate back-propagation effect on the xNES individual update.
Definition: evoga.h:821
~EvaluatorThreadForXnes()
Destructor.
Definition: evoga.cpp:180
float backPropOffspringFitnessIncreasePercentage
Percentage of increase of the fitness of the backpropagation offspring.
Definition: evoga.h:811
void computeFStat2()
Calculate the average, minimal and maximal fitness of the current population Assume that the fitness ...
Definition: evoga.cpp:732
QMutex mutexStepByStep
the mutex used for controlling the step-by-step modality
Definition: evoga.h:761
double limitationFactor
The limitation factor that will multiply the offsprings' fitness.
Definition: evoga.h:854
Evonet is the neural network taken from the EvoRobot.
Definition: evonet.h:121
int rouletteWheel(QVector< double > candidates)
perform a roulette wheel and return the winner's index
Definition: evoga.cpp:3829
void setSeed(int s)
Initialize the random number generator.
Definition: evoga.cpp:375
double * terror
A pointer to a vector used to store the sum of the errors obtained during different evaluations of an...
Definition: evoga.h:720
virtual QString bestsFilename()
Returns the template name (regular expression) for "best genomes" files.
Definition: evoga.cpp:3155
void save_net_blocks(const char *filename, int mode)
Save the description of the neural architecture into a .net of .phe file (see the create_net_block me...
Definition: evonet.cpp:658
double drand()
return a random floating point value generated with an uniform distribution in the range[0...
Definition: evoga.cpp:383
double gaussianMean
Mean of the gaussian distribution.
Definition: evoga.h:791
Population bestgenome
The matrix that contains a copy of the genome of the best individuals.
Definition: evoga.h:708
virtual void doNotUseMultipleThreads()
Forces execution of the GA using no threads (i.e., in the current thread)
Definition: evoga.cpp:3170
bool standardNes
Flags whether the standard xNES algorithm must be used (i.e. the parameters are set according to the ...
Definition: evoga.h:815
void startingReplication(int replication)
emitted when a replication is going to start
int cgen
current generation
Definition: evoga.h:745
double getGaussian(double var, double mean=0.0)
static const int MaxInteger
FARSA_UTIL_TEMPLATE const T min(const T &t1, const U &t2)
bool isEnabledStepByStep()
return true is the step-by-step modality is enabled, false otherwise
Definition: evoga.cpp:3066
void getGenome(int frombestgenome, int togenome, int mut)
Copy a genome stored in the bestgenome matrix into the genome of the current population Apply mutatio...
Definition: evoga.cpp:440
void setMutations(float *)
Set the mutation rate of each parameter.
Definition: evoga.cpp:1001
void setInitialPopulation(int *)
Overwrite the genome of all individuals with a manually specify vector of parameters (loaded from a ...
Definition: evoga.cpp:986
void loadgenotype(FILE *fp, int ind)
Load the genome of one individual in a text file.
Definition: evoga.cpp:859
EvoRobotExperiment * getExperiment()
Returns the experiment we run.
Definition: evoga.cpp:124
Population genome
The matrix that contain the genome of the corrent population.
Definition: evoga.h:706
virtual EvoRobotExperiment * getEvoRobotExperiment()
Returns a pointer to the EvoRobotExperiment object.
Definition: evoga.cpp:3074
void saveagenotype(FILE *fp, int ind)
Save the genome of one individual in a text file.
Definition: evoga.cpp:763
int freeParameters()
return number of defined free parameters
Definition: evonet.cpp:1070
bool averageIndividualFitnessOverGenerations
Whether to average an individual fitness with its previous one or not.
Definition: evoga.h:782
double getDouble(double min, double max)
void xnes()
Main function of the xNES Algorithm (exponential Natural Evolution Strategies) The size of the popula...
Definition: evoga.cpp:1299
virtual void postConfigureInitialization()
This function is called after all linked objects have been configured.
Definition: evoga.cpp:2938
static int getInt(ConfigurationParameters &params, QString paramPath, int def=0)
double overwriteRate
The probability that a module will be overwritten by another one – specializerSteadyState.
Definition: evoga.h:849
int popSize
population size
Definition: evoga.h:600
int loadedIndividuals
The number of individual genome loaded from a .gen file into the genome matrix (-1 when none has been...
Definition: evoga.h:712
void saveallg()
Save the genome of the current population in a G?S?.gen file.
Definition: evoga.cpp:773
virtual unsigned int getStartingSeed()
Returns the starting seed.
Definition: evoga.cpp:3091
void computeFStat()
Calculate the average, minimal and maximal fitness of the current population Assume that the fitness ...
Definition: evoga.cpp:706
bool debugPrintInfoToFile
Flags whether to print debug information about the xNES algorithm to file.
Definition: evoga.h:819
void saveBestInd()
Append the genome of the best individual of the current population to the BdSd.gen file...
Definition: evoga.cpp:537
The base common class that evaluate the fitness of a robot.
EvaluatorThreadForXnes(Evoga *ga, EvoRobotExperiment *exp)
Constructor.
Definition: evoga.cpp:171
void endGeneration(int generation, double fmax, double faverage, double fmin)
emitted when a generation is ended
double getFitness() const
Returns the fitness of the last run.
Definition: evoga.cpp:114
void printBest()
Print the fitness of the best individuals of the current population.
Definition: evoga.cpp:695
bool variableStdDev
Flags whether the standard deviation to generate offspring is constant or not.
Definition: evoga.h:797
virtual void evolveAllReplicas()
Evolves all replications of the ga process.
Definition: evoga.cpp:3016
static void warning(QString msg)
bool backPropOffspringFitnessIncrease
Flag whether to increase the fitness of the backpropagation offspring.
Definition: evoga.h:809
int loadallg(int gen, const char *filew)
Load the genome of the population from a file.
Definition: evoga.cpp:872
virtual unsigned int getNumReplications()
Returns the number of replications.
Definition: evoga.cpp:3101
bool isStepByStep
if step-by-step modality is enabled or not
Definition: evoga.h:759
int xnesCombinationType
The type of combination between xnes and backpropagation algorithms.
Definition: evoga.h:805
double getNoise(double minn, double maxn)
Unused function (to be removed)
Definition: evoga.cpp:388
int loadStatistics(char *filename)
Load the fitness statistics from a .fit file Return the number of loaded individuals (0 if the file d...
Definition: evoga.cpp:954
void loadallTeams(int gen, const char *filew, QVector< QVector< int > > &teams)
Load the teams of the population from a file.
Definition: evoga.cpp:907
static const float DEFAULT_VALUE
DEFAULT_VALUE is used for do not assign values to mut and parameters.
Definition: evonet.h:137