diff --git a/Easea.h b/Easea.h index bd66acd4e773e7809f90fa93071fd62cd9dfb67d..74591725473668c715daf2869d1742bd0d3ce330 100644 --- a/Easea.h +++ b/Easea.h @@ -22,6 +22,7 @@ Centre de Math #define EO 2 #define DREAM 3 #define CUDA 4 +#define STD 5 #define UNIX 1 #define WINDOWS 2 #define UNKNOWN_OS 3 diff --git a/EaseaLex.l b/EaseaLex.l index 8e854b640d029a19cd426dececf20d71a13e1fc3..21905c5531683b666a8320fd8dc490e6dd171bbe 100644 --- a/EaseaLex.l +++ b/EaseaLex.l @@ -29,6 +29,11 @@ Centre de Math strcat(selectorName,"Tournament(globalRandomGenerator)"); else if( mystricmp("dettour",sSELECTOR)==0 ) strcat(selectorName,"Tournament(globalRandomGenerator)"); + else if( mystricmp("Sequential",sSELECTOR)==0 ) + strcat(selectorName,"Deterministic()"); + else if( mystricmp("Random",sSELECTOR)==0 ) + strcat(selectorName,"Random(globalRandomGenerator)"); + else return NULL; char* ret = (char*)malloc((strlen(selectorName)+1)*sizeof(char)); @@ -51,7 +56,7 @@ Centre de Math %start COPY_EO_INITIALISER %start COPY COPY_INITIALISER COPY_CROSSOVER COPY_MUTATOR COPY_EVALUATOR COPY_FINALIZATION_FUNCTION %start COPY_DISPLAY COPY_USER_FUNCTION COPY_USER_GENERATION PARAMETERS_ANALYSIS GET_PARAMETERS -%start COPY_USER_FUNCTIONS COPY_GENERATION_FUNCTION GET_METHODS +%start COPY_USER_FUNCTIONS COPY_GENERATION_FUNCTION GET_METHODS COPY_MAKEFILE_OPTION // lexical analyser name and class definition %name CEASEALexer { @@ -62,7 +67,7 @@ Centre de Math bool bDoubleQuotes,bWithinDisplayFunction,bWithinInitialiser,bWithinMutator,bWithinXover; bool bWaitingForSemiColon,bFinishNB_GEN,bFinishMINIMISE,bFinishMINIMIZE,bGenerationFunction; bool bCatchNextSemiColon,bWaitingToClosePopulation, bMethodsInGenome, bFinalizationFunction; - bool bWithinCUDA_Initializer; + bool bWithinCUDA_Initializer, bWithinMAKEFILEOPTION; CSymbol *pASymbol; public: @@ -77,7 +82,7 @@ Centre de Math bSymbolInserted=bDoubleQuotes=bWithinDisplayFunction=bWithinInitialiser=bWithinMutator=bWithinXover=0; bWaitingForSemiColon=bFinishNB_GEN=bFinishMINIMISE=bFinishMINIMIZE=bGenerationFunction=0; bCatchNextSemiColon,bWaitingToClosePopulation=bMethodsInGenome=0; - bWithinCUDA_Initializer=0; + bWithinCUDA_Initializer=0, bWithinMAKEFILEOPTION; } // macros @@ -109,6 +114,7 @@ exponent ([Ee][+-]?[0-9]+) strcpy(sFileName, sRAW_PROJECT_NAME); switch (TARGET) { case DREAM : strcat(sFileName,".java"); break; + case STD : case CUDA : strcat(sFileName,".cpp"); break; default : strcat(sFileName,".cpp"); } @@ -337,6 +343,15 @@ exponent ([Ee][+-]?[0-9]+) yyin = fpGenomeFile; // switch to .ez file and analyser BEGIN COPY_DISPLAY; } + + +"\\INSERT_MAKEFILE_OPTION" { + if( bVERBOSE ) printf("Inserting user LDFLAGS.\n"); + yyreset(); + yyin = fpGenomeFile; + BEGIN COPY_MAKEFILE_OPTION; + } + "\\WRITE" { CListItem *pSym; if (!bDisplayFunction){ @@ -402,7 +417,7 @@ exponent ([Ee][+-]?[0-9]+) "\\INSERT_EO_INITIALISER" { yyreset(); bWithinEO_Function=1; - if( TARGET==CUDA ) bWithinCUDA_Initializer = 1; + if( TARGET==CUDA || TARGET==STD) bWithinCUDA_Initializer = 1; yyin = fpGenomeFile; // switch to .ez file and analyser BEGIN COPY_EO_INITIALISER; // not implemented as a function ! } @@ -441,7 +456,12 @@ exponent ([Ee][+-]?[0-9]+) BEGIN PARAMETERS_ANALYSIS; } "\\INSERT_GEN_FCT_CALL" { - if (bGenerationFunction) fprintf(fpOutputFile,"\n EASEAGenerationFunction(ga);\n"); + if (bGenerationFunction) { + if( TARGET==CUDA || TARGET==STD ){ + fprintf(fpOutputFile,"\n\tEASEAGenerationFunction(this);"); + } + else fprintf(fpOutputFile,"\n EASEAGenerationFunction(ga);\n"); + } } "\\INSERT_INIT_FCT_CALL" { if (bInitFunction) fprintf(fpOutputFile,"\n EASEAInitFunction(argc, argv);\n"); @@ -457,11 +477,11 @@ exponent ([Ee][+-]?[0-9]+) } "\\SELECTOR" { - if( TARGET==CUDA ){ + if( TARGET==CUDA || TARGET==STD){ DEBUG_PRT("Selector is \"%s\" | Goal is %s",sSELECTOR,(nMINIMISE?"Minimize":"Maximize")); char* selectorClass = selectorDetermination(nMINIMISE,sSELECTOR); if( !selectorClass ){ - fprintf(stderr,"Error %d : selection operator %s doesn't exist in CUDA template\n",yylineno,sSELECTOR); + fprintf(stderr,"Error %d : selection operator %s doesn't exist in CUDA/STD template\n",yylineno,sSELECTOR); return -1; } DEBUG_PRT("Created class is %s",selectorClass); @@ -475,7 +495,7 @@ exponent ([Ee][+-]?[0-9]+) "\\OFF_SIZE" {fprintf(fpOutputFile,"%d",nOFF_SIZE);} "\\ELITE_SIZE" { fprintf(fpOutputFile,"%d",nELITE); - DEBUG_PRT("elitism is %d, elite size is %d",bELITISM, nELITE); + //DEBUG_PRT("elitism is %d, elite size is %d",bELITISM, nELITE); } "\\RED_PAR" {fprintf(fpOutputFile,"%s",sRED_PAR);} @@ -483,11 +503,11 @@ exponent ([Ee][+-]?[0-9]+) "\\RED_OFF" {fprintf(fpOutputFile,"%s",sRED_OFF);} "\\RED_OFF_PRM" {fprintf(fpOutputFile,"%s",sRED_OFF_PRM);} "\\RED_FINAL" { - if( TARGET==CUDA ){ + if( TARGET==CUDA || TARGET==STD){ DEBUG_PRT("Replacement selector is \"%s\" | Goal is %s",sRED_FINAL,(nMINIMISE?"Minimize":"Maximize")); char* selectorClass = selectorDetermination(nMINIMISE,sRED_FINAL); if( !selectorClass ){ - fprintf(stderr,"Error %d : replacement operator %s doesn't exist in CUDA template\n",yylineno,sRED_FINAL); + fprintf(stderr,"Error %d : replacement operator %s doesn't exist in CUDA/TPL template\n",yylineno,sRED_FINAL); return -1; } DEBUG_PRT("Created class is %s",selectorClass); @@ -524,6 +544,8 @@ exponent ([Ee][+-]?[0-9]+) else fprintf(fpOutputFile," ga.elitist(gaFalse);\n"); break; case EO : fprintf(fpOutputFile,"%d",bELITISM); + break; + case STD: case CUDA: fprintf(fpOutputFile,"%d",bELITISM); } } "\\IMMIG_SEL" {fprintf(fpOutputFile,"%s",sIMMIG_SEL);} @@ -567,7 +589,10 @@ exponent ([Ee][+-]?[0-9]+) char sFileName[1000]; fclose(fpOutputFile); strcpy(sFileName, sRAW_PROJECT_NAME); - strcat(sFileName,"Individual.cu"); + if( TARGET==CUDA ) + strcat(sFileName,"Individual.cu"); + else if( TARGET==STD ) + strcat(sFileName,"Individual.cpp"); fpOutputFile=fopen(sFileName,"w"); if (bVERBOSE) printf("Creating %s...\n",sFileName); } @@ -808,7 +833,7 @@ exponent ([Ee][+-]?[0-9]+) printf ("%s @%s.prm\n\n",sPROJECT_NAME,sPROJECT_NAME); } } printf ("Have a nice compile time.\n"); - if (TARGET==EO || TARGET==CUDA) fprintf(fpOutputFile,"\n# That's all folks ! \n"); + if (TARGET==EO || TARGET==CUDA || TARGET==STD) fprintf(fpOutputFile,"\n# That's all folks ! \n"); else fprintf(fpOutputFile,"\n// That's all folks ! \n"); fflush(fpOutputFile); fclose(fpOutputFile); @@ -890,8 +915,9 @@ exponent ([Ee][+-]?[0-9]+) case EO: fprintf (fpOutputFile,"// Finalization function\n\nvoid EASEAFinalFunction(eoPop& population){"); break; + case STD: case CUDA: - fprintf (fpOutputFile,"// Finalization function\n\nvoid EASEAFinalization(Population* population){"); + fprintf (fpOutputFile,"// Finalization function\nvoid EASEAFinalization(Population* population){"); break; default: fprintf (stderr," Warning this template doesn't support finalization function "); @@ -914,9 +940,14 @@ exponent ([Ee][+-]?[0-9]+) "\\At"[ \t\n]+"each"[ \t\n]+"new"[ \t\n]+"generation"[ \t\n]*":" { + if( TARGET==GALIB){ fprintf (fpOutputFile,"// Function called at each new generation\n\nvoid EASEAGenerationFunction(GAGeneticAlgorithm & g){\n"); fprintf(fpOutputFile," const GAPopulation *pPopulation;\n",sPROJECT_NAME); fprintf(fpOutputFile," pPopulation=&(g.population()); // to circumvent a bug in GALib\n",sPROJECT_NAME); + } + else if(TARGET==CUDA || TARGET==STD){ + fprintf (fpOutputFile,"// Function called at each new generation\nvoid EASEAGenerationFunction(EvolutionaryAlgorithm* evolutionaryAlgorithm){\n"); + } bFunction=1; bGenerationFunction=1; BEGIN COPY_USER_GENERATION; } @@ -989,10 +1020,10 @@ exponent ([Ee][+-]?[0-9]+) } // local random name "random" { if (TARGET==DREAM) fprintf(fpOutputFile,"%s.random",sPROJECT_NAME); - else if( TARGET==CUDA ) fprintf(fpOutputFile,"globalRandomGenerator->random"); + else if( TARGET==CUDA || TARGET==STD) fprintf(fpOutputFile,"globalRandomGenerator->random"); else fprintf(fpOutputFile,"random");} "Genome" { - if (bWithinEO_Function && TARGET!=CUDA) fprintf(fpOutputFile,"_genotype"); + if (bWithinEO_Function && TARGET!=CUDA && TARGET!=STD) fprintf(fpOutputFile,"_genotype"); else if(bWithinEO_Function && bWithinCUDA_Initializer )fprintf(fpOutputFile,"(*this)"); else fprintf(fpOutputFile,"Genome");} // local genome name "identicalGenome" {fprintf(fpOutputFile,"genome._evaluated");} // local name @@ -1005,22 +1036,24 @@ exponent ([Ee][+-]?[0-9]+) "GenomeClass::" {fprintf(fpOutputFile,"template %sGenome::",sPROJECT_NAME);} "GenomeClass" { if (TARGET==EO) fprintf(fpOutputFile,"Indi"); - else if( TARGET==CUDA ) fprintf(fpOutputFile,"Individual"); + else if( TARGET==CUDA || TARGET==STD) fprintf(fpOutputFile,"Individual"); else fprintf(fpOutputFile,"%sGenome",sPROJECT_NAME);} // local name "population" { - if( TARGET == CUDA && bFinalizationFunction ){ + if( (TARGET == CUDA || TARGET==STD) && bFinalizationFunction ){ fprintf(fpOutputFile,"(*population)"); } else fprintf(fpOutputFile,"population"); } "\\end" { - if (bFunction==1) { + if (bFunction==1 && bWithinCUDA_Initializer==0) { fprintf (fpOutputFile,"}\n"); bFunction=0; + bWithinCUDA_Initializer=0; } bWithinEO_Function=0; rewind(fpGenomeFile); - yyin = fpTemplateFile; BEGIN TEMPLATE_ANALYSIS;} // Back to the template file + yyin = fpTemplateFile; + BEGIN TEMPLATE_ANALYSIS;} // Back to the template file .|\n {putc(yytext[0],fpOutputFile);} // Looking for an identifier @@ -1115,13 +1148,54 @@ exponent ([Ee][+-]?[0-9]+) } .|\n {} +"\\User"[ \t\n]+[Mm]"akefile"[ \t\n]+"options"[ \t\n]*":" { + DEBUG_PRT("LDFLAGS is beg: %s",yytext); + bWithinMAKEFILEOPTION=1; + return MAKEFILE_OPTION; + } + + //**************************************** -// Looks for standard and user functions in the .ez file +// Looks for Makefile options (like +// LDFLAGS+= or CPPFLAGS...) //**************************************** +"\\end" { + if( bWithinMAKEFILEOPTION ){ + DEBUG_PRT("end of makefile options"); + yyin = fpTemplateFile; + bWithinMAKEFILEOPTION = 0; + BEGIN TEMPLATE_ANALYSIS; + return END_OF_FUNCTION; + } + } + +.|\n { + if( bWithinMAKEFILEOPTION ){ + putc(yytext[0],fpOutputFile); + } + } + +\n { + if( bWithinMAKEFILEOPTION ); + } + +<> { + DEBUG_PRT("No makefile options defined."); + yyin = fpTemplateFile; + bWithinMAKEFILEOPTION = 0; + BEGIN TEMPLATE_ANALYSIS; + + return MAKEFILE_OPTION; + } + +//**************************************** +// Looks for standard and user functions in the .ez file +//**************************************** "\\GenomeClass::initiali"[sz]"er"[ \t\n]*":" { bWithinInitialiser=1; BEGIN COPY_USER_FUNCTION; + BEGIN TEMPLATE_ANALYSIS; return USER_CTOR; } .|\n {} @@ -1159,17 +1233,28 @@ exponent ([Ee][+-]?[0-9]+) "pPopulation"[ \t\n]*"[" {bWaitingToClosePopulation=true; switch (TARGET) { case EO: fprintf(fpOutputFile,"pPopulation ["); break; - case GALIB: fprintf(fpOutputFile,"((%sGenome *)&(pPopulation->individual(",sPROJECT_NAME); + case GALIB: + fprintf(fpOutputFile,"((%sGenome *)&(pPopulation->individual(",sPROJECT_NAME); + break; + case CUDA: + case STD: + fprintf(fpOutputFile,"(*evolutionaryAlgorithm->getPopulation())"); } } "]" {if (!bWaitingToClosePopulation) fprintf(fpOutputFile,"]"); else {fprintf(fpOutputFile,")))"); bWaitingToClosePopulation=false;}} "currentGeneration" | -"currentGeneration"/[ \t\n]*"==" {if (bDoubleQuotes) fprintf(fpOutputFile,"currentGeneration"); +"currentGeneration"/[ \t\n]*"==" { + if (bDoubleQuotes) fprintf(fpOutputFile,"currentGeneration"); else switch (TARGET) { case GALIB : fprintf(fpOutputFile,"g.generation()"); break; - case EO : fprintf(fpOutputFile,"generationCounter.value()"); + case EO : + fprintf(fpOutputFile,"generationCounter.value()"); break; + case CUDA: + case STD: + fprintf(fpOutputFile,"(evolutionaryAlgorithm->getCurrentGeneration())"); + break; }} // local genome name "NB_GEN" | "NB_GEN"/[ \t\n]*"==" {if (bDoubleQuotes) fprintf(fpOutputFile,"NB_GEN"); @@ -1295,7 +1380,10 @@ exponent ([Ee][+-]?[0-9]+) else fprintf(fpOutputFile,"));"); } else fprintf(fpOutputFile,";");} - +"evoluationaryAlgorithm." | +"ea." { + fprintf(fpOutputFile,"(*evoluationaryAlgorithm)."); + } .|\n {putc(yytext[0],fpOutputFile);} //**************************************** @@ -1315,7 +1403,7 @@ exponent ([Ee][+-]?[0-9]+) if (bWithinDisplayFunction) fprintf(fpOutputFile,"(*this)"); else if ((TARGET==EO)&&(bWithinInitialiser)) fprintf(fpOutputFile, "(*genome)"); - else if ((TARGET==CUDA) && ((bWithinEvaluator) || bWithinMutator)) fprintf(fpOutputFile, "(*this)"); + else if ((TARGET==CUDA || TARGET==STD) && ((bWithinEvaluator) || bWithinMutator)) fprintf(fpOutputFile, "(*this)"); else if ((TARGET==EO)&&(bWithinMutator)) fprintf(fpOutputFile, "_genotype"); else fprintf(fpOutputFile,"genome");} // local genome name @@ -1371,7 +1459,7 @@ exponent ([Ee][+-]?[0-9]+) if (TARGET==DREAM) fprintf(fpOutputFile,"Math.random()<");} // local random name "random" { if (TARGET==DREAM) fprintf(fpOutputFile,"%s.random",sPROJECT_NAME); - else if( TARGET==CUDA ) fprintf(fpOutputFile,"rg->random"); + else if( TARGET==CUDA || TARGET==STD) fprintf(fpOutputFile,"rg->random"); else fprintf(fpOutputFile,"random");} "child1" {if ((bWithinXover)&&(TARGET==GALIB)) fprintf(fpOutputFile, "(*pBro)"); else fprintf(fpOutputFile,"child1"); @@ -1390,7 +1478,7 @@ exponent ([Ee][+-]?[0-9]+) if (TARGET==GALIB) fprintf(fpOutputFile,"EZ_EVAL+=(double)(clock()-EZ_t1);\n return (float)"); else if (TARGET==EO) {fprintf(fpOutputFile,"genome.fitness(");bCatchNextSemiColon=true;}// changes function type// changes function type else if (TARGET==DREAM) {fprintf(fpOutputFile,"infoHabitant.setFitness(new Double(");bCatchNextSemiColon=true;}// changes function type - else if( TARGET==CUDA ) { + else if( TARGET==CUDA || TARGET==STD) { fprintf(fpOutputFile,"return fitness = "); bCatchNextSemiColon=false; } @@ -1548,15 +1636,18 @@ int CEASEALexer::create(CEASEAParser* pParser, CSymbolTable* pSymTable) if (bVERBOSE) printf("\n"); if (TARGET==0) { - printf("\nPlease select a target library (DREAM, EO, GALib or CUDA): "); - scanf("%s",sTemp); - if (!mystricmp(sTemp,"eo")) TARGET=EO; - else if (!mystricmp(sTemp,"galib")) TARGET=GALIB; - else if (!mystricmp(sTemp,"dream")) TARGET=DREAM; - else if (!mystricmp(sTemp,"cuda")) TARGET=CUDA; - else return 0; +/* printf("\nPlease select a target library (DREAM, EO, GALib STD or CUDA): "); */ +/* scanf("%s",sTemp); */ +/* if (!mystricmp(sTemp,"eo")) TARGET=EO; */ +/* else if (!mystricmp(sTemp,"galib")) TARGET=GALIB; */ +/* else if (!mystricmp(sTemp,"dream")) TARGET=DREAM; */ +/* else if (!mystricmp(sTemp,"cuda")) TARGET=CUDA; */ +/* else if (!mystricmp(sTemp,"std")) TARGET=STD; */ +/* else return 0; */ + TARGET = STD; } - + + char* sEZ_PATH = "./tpl/"; ///////////////////////////////////////////////////////// //strcpy(sTemp,"e:\\lutton\\easea\\debug");pour tester sous windows if ((sEZ_PATH==NULL)||(sEZ_PATH[0]==0)) { @@ -1564,14 +1655,14 @@ int CEASEALexer::create(CEASEAParser* pParser, CSymbolTable* pSymTable) printf("\n\nHmmm, it looks like you are running EASEA without GUIDE for the first time.\n"); printf("Please, add the path of the installation directory to the PATH variable and\n"); printf("into the \"EZ_PATH\" environment variable, so that EASEA knows where to look for\n"); - printf("its template files.\n"); + printf("its template files.\n"); exit(1); } strcpy(sEZ_PATH,getenv("EZ_PATH")); } switch (OPERATING_SYSTEM) { - case UNIX : if (sEZ_PATH[strlen(sEZ_PATH)-1] != '/') strcat (sEZ_PATH,"/"); break; + case UNIX : if (sEZ_PATH[strlen(sEZ_PATH)-1] != '/') strcat (sEZ_PATH,"./"); break; case WINDOWS : if (sEZ_PATH[strlen(sEZ_PATH)-1] != '\\') strcat (sEZ_PATH,"\\"); break; case UNKNOWN_OS : fprintf(fpOutputFile,"UNKNOWN_OS"); break; } @@ -1606,6 +1697,13 @@ int CEASEALexer::create(CEASEAParser* pParser, CSymbolTable* pSymTable) exit(1); } } + if (TARGET==STD){ + strcat(sTemp,"STD.tpl"); + if (!(yyin = fpTemplateFile = fopen(sTemp, "r"))){ + fprintf(stderr,"\n*** Could not open %s.\n",sTemp); + fprintf(stderr,"*** Please modify the EZ_PATH environment variable.\n"); + exit(1); + } } if (TARGET==EO){ if ((sEO_DIR==NULL)||(sEO_DIR[0]==0)) { diff --git a/EaseaParse.y b/EaseaParse.y index 243a17c9f4c2f39f23181a4f8a5169883ff40c3b..2efee4075f8cab37b5b0e80e1ce5b8150576dd23 100644 --- a/EaseaParse.y +++ b/EaseaParse.y @@ -92,6 +92,7 @@ class CSymbol; %token USER_XOVER %token USER_MUTATOR %token USER_EVALUATOR +%token MAKEFILE_OPTION %token END_OF_FUNCTION //%token DELETE %token END_METHODS @@ -467,7 +468,7 @@ StandardFunctionAnalysis } } END_OF_FUNCTION { if (TARGET==DREAM) fprintf(fpOutputFile," }\n"); - if( TARGET!=CUDA ) fprintf(fpOutputFile,"}"); + if( TARGET!=CUDA && TARGET!=STD) fprintf(fpOutputFile,"}"); } | USER_EVALUATOR { if (bVERBOSE) printf("Inserting user genome evaluator (taken from .ez file).\n"); @@ -485,8 +486,12 @@ StandardFunctionAnalysis fprintf(fpOutputFile," EZ_NB_EVALUATIONS++;\n",sPROJECT_NAME); } } END_OF_FUNCTION { - if (TARGET!=EO && TARGET!=CUDA ) fprintf(fpOutputFile,"}\n"); + if (TARGET!=EO && TARGET!=CUDA && TARGET!=STD) fprintf(fpOutputFile,"}\n"); } + | MAKEFILE_OPTION END_OF_FUNCTION { + DEBUG_PRT("User makefile options have been reduced"); + } + | MAKEFILE_OPTION {} ; RunParameters @@ -547,18 +552,28 @@ Parameter exit(1); } break; - case EO : if (!mystricmp(sSELECTOR,"RouletteWheel")){ - if (nMINIMISE==1) { - fprintf(stderr,"\n%s - Error line %d: The RouletteWheel selection scheme cannot be\n selected when \"minimising the fitness\" is the evaluator goal.\n",sEZ_FILE_NAME,EASEALexer.yylineno); - exit(1); - } - else sprintf(sSELECTOR,"Roulette"); - } - else if (!mystricmp(sSELECTOR,"Tournament")) sprintf(sSELECTOR,"DetTour"); - else if (!mystricmp(sSELECTOR,"StochTrn")) sprintf(sSELECTOR,"StochTour"); - else if (!mystricmp(sSELECTOR,"Random")) sprintf(sSELECTOR,"Random"); - else if (!mystricmp(sSELECTOR,"Ranking")) sprintf(sSELECTOR,"Ranking"); - else if (!mystricmp(sSELECTOR,"Sequential")) sprintf(sSELECTOR,"Sequential"); + case CUDA: + case STD: + case EO : if (!mystricmp(sSELECTOR,"RouletteWheel")){ + if (nMINIMISE==1) { + fprintf(stderr,"\n%s - Error line %d: The RouletteWheel selection scheme cannot be\n selected when \"minimising the fitness\" is the evaluator goal.\n",sEZ_FILE_NAME,EASEALexer.yylineno); + exit(1); + } + else sprintf(sSELECTOR,"Roulette"); + } + else if (!mystricmp(sSELECTOR,"Tournament")) sprintf(sSELECTOR,"DetTour"); + else if (!mystricmp(sSELECTOR,"StochTrn")) sprintf(sSELECTOR,"StochTour"); + else if (!mystricmp(sSELECTOR,"Random")){ + sprintf(sSELECTOR,"Random"); + if( TARGET==CUDA || TARGET==STD ) + sprintf(sSELECT_PRM,"(0)"); + } + else if (!mystricmp(sSELECTOR,"Ranking")) sprintf(sSELECTOR,"Ranking"); + else if (!mystricmp(sSELECTOR,"Sequential")){ + sprintf(sSELECTOR,"Sequential"); + if( TARGET==CUDA || TARGET==STD) sprintf(sSELECT_PRM,"(0)"); + + } else { fprintf(stderr,"\n%s - Error line %d: The %s selection scheme does not exist in EO.\n",sEZ_FILE_NAME,EASEALexer.yylineno, sSELECTOR); exit(1); @@ -606,6 +621,7 @@ Parameter } break; case CUDA: + case STD: case EO : if (!mystricmp(sSELECTOR,"Tournament")||!mystricmp(sSELECTOR,"StochTrn")) { if ($3>=2) {sprintf(sSELECTOR,"DetTour");sprintf(sSELECT_PRM,"(%d)",(int) $3);} else if (($3>.5)&&($3<=1.0)) {sprintf(sSELECTOR,"StochTour");sprintf(sSELECT_PRM,"(%f)",(float) $3);} @@ -630,7 +646,12 @@ Parameter } else if (!mystricmp(sSELECTOR,"Sequential")) { sprintf(sSELECTOR,"Sequential"); - if ($3==0) sprintf(sSELECT_PRM,"(unordered)"); + if ($3==0) + if( TARGET==CUDA || TARGET==STD ) + sprintf(sSELECT_PRM,"(0)"); + else + sprintf(sSELECT_PRM,"(unordered)"); + else if ($3==1) sprintf(sSELECT_PRM,"(ordered)"); else { fprintf(stderr,"\n%s - Warning line %d: The parameter of Sequential must be either 0 (unordered) or 1 (ordered).\nThe parameter will default to 1.",sEZ_FILE_NAME,EASEALexer.yylineno);nWARNINGS++; @@ -708,6 +729,7 @@ Parameter } break; case CUDA : + case STD: case EO : if (!mystricmp(sRED_PAR,"Tournament")||!mystricmp(sRED_PAR,"StochTrn")) { if ($3>=2) {sprintf(sRED_PAR,"DetTour");sprintf(sRED_PAR_PRM,"(%d)",(int) $3);} else if (($3>.5)&&($3<=1.0)) {sprintf(sRED_PAR,"StochTour");sprintf(sRED_PAR_PRM,"(%f)",(float) $3);} @@ -732,8 +754,13 @@ Parameter } else if (!mystricmp(sRED_PAR,"Sequential")) { sprintf(sRED_PAR,"Sequential"); - if ($3==0) sprintf(sRED_PAR_PRM,"(unordered)"); - else if ($3==1) sprintf(sRED_PAR_PRM,"(ordered)"); + + if ($3==0) + if( TARGET==CUDA || TARGET==STD ) + sprintf(sSELECT_PRM,"(0)"); + else + sprintf(sSELECT_PRM,"(unordered)"); + else if ($3==1) sprintf(sRED_PAR_PRM,"(ordered)"); else { fprintf(stderr,"\n%s - Warning line %d: The parameter of Sequential must be either 0 (unordered) or 1 (ordered).\nThe parameter will default to 1.",sEZ_FILE_NAME,EASEALexer.yylineno);nWARNINGS++; sprintf(sRED_PAR_PRM,"(ordered)"); @@ -831,7 +858,11 @@ Parameter } else if (!mystricmp(sRED_OFF,"Sequential")) { sprintf(sRED_OFF,"Sequential"); - if ($3==0) sprintf(sRED_OFF_PRM,"(unordered)"); + + if ($3==0) if( TARGET==CUDA || TARGET==STD ) + sprintf(sSELECT_PRM,"(0)"); + else + sprintf(sRED_OFF_PRM,"(unordered)"); else if ($3==1) sprintf(sRED_OFF_PRM,"(ordered)"); else { fprintf(stderr,"\n%s - Warning line %d: The parameter of Sequential must be either 0 (unordered) or 1 (ordered).\nThe parameter will default to 1.",sEZ_FILE_NAME,EASEALexer.yylineno);nWARNINGS++; @@ -864,6 +895,8 @@ Parameter exit(1); } break; + case CUDA: + case STD: case EO : if (!mystricmp(sRED_FINAL,"RouletteWheel")){ if (nMINIMISE==1) { fprintf(stderr,"\n%s - Error line %d: The RouletteWheel selection scheme cannot be\n selected when \"minimising the fitness\" is the evaluator goal.\n",sEZ_FILE_NAME,EASEALexer.yylineno); @@ -873,9 +906,16 @@ Parameter } else if (!mystricmp(sRED_FINAL,"Tournament")) sprintf(sRED_FINAL,"DetTour"); else if (!mystricmp(sRED_FINAL,"StochTrn")) sprintf(sRED_FINAL,"StochTour"); - else if (!mystricmp(sRED_FINAL,"Random")) sprintf(sRED_FINAL,"Random"); + else if (!mystricmp(sRED_FINAL,"Random")){ + sprintf(sRED_FINAL,"Random"); + if( TARGET==CUDA || TARGET==STD ) + sprintf(sRED_FINAL_PRM,"(0)"); + } else if (!mystricmp(sRED_FINAL,"Ranking")) sprintf(sRED_FINAL,"Ranking"); - else if (!mystricmp(sRED_FINAL,"Sequential")) sprintf(sRED_FINAL,"Sequential"); + else if (!mystricmp(sRED_FINAL,"Sequential")) { + sprintf(sRED_FINAL,"Sequential"); + sprintf(sRED_FINAL_PRM,"(2)"); + } else { fprintf(stderr,"\n%s - Error line %d: The %s selection scheme does not exist in EO.\n",sEZ_FILE_NAME,EASEALexer.yylineno, sRED_FINAL); exit(1); @@ -907,6 +947,7 @@ Parameter } break; case CUDA : + case STD: case EO : if (!mystricmp(sRED_FINAL,"Tournament")||!mystricmp(sRED_FINAL,"StochTrn")) { if ($3>=2) { @@ -935,7 +976,11 @@ Parameter } else if (!mystricmp(sRED_FINAL,"Sequential")) { sprintf(sRED_FINAL,"Sequential"); - if ($3==0) sprintf(sRED_FINAL_PRM,"(unordered)"); + if ($3==0) + if( TARGET==CUDA || TARGET==STD ) + sprintf(sRED_FINAL_PRM,"(0)"); + else + sprintf(sRED_FINAL_PRM,"(unordered)"); else if ($3==1) sprintf(sRED_FINAL_PRM,"(ordered)"); else { fprintf(stderr,"\n%s - Warning line %d: The parameter of Sequential must be either 0 (unordered) or 1 (ordered).\nThe parameter will default to 1.",sEZ_FILE_NAME,EASEALexer.yylineno);nWARNINGS++; @@ -1276,6 +1321,7 @@ int main(int argc, char *argv[]){ else if (!mystricmp(sTemp,"galib")) TARGET=GALIB; else if (!mystricmp(sTemp,"dream")) TARGET=DREAM; else if (!mystricmp(sTemp,"cuda")) TARGET=CUDA; + else if (!mystricmp(sTemp,"std")) TARGET=STD; else if (!mystricmp(sTemp,"v")) bVERBOSE=true; else if (!mystricmp(sTemp,"path")) { if (argv[++nParamNb][0]=='"') { diff --git a/EaseaSym.cpp b/EaseaSym.cpp index f7ac3a7da69c914541eb625426f60748f84c9544..ce9eca3be60899e18d6d3a93c0d5b00daeb5d69d 100644 --- a/EaseaSym.cpp +++ b/EaseaSym.cpp @@ -154,7 +154,7 @@ void CSymbol::print(FILE *fp){ fprintf(fp," if ((%s)&&(%s!=EASEA_Var.%s)) return gaFalse;\n",pSym->Object->sName,pSym->Object->sName,pSym->Object->sName, pSym->Object->pType->sName,pSym->Object->sName,pSym->Object->sName); } } - if (TARGET==EO || TARGET==CUDA){ + if (TARGET==EO || TARGET==CUDA || TARGET==STD){ if (pSym->Object->ObjectType==oObject) fprintf(fp," if (%s!=EASEA_Var.%s) return false;\n",pSym->Object->sName,pSym->Object->sName); if (pSym->Object->ObjectType==oArray){ @@ -168,7 +168,7 @@ void CSymbol::print(FILE *fp){ } } if (TARGET==GALIB) fprintf(fp," return gaTrue;\n }\n\n"); // operator== - if (TARGET==EO || TARGET==CUDA) fprintf(fp," return true;\n }\n\n"); // operator== + if (TARGET==EO || TARGET==CUDA || TARGET==STD) fprintf(fp," return true;\n }\n\n"); // operator== fprintf(fp," bool operator!=(%s &EASEA_Var) const {return !(*this==EASEA_Var);} // operator!=\n\n",sName); // operator!= @@ -329,7 +329,7 @@ void CSymbol::printClasses(FILE *fp){ void CSymbol::printUC(FILE* fp){ DEBUG_PRT("print user classes definitions"); - if (strcmp(sName,"Genome")&&(TARGET==CUDA)){ // If we are printing a user class other than the genome + if (strcmp(sName,"Genome") && (TARGET==CUDA || TARGET==STD)){ // If we are printing a user class other than the genome fprintf(fp,"\nclass %s;\n",sName); // class header } DEBUG_PRT("%s",sName); diff --git a/makefile b/makefile index 0fa0f803d90601a0eb0db58f0b1efeda6daa1f8f..33c386214f65733f6d228ac7239110003e7b2b8d 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,5 @@ EXEC = main.out -CPPFLAGS = -DUNIX_OS -Ialexyacc/include/ -DDEBUG -g +CPPFLAGS += -DUNIX_OS -Ialexyacc/include/ -g CPPC = g++ LDFLAGS = @@ -20,39 +20,14 @@ alexyacc/libalex.so:alexyacc/*.cpp clean: rm -f *.o $(EXEC) - rm -f EaseaParse.cpp EaseaParse.h EaseaLex.cpp EaseaLex.h cd alexyacc && make clean +realclean: clean + rm -f EaseaParse.cpp EaseaParse.h EaseaLex.cpp EaseaLex.h EaseaParse.cpp: EaseaParse.y wine ~/.wine/drive_c/Program\ Files/Parser\ Generator/BIN/ayacc.exe $< -Tcpp -d EaseaLex.cpp: EaseaLex.l - wine ~/.wine/drive_c/Program\ Files/Parser\ Generator/BIN/ALex.exe $< -Tcpp -i - - -# #handle file between windows and local directory -# winclean: -# rm -f $(TMP_DIR)/EaseaLex.cpp $(TMP_DIR)/EaseaLex.h $(TMP_DIR)/EaseaParse.cpp $(TMP_DIR)/EaseaParse.h $(TMP_DIR)/EaseaParse.v - -# winrealclean: winclean -# rm -f $(TMP_DIR)/EaseaParse.y $(TMP_DIR)/EaseaLex.l - -# #send alex and ayacc files to windows -# winsend: winsend_l winsend_y -# winsend_l: -# sudo cp EaseaLex.l $(TMP_DIR)/ -# winsend_y: -# sudo cp EaseaParse.y $(TMP_DIR)/ - -# #receveive alex and ayacc files from windows -# winreceive: winreceive_l winreceive_y - -# winreceive_l: -# cp $(TMP_DIR)/EaseaLex.cpp $(TMP_DIR)/EaseaLex.h ./ -# chmod -x EaseaLex.cpp EaseaLex.h - -# winreceive_y: -# cp $(TMP_DIR)/EaseaParse.cpp $(TMP_DIR)/EaseaParse.h ./ -# chmod -x EaseaParse.cpp EaseaParse.h \ No newline at end of file + wine ~/.wine/drive_c/Program\ Files/Parser\ Generator/BIN/ALex.exe $< -Tcpp -i \ No newline at end of file diff --git a/tpl/EO.tpl b/tpl/EO.tpl index 17a71451a1ddccda9f2c6c2dd864195e38ffdd32..e4960f6ae114ff4c95f2c0ae6618bfb2f6cabb47 100755 --- a/tpl/EO.tpl +++ b/tpl/EO.tpl @@ -50,7 +50,6 @@ inline float random(float b1=0, float b2=1){ \ANALYSE_PARAMETERS \INSERT_USER_DECLARATIONS -\INSERT_INITIALISATION_FUNCTION // include here whatever specific files for your representation @@ -74,6 +73,7 @@ typedef \MINIMAXI MyFitT ; // type of fitness typedef EASEAGenome Indi; // ***MUST*** derive from EO \INSERT_USER_FUNCTIONS +\INSERT_INITIALISATION_FUNCTION /** definition of evaluation: * class EASEAEvalFunc MUST derive from eoEvalFunc diff --git a/tpl/STD.tpl b/tpl/STD.tpl new file mode 100644 index 0000000000000000000000000000000000000000..744969f9d26df9ef4a8e3589793dbcf5d1cfd90a --- /dev/null +++ b/tpl/STD.tpl @@ -0,0 +1,1204 @@ +\TEMPLATE_START/** + This is program entry for CUDA template for EASEA + +*/ +\ANALYSE_PARAMETERS +using namespace std; +#include +#include "EASEATools.hpp" +#include "EASEAIndividual.hpp" + +RandomGenerator* globalRandomGenerator; + + +int main(int argc, char** argv){ + + size_t parentPopulationSize = \POP_SIZE; + size_t offspringPopulationSize = \OFF_SIZE; + float pCrossover = \XOVER_PROB; + float pMutation = \MUT_PROB; + float pMutationPerGene = 0.05; + + globalRandomGenerator = new RandomGenerator(0); + + SelectionOperator* selectionOperator = new \SELECTOR; + SelectionOperator* replacementOperator = new \RED_FINAL; + float selectionPressure = \SELECT_PRM; + float replacementPressure = \RED_FINAL_PRM; + + + \INSERT_INIT_FCT_CALL + + EvolutionaryAlgorithm ea(parentPopulationSize,offspringPopulationSize,selectionPressure,replacementPressure, + selectionOperator,replacementOperator,pCrossover, pMutation, pMutationPerGene); + + StoppingCriterion* sc = new GenerationalCriterion(&ea,\NB_GEN); + ea.addStoppingCriterion(sc); + Population* pop = ea.getPopulation(); + + //pop->initializeParentPopulation(); + //pop->evaluateParentPopulation(); + + //cout << *pop; + + ea.runEvolutionaryLoop(); + + EASEAFinal(pop); + + delete pop; + delete sc; + + return 0; +} + + +\START_CUDA_GENOME_CU_TPL +#include "EASEAIndividual.hpp" +#include "EASEAUserClasses.hpp" +#include + +extern RandomGenerator* globalRandomGenerator; + +\INSERT_USER_DECLARATIONS +\ANALYSE_USER_CLASSES + +\INSERT_USER_FUNCTIONS + +\INSERT_INITIALISATION_FUNCTION +\INSERT_FINALIZATION_FUNCTION +\INSERT_GENERATION_FUNCTION + +void EASEAFinal(Population* pop){ + \INSERT_FINALIZATION_FCT_CALL +} + +using namespace std; + +RandomGenerator* Individual::rg; + +Individual::Individual(){ + \GENOME_CTOR + \INSERT_EO_INITIALISER + valid = false; +} + + +Individual::~Individual(){ + \GENOME_DTOR +} + + +float Individual::evaluate(){ + if(valid) + return fitness; + else{ + valid = true; + \INSERT_EVALUATOR + } +} + +Individual::Individual(const Individual& genome){ + + // ******************** + // Problem specific part + \COPY_CTOR + + // ******************** + // Generic part + this->valid = genome.valid; + this->fitness = genome.fitness; +} + + +Individual* Individual::crossover(Individual** ps){ + // ******************** + // Generic part + Individual parent1(*this); + Individual parent2(*ps[0]); + Individual child1(*this); + + DEBUG_PRT("Xover"); +/* cout << "p1 : " << parent1 << endl; */ +/* cout << "p2 : " << parent2 << endl; */ + + // ******************** + // Problem specific part + \INSERT_CROSSOVER + + child1.valid = false; +/* cout << "child1 : " << child1 << endl; */ + return new Individual(child1); +} + + +void Individual::printOn(std::ostream& os) const{ + \INSERT_DISPLAY +} + +std::ostream& operator << (std::ostream& O, const Individual& B) +{ + // ******************** + // Problem specific part + O << "\nIndividual : "<< std::endl; + O << "\t\t\t"; + B.printOn(O); + + if( B.valid ) O << "\t\t\tfitness : " << B.fitness; + else O << "fitness is not yet computed" << std::endl; + return O; +} + + +size_t Individual::mutate( float pMutationPerGene ){ + this->valid=false; + + + // ******************** + // Problem specific part + \INSERT_MUTATOR +} + +/* **************************************** + EvolutionaryAlgorithm class +****************************************/ + +/** + @DEPRECATED This contructor will be deleted. It was for test only, because it + is too much constrained (default selection/replacement operator) + */ +EvolutionaryAlgorithm::EvolutionaryAlgorithm( size_t parentPopulationSize, + size_t offspringPopulationSize, + float selectionPressure, float replacementPressure, + float pCrossover, float pMutation, + float pMutationPerGene){ + RandomGenerator* rg = globalRandomGenerator; + + + SelectionOperator* so = new MaxTournament(rg); + SelectionOperator* ro = new MaxTournament(rg); + + Individual::initRandomGenerator(rg); + Population::initPopulation(so,ro,selectionPressure,replacementPressure); + + this->population = new Population(parentPopulationSize,offspringPopulationSize, + pCrossover,pMutation,pMutationPerGene,rg); + + this->currentGeneration = 0; + + this->reduceParents = 0; + this->reduceOffsprings = 0; + + +} + +EvolutionaryAlgorithm::EvolutionaryAlgorithm( size_t parentPopulationSize, + size_t offspringPopulationSize, + float selectionPressure, float replacementPressure, + SelectionOperator* selectionOperator, SelectionOperator* replacementOperator, + float pCrossover, float pMutation, + float pMutationPerGene){ + + RandomGenerator* rg = globalRandomGenerator; + + SelectionOperator* so = selectionOperator; + SelectionOperator* ro = replacementOperator; + + Individual::initRandomGenerator(rg); + Population::initPopulation(so,ro,selectionPressure,replacementPressure); + + this->population = new Population(parentPopulationSize,offspringPopulationSize, + pCrossover,pMutation,pMutationPerGene,rg); + + this->currentGeneration = 0; + + this->reduceParents = 0; + this->reduceOffsprings = 0; + + +} + +void EvolutionaryAlgorithm::addStoppingCriterion(StoppingCriterion* sc){ + this->stoppingCriteria.push_back(sc); +} + +void EvolutionaryAlgorithm::runEvolutionaryLoop(){ + + std::cout << "Parent's population initializing "<< std::endl; + this->population->initializeParentPopulation(); + std::cout << *population << std::endl; + + while( this->allCriteria() == false ){ + + + population->produceOffspringPopulation(); + population->evaluateOffspringPopulation(); + + if(reduceParents) + population->reduceParentPopulation(reduceParents); + + if(reduceOffsprings) + population->reduceOffspringPopulation(reduceOffsprings); + + population->reduceTotalPopulation(); + + currentGeneration += 1; + + \INSERT_GEN_FCT_CALL + + } + population->sortParentPopulation(); + std::cout << *population << std::endl; + std::cout << "Generation : " << currentGeneration << std::endl; +} + + +bool EvolutionaryAlgorithm::allCriteria(){ + + for( size_t i=0 ; ireached() ){ + std::cout << "Stopping criterion reached : " << i << std::endl; + return true; + } + } + return false; +} + + + +\START_CUDA_USER_CLASSES_H_TPL +#include +#include +#include +using namespace std; +\INSERT_USER_CLASSES + +\START_CUDA_GENOME_H_TPL +#ifndef __INDIVIDUAL +#define __INDIVIDUAL +#include "EASEATools.hpp" +#include + +\INSERT_USER_CLASSES_DEFINITIONS + +void EASEAInitFunction(int argc, char *argv[]); +void EASEAFinal(Population* population); +void EASEAFinalization(Population* population); + +class Individual{ + + public: // in AESAE the genome is public (for user functions,...) + \INSERT_GENOME + bool valid; + float fitness; + static RandomGenerator* rg; + + public: + Individual(); + Individual(const Individual& indiv); + virtual ~Individual(); + float evaluate(); + static size_t getCrossoverArrity(){ return 2; } + float getFitness(){ return this->fitness; } + Individual* crossover(Individual** p2); + void printOn(std::ostream& O) const; + + size_t mutate(float pMutationPerGene); + + + friend std::ostream& operator << (std::ostream& O, const Individual& B) ; + static void initRandomGenerator(RandomGenerator* rg){ Individual::rg = rg;} + + +}; + + +/* **************************************** + EvolutionaryAlgorithm class +****************************************/ +class EvolutionaryAlgorithm{ +public: + EvolutionaryAlgorithm( size_t parentPopulationSize, size_t offspringPopulationSize, + float selectionPressure, float replacementPressure, + float pCrossover, float pMutation, float pMutationPerGene); + EvolutionaryAlgorithm( size_t parentPopulationSize,size_t offspringPopulationSize, + float selectionPressure, float replacementPressure, + SelectionOperator* selectionOperator, SelectionOperator* replacementOperator, + float pCrossover, float pMutation, + float pMutationPerGene); + + size_t* getCurrentGenerationPtr(){ return ¤tGeneration;} + + + void addStoppingCriterion(StoppingCriterion* sc); + void runEvolutionaryLoop(); + bool allCriteria(); + Population* getPopulation(){ return population;} + size_t getCurrentGeneration() { return currentGeneration;} +private: + size_t currentGeneration; + Population* population; + size_t reduceParents; + size_t reduceOffsprings; + std::vector stoppingCriteria; +}; + + +#endif + + +\START_CUDA_TOOLS_CPP_TPL/* **************************************** + + RandomGenerator class + +****************************************/ +#include "EASEATools.hpp" +#include "EASEAIndividual.hpp" +#include +#include +#include +#include + +RandomGenerator::RandomGenerator(unsigned int seed){ + srand(seed); +} + +int RandomGenerator::randInt(){ + return rand(); +} + +bool RandomGenerator::tossCoin(){ + + int rVal = rand(); + if( rVal >=(RAND_MAX/2)) + return true; + else return false; +} + + +bool RandomGenerator::tossCoin(float bias){ + + int rVal = rand(); + if( rVal <=(RAND_MAX*bias) ) + return true; + else return false; +} + + + +int RandomGenerator::randInt(int min, int max){ + + int rValue = (((float)rand()/RAND_MAX))*(max-min); + DEBUG_PRT("Int Random Value : %d",min+rValue); + return rValue+min; + +} + +int RandomGenerator::random(int min, int max){ + return randInt(min,max); +} + +float RandomGenerator::randFloat(float min, float max){ + float rValue = (((float)rand()/RAND_MAX))*(max-min); + DEBUG_PRT("Float Random Value : %f",min+rValue); + return rValue+min; +} + +float RandomGenerator::random(float min, float max){ + return randFloat(min,max); +} + +double RandomGenerator::random(double min, double max){ + return randFloat(min,max); +} + + +int RandomGenerator::getRandomIntMax(int max){ + double r = rand(); + r = r / RAND_MAX; + r = r * max; + return r; +} + + +/* **************************************** + Tournament class (min and max) +****************************************/ +void MaxTournament::initialize(Individual** population, float selectionPressure, size_t populationSize) { + SelectionOperator::initialize(population,selectionPressure,populationSize); +} + + +float MaxTournament::getExtremum(){ + return -FLT_MAX; +} + +size_t MaxTournament::selectNext(size_t populationSize){ + size_t bestIndex = 0; + float bestFitness = -FLT_MAX; + + //std::cout << "MaxTournament selection " ; + if( currentSelectionPressure >= 2 ){ + for( size_t i = 0 ; igetRandomIntMax(populationSize); + //std::cout << selectedIndex << " "; + float currentFitness = population[selectedIndex]->getFitness(); + + if( bestFitness < currentFitness ){ + bestIndex = selectedIndex; + bestFitness = currentFitness; + } + + } + } + else if( currentSelectionPressure <= 1 && currentSelectionPressure > 0 ){ + size_t i1 = rg->getRandomIntMax(populationSize); + size_t i2 = rg->getRandomIntMax(populationSize); + + if( rg->tossCoin(currentSelectionPressure) ){ + if( population[i1]->getFitness() > population[i2]->getFitness() ){ + bestIndex = i1; + } + } + else{ + if( population[i1]->getFitness() > population[i2]->getFitness() ){ + bestIndex = i2; + } + } + } + else{ + std::cerr << " MaxTournament selection operator doesn't handle selection pressure : " + << currentSelectionPressure << std::endl; + } + //std::cout << std::endl; + return bestIndex; +} + + +void MinTournament::initialize(Individual** population, float selectionPressure, size_t populationSize) { + SelectionOperator::initialize(population,selectionPressure,populationSize); +} + +float MinTournament::getExtremum(){ + return FLT_MAX; +} + + +size_t MinTournament::selectNext(size_t populationSize){ + size_t bestIndex = 0; + float bestFitness = FLT_MAX; + + //std::cout << "MinTournament selection " ; + if( currentSelectionPressure >= 2 ){ + for( size_t i = 0 ; igetRandomIntMax(populationSize); + //std::cout << selectedIndex << " "; + float currentFitness = population[selectedIndex]->getFitness(); + + if( bestFitness > currentFitness ){ + bestIndex = selectedIndex; + bestFitness = currentFitness; + } + + } + } + else if( currentSelectionPressure <= 1 && currentSelectionPressure > 0 ){ + size_t i1 = rg->getRandomIntMax(populationSize); + size_t i2 = rg->getRandomIntMax(populationSize); + + if( rg->tossCoin(currentSelectionPressure) ){ + if( population[i1]->getFitness() < population[i2]->getFitness() ){ + bestIndex = i1; + } + } + else{ + if( population[i1]->getFitness() < population[i2]->getFitness() ){ + bestIndex = i2; + } + } + } + else{ + std::cerr << " MinTournament selection operator doesn't handle selection pressure : " + << currentSelectionPressure << std::endl; + } + + //std::cout << std::endl; + return bestIndex; +} + + +/* **************************************** + SelectionOperator class +****************************************/ +void SelectionOperator::initialize(Individual** population, float selectionPressure, size_t populationSize){ + this->population = population; + this->currentSelectionPressure = selectionPressure; +} + +size_t SelectionOperator::selectNext(size_t populationSize){ return 0; } + + +/* **************************************** + GenerationalCriterion class +****************************************/ +GenerationalCriterion::GenerationalCriterion(EvolutionaryAlgorithm* ea, size_t generationalLimit){ + this->currentGenerationPtr = ea->getCurrentGenerationPtr(); + this->generationalLimit = generationalLimit; +} + +bool GenerationalCriterion::reached(){ + if( generationalLimit <= *currentGenerationPtr ){ + std::cout << "Current generation " << *currentGenerationPtr << " Generational limit : " << + generationalLimit << std::endl; + return true; + } + else return false; +} + + +/* **************************************** + Population class +****************************************/ +SelectionOperator* Population::selectionOperator; +SelectionOperator* Population::replacementOperator; + +float Population::selectionPressure; +float Population::replacementPressure; + + + +Population::Population(size_t parentPopulationSize, size_t offspringPopulationSize, + float pCrossover, float pMutation, float pMutationPerGene, + RandomGenerator* rg){ + + this->parents = new Individual*[parentPopulationSize]; + this->offsprings = new Individual*[offspringPopulationSize]; + + this->parentPopulationSize = parentPopulationSize; + this->offspringPopulationSize = offspringPopulationSize; + + this->actualParentPopulationSize = 0; + this->actualOffspringPopulationSize = 0; + + this->pCrossover = pCrossover; + this->pMutation = pMutation; + this->pMutationPerGene = pMutationPerGene; + + this->rg = rg; + + +} + +Population::~Population(){ + for( size_t i=0 ; iparents); + delete[](this->offsprings); +} + +void Population::initPopulation(SelectionOperator* selectionOperator, + SelectionOperator* replacementOperator, + float selectionPressure, float replacementPressure){ + Population::selectionOperator = selectionOperator; + Population::replacementOperator = replacementOperator; + Population::selectionPressure = selectionPressure; + Population::replacementPressure = replacementPressure; +} + + +void Population::initializeParentPopulation(){ + + for( size_t i=0 ; ievaluate(); +} + + +void Population::evaluateParentPopulation(){ + evaluatePopulation(parents,parentPopulationSize); +} + + +void Population::evaluateOffspringPopulation(){ + evaluatePopulation(offsprings,offspringPopulationSize); +} + + +/** + Reduit la population population de taille populationSize + a une population reducedPopulation de taille obSize. + reducedPopulation doit etre alloue a obSize. + + Ici on pourrait avoir le best fitness de la prochaine population de parents. + + + */ +Individual** Population::reducePopulation(Individual** population, size_t populationSize, + Individual** reducedPopulation, size_t obSize, + SelectionOperator* replacementOperator){ + + + replacementOperator->initialize(population,replacementPressure,populationSize); + + for( size_t i=0 ; iselectNext(populationSize - i); + // std::cout << "Selected " << selectedIndex << "/" << populationSize + // << " replaced by : " << populationSize-(i+1)<< std::endl; + reducedPopulation[i] = population[selectedIndex]; + + // erase it to the std population by swapping last individual end current + population[selectedIndex] = population[populationSize-(i+1)]; + //population[populationSize-(i+1)] = NULL; + } + + //return reducedPopulation; +} + + +Individual** Population::reduceParentPopulation(size_t obSize){ + Individual** nextGeneration = new Individual*[obSize]; + + reducePopulation(parents,actualParentPopulationSize,nextGeneration,obSize, + Population::replacementOperator); + + // free no longer needed individuals + for( size_t i=0 ; iactualParentPopulationSize = obSize; + parents = nextGeneration; + + + return nextGeneration; +} + + +Individual** Population::reduceOffspringPopulation(size_t obSize){ + Individual** nextGeneration = new Individual*[obSize]; + + reducePopulation(offsprings,actualOffspringPopulationSize,nextGeneration,obSize, + Population::replacementOperator); + + // free no longer needed individuals + for( size_t i=0 ; iactualParentPopulationSize = obSize; + parents = nextGeneration; + return nextGeneration; +} + + +static int individualCompare(const void* p1, const void* p2){ + Individual** p1_i = (Individual**)p1; + Individual** p2_i = (Individual**)p2; + + return p1_i[0]->getFitness() > p2_i[0]->getFitness(); +} + +static int individualRCompare(const void* p1, const void* p2){ + Individual** p1_i = (Individual**)p1; + Individual** p2_i = (Individual**)p2; + + return p1_i[0]->getFitness() < p2_i[0]->getFitness(); +} + + +void Population::sortPopulation(Individual** population, size_t populationSize){ + qsort(population,populationSize,sizeof(Individual*),individualCompare); +} + +void Population::sortRPopulation(Individual** population, size_t populationSize){ + qsort(population,populationSize,sizeof(Individual*),individualRCompare); +} + + +/** + Reduit les populations en faisant l'operation de remplacement. + + @TODO : on aurait voulu eviter la recopie des deux populations en une seule + mais cela semble incompatible avec SelectionOperator (notamment l'operation + d'initialisation. +*/ +void Population::reduceTotalPopulation(){ + + Individual** nextGeneration = new Individual*[parentPopulationSize]; + +#if ((\ELITE_SIZE!=0) && (\ELITISM==true)) // If there is elitism and it is strong + Population::elitism(\ELITE_SIZE,parents,actualParentPopulationSize, + nextGeneration,parentPopulationSize); // do the elitism on the parent population only + actualParentPopulationSize -= \ELITE_SIZE; // decrement the parent population size +#endif + + size_t actualGlobalSize = actualParentPopulationSize+actualOffspringPopulationSize; + Individual** globalPopulation = new Individual*[actualGlobalSize](); + + + memcpy(globalPopulation,parents,sizeof(Individual*)*actualParentPopulationSize); + memcpy(globalPopulation+actualParentPopulationSize,offsprings, + sizeof(Individual*)*actualOffspringPopulationSize); + replacementOperator->initialize(globalPopulation, replacementPressure,actualGlobalSize); + +#if ((\ELITE_SIZE!=0) && (\ELITISM==false)) // If there is elitism and it is weak + Population::elitism(\ELITE_SIZE,globalPopulation,actualGlobalSize, + nextGeneration,parentPopulationSize); // do the elitism on the global (already merged) population + actualGlobalSize -= \ELITE_SIZE; // decrement the parent population size +#endif + + + Population::reducePopulation(globalPopulation,actualGlobalSize,\ELITE_SIZE+nextGeneration, + parentPopulationSize-\ELITE_SIZE,replacementOperator); + + for( size_t i=0 ; iinitialize(parents,selectionPressure,actualParentPopulationSize); + + for( size_t i=0 ; iselectNext(offspringPopulationSize); + p1 = parents[index]; + + if( rg->tossCoin(pCrossover) ){ + for( size_t j=0 ; jselectNext(offspringPopulationSize); + ps[j] = parents[index]; + } + child = p1->crossover(ps); + } + else child = new Individual(*parents[index]); + + if( rg->tossCoin(pMutation) ){ + child->mutate(pMutationPerGene); + } + + offsprings[actualOffspringPopulationSize++] = child; + } + delete[](ps); + } + + + + +/** + Here we save elit individuals to the replacement + + @ARG elitismSize the number of individuals save by elitism + @ARG population the population where the individuals are save + @ARG populationSize the size of the population + @ARG outPopulation the output population, this must be allocated with size greather than elitism + @ARG outPopulationSize the size of the output population + +*/ + void Population::elitism(size_t elitismSize, Individual** population, size_t populationSize, + Individual** outPopulation, size_t outPopulationSize){ + + float bestFitness; + size_t bestIndividual; + + if( elitismSize >= 5 )DEBUG_PRT("Warning, elitism has O(n) complexity, elitismSize is maybe too big (%d)",elitismSize); + + + for(size_t i = 0 ; igetExtremum(); + bestIndividual = 0; + for( size_t j=0 ; jgetFitness() ){ + bestFitness = population[j]->getFitness(); + bestIndividual = j; + } + } + outPopulation[i] = population[bestIndividual]; + population[bestIndividual] = population[populationSize-(i+1)]; + population[populationSize-(i+1)] = NULL; + } +} + + + + +std::ostream& operator << (std::ostream& O, const Population& B) +{ + + size_t offspringPopulationSize = B.offspringPopulationSize; + size_t realOffspringPopulationSize = B.actualOffspringPopulationSize; + + size_t parentPopulationSize = B.parentPopulationSize; + size_t realParentPopulationSize = B.actualParentPopulationSize; + + + O << "Population : "<< std::endl; + O << "\t Parents size : "<< realParentPopulationSize << "/" << + parentPopulationSize << std::endl; + + for( size_t i=0 ; irandom(0,populationSize-1); +} + +float MaxRandom::getExtremum(){ + return -FLT_MAX; +} + +MinRandom::MinRandom(RandomGenerator* globalRandomGenerator){ + rg = globalRandomGenerator; +} + +void MinRandom::initialize(Individual** population, float selectionPressure, size_t populationSize){ + SelectionOperator::initialize(population,selectionPressure,populationSize); +} + +size_t MinRandom::selectNext(size_t populationSize){ + rg->random(0,populationSize-1); +} + +float MinRandom::getExtremum(){ + return -FLT_MAX; +} + + + + +\START_CUDA_TOOLS_H_TPL/* **************************************** + Some tools classes for algorithm +****************************************/ +#include +#include +#include +class EvolutionaryAlgorithm; +class Individual; +class Population; + +#ifdef DEBUG +#define DEBUG_PRT(format, args...) fprintf (stdout,"***DBG*** %s-%d: "format"\n",__FILE__,__LINE__,##args) +#define DEBUG_YACC(format, args...) fprintf (stdout,"***DBG_YACC*** %s-%d: "format"\n",__FILE__,__LINE__,##args) +#else +#define DEBUG_PRT(format, args...) +#define DEBUG_YACC(format, args...) +#endif + + +/* **************************************** + StoppingCriterion class +****************************************/ +#ifndef __EASEATOOLS +#define __EASEATOOLS +class StoppingCriterion { + +public: + virtual bool reached() = 0; + +}; + + +/* **************************************** + GenerationalCriterion class +****************************************/ +class GenerationalCriterion : public StoppingCriterion { + private: + size_t* currentGenerationPtr; + size_t generationalLimit; + public: + virtual bool reached(); + GenerationalCriterion(EvolutionaryAlgorithm* ea, size_t generationalLimit); + +}; + + +/* **************************************** + RandomGenerator class +****************************************/ +class RandomGenerator{ +public: + RandomGenerator(unsigned int seed); + int randInt(); + bool tossCoin(); + bool tossCoin(float bias); + int randInt(int min, int max); + int getRandomIntMax(int max); + float randFloat(float min, float max); + int random(int min, int max); + float random(float min, float max); + double random(double min, double max); + +}; + + + +/* **************************************** + Selection Operator class +****************************************/ +class SelectionOperator{ +public: + virtual void initialize(Individual** population, float selectionPressure, size_t populationSize); + virtual size_t selectNext(size_t populationSize); + virtual float getExtremum() = 0 ; +protected: + Individual** population; + float currentSelectionPressure; +}; + + +/* **************************************** + Tournament classes (min and max) +****************************************/ +class MaxTournament : public SelectionOperator{ +public: + MaxTournament(RandomGenerator* rg){ this->rg = rg; } + virtual void initialize(Individual** population, float selectionPressure, size_t populationSize); + virtual size_t selectNext(size_t populationSize); + float getExtremum(); +private: + RandomGenerator* rg; + +}; + + + +class MinTournament : public SelectionOperator{ +public: + MinTournament(RandomGenerator* rg){ this->rg = rg; } + virtual void initialize(Individual** population, float selectionPressure, size_t populationSize); + virtual size_t selectNext(size_t populationSize); + float getExtremum(); +private: + RandomGenerator* rg; + +}; + + +class MaxDeterministic : public SelectionOperator{ + public: + virtual void initialize(Individual** population, float selectionPressure, size_t populationSize); + virtual size_t selectNext(size_t populationSize); + float getExtremum(); + private: + size_t populationSize; +}; + +class MinDeterministic : public SelectionOperator{ + public: + virtual void initialize(Individual** population, float selectionPressure, size_t populationSize); + virtual size_t selectNext(size_t populationSize); + float getExtremum(); + private: + size_t populationSize; + +}; + + +class MaxRandom : public SelectionOperator{ + public: + MaxRandom(RandomGenerator* globalRandomGenerator); + virtual void initialize(Individual** population, float selectionPressure, size_t populationSize); + virtual size_t selectNext(size_t populationSize); + float getExtremum(); + private: + size_t populationSize; + RandomGenerator* rg; + +}; + +class MinRandom : public SelectionOperator{ + public: + MinRandom(RandomGenerator* globalRandomGenerator); + virtual void initialize(Individual** population, float selectionPressure, size_t populationSize); + virtual size_t selectNext(size_t populationSize); + float getExtremum(); + private: + size_t populationSize; + RandomGenerator* rg; +}; + + + +class Population { + + private: + + float pCrossover; + float pMutation; + float pMutationPerGene; + + Individual** parents; + Individual** offsprings; + + size_t parentPopulationSize; + size_t offspringPopulationSize; + + size_t actualParentPopulationSize; + size_t actualOffspringPopulationSize; + + static SelectionOperator* selectionOperator; + static SelectionOperator* replacementOperator; + + RandomGenerator* rg; + + public: + + Population(size_t parentPopulationSize, size_t offspringPopulationSize, + float pCrossover, float pMutation, float pMutationPerGene, RandomGenerator* rg); + virtual ~Population(); + + void initializeParentPopulation(); + void evaluatePopulation(Individual** population, size_t populationSize); + void evaluateParentPopulation(); + + static void elitism(size_t elitismSize, Individual** population, size_t populationSize, Individual** outPopulation, + size_t outPopulationSize); + + void evaluateOffspringPopulation(); + Individual** reducePopulations(Individual** population, size_t populationSize, + Individual** reducedPopulation, size_t obSize); + Individual** reduceParentPopulation(size_t obSize); + Individual** reduceOffspringPopulation(size_t obSize); + void reduceTotalPopulation(); + void evolve(); + + static float selectionPressure; + static float replacementPressure; + static void initPopulation(SelectionOperator* selectionOperator, + SelectionOperator* replacementOperator, + float selectionPressure, float replacementPressure); + + static void sortPopulation(Individual** population, size_t populationSize); + + static void sortRPopulation(Individual** population, size_t populationSize); + + + void sortParentPopulation(){ Population::sortPopulation(parents,actualParentPopulationSize);} + + void produceOffspringPopulation(); + + friend std::ostream& operator << (std::ostream& O, const Population& B); + + + void setParentPopulation(Individual** population, size_t actualParentPopulationSize){ + this->parents = population; + this->actualParentPopulationSize = actualParentPopulationSize; + } + + static Individual** reducePopulation(Individual** population, size_t populationSize, + Individual** reducedPopulation, size_t obSize, + SelectionOperator* replacementOperator); +}; + + +#endif + + +\START_CUDA_MAKEFILE_TPL + +NVCC= nvcc +CPPC= g++ +CXXFLAGS+=-g + +#USER MAKEFILE OPTIONS : +\INSERT_MAKEFILE_OPTION#END OF USER MAKEFILE OPTIONS + +EASEA_SRC= EASEATools.cpp EASEAIndividual.cpp +EASEA_MAIN_HDR= EASEA.cpp +EASEA_UC_HDR= EASEAUserClasses.hpp + +EASEA_HDR= $(EASEA_SRC:.cpp=.hpp) + +SRC= $(EASEA_SRC) $(EASEA_MAIN_HDR) +HDR= $(EASEA_HDR) $(EASEA_UC_HDR) +OBJ= $(EASEA_SRC:.cpp=.o) $(EASEA_MAIN_HDR:.cpp=.o) + +BIN= EASEA + +all:$(BIN) + +$(BIN):$(OBJ) + $(CXX) $^ -o $@ $(LDFLAGS) + +easeaclean: clean + rm -f Makefile $(SRC) $(HDR) EASEA.mak +clean: + rm -f $(OBJ) $(BIN) + +\TEMPLATE_END