Commit 9d46eb94 authored by kruger's avatar kruger
Browse files

Memetic Version for STD

parent 65d4100f
/*_________________________________________________________
Test functions
log normal adaptive mutation
Selection operator: Tournament
__________________________________________________________*/
\User declarations :
#define SIZE 100
#define X_MIN -1.
#define X_MAX 1.
#define ITER 120
#define Abs(x) ((x) < 0 ? -(x) : (x))
#define MAX(x,y) ((x)>(y)?(x):(y))
#define MIN(x,y) ((x)<(y)?(x):(y))
#define SIGMA 1. /* mutation parameter */
#define PI 3.141592654
float pMutPerGene=0.1;
\end
\User functions:
//fitness function
#include <math.h>
__device__ __host__ inline float Weierstrass(float x[SIZE], int n) // Weierstrass multimidmensionnel h = 0.25
{
float res = 0.;
float val[SIZE];
float b=2.;
float h = 0.25;
for (int i = 0;i<n; i++) {
val[i] = 0.;
for (int k=0;k<ITER;k++)
val[i] += pow(b,-(float)k*h) * sin(pow(b,(float)k)*x[i]);
res += Abs(val[i]);
}
return (res);
}
float gauss()
/* Generates a normally distributed random value with variance 1 and 0 mean.
Algorithm based on "gasdev" from Numerical recipes' pg. 203. */
{
int iset = 0;
float gset = 0.0;
float v1 = 0.0, v2 = 0.0, r = 0.0;
float factor = 0.0;
if (iset) {
iset = 0;
return gset;
}
else {
do {
v1 = (float)random(0.,1.) * 2.0 - 1.0;
v2 = (float)random(0.,1.) * 2.0 - 1.0;
r = v1 * v1 + v2 * v2;
}
while (r > 1.0);
factor = sqrt (-2.0 * log (r) / r);
gset = v1 * factor;
iset = 1;
return (v2 * factor);
}
}
\end
\Before everything else function:
//cout<<"Before everything else function called "<<endl;
\end
\After everything else function:
//cout << "After everything else function called" << endl;
\end
\At the beginning of each generation function:
//cout << "At the beginning of each generation function called" << endl;
\end
\At the end of each generation function:
//cout << "At the end of each generation function called" << endl;
\end
\At each generation before reduce function:
//cout << "At each generation before replacement function called" << endl;
\end
\User classes :
GenomeClass {
float x[SIZE];
float sigma[SIZE]; // auto-adaptative mutation parameter
}
\end
\GenomeClass::display:
/* for( size_t i=0 ; i<SIZE ; i++){ */
/* // cout << Genome.x[i] << ":" << Genome.sigma[i] << "|"; */
/* printf("%.02f:%.02f|",Genome.x[i],Genome.sigma[i]); */
/* } */
\end
\GenomeClass::initialiser : // "initializer" is also accepted
for(int i=0; i<SIZE; i++ ) {
Genome.x[i] = (float)random(X_MIN,X_MAX);
Genome.sigma[i]=(float)random(0.,0.5);
}
\end
\GenomeClass::crossover :
for (int i=0; i<SIZE; i++)
{
float alpha = (float)random(0.,1.); // barycentric crossover
child.x[i] = alpha*parent1.x[i] + (1.-alpha)*parent2.x[i];
}
\end
\GenomeClass::mutator : // Must return the number of mutations
int NbMut=0;
float pond = 1./sqrt((float)SIZE);
for (int i=0; i<SIZE; i++)
if (tossCoin(pMutPerGene)){
NbMut++;
Genome.sigma[i] = Genome.sigma[i] * exp(SIGMA*pond*(float)gauss());
Genome.sigma[i] = MIN(0.5,Genome.sigma[0]);
Genome.sigma[i] = MAX(0.,Genome.sigma[0]);
Genome.x[i] += Genome.sigma[i]*(float)gauss();
Genome.x[i] = MIN(X_MAX,Genome.x[i]); // pour eviter les depassements
Genome.x[i] = MAX(X_MIN,Genome.x[i]);
}
return NbMut;
\end
\GenomeClass::evaluator : // Returns the score
float Score= 0.0;
Score= Weierstrass(Genome.x, SIZE);
return Score;
\end
\GenomeClass::optimiser : // Optimises the Genome
for(int i=0; i<SIZE; i++){
if(random(0.,1.)<0.2)
Genome.x[i]+=0.1;
}
\end
\User Makefile options:
CPPFLAGS+=
\end
\Default run parameters : // Please let the parameters appear in this order
Number of generations : 100 // NB_GEN
Time limit: 0 // In seconds, 0 to deactivate
Population size : 10 //POP_SIZE
Offspring size : 10 // 40%
Mutation probability : 1 // MUT_PROB
Crossover probability : 1 // XOVER_PROB
Evaluator goal : minimise // Maximise
Selection operator: Tournament 2.0
Surviving parents: 100%//percentage or absolute
Surviving offspring: 100%
Reduce parents operator: Tournament 2
Reduce offspring operator: Tournament 2
Final reduce operator: Tournament 2
Elitism: Strong //Weak or Strong
Elite: 1
Number of optimisation iterations : 100 //Number of optimisation iteration
Baldwinism : true //True or False (Lamarckism : keep optimised Genome
Print stats:1 //Default: 1
Generate csv stats file:0
Generate gnuplot script:0
Generate R script:0
Plot stats:0 //Default: 0
\end
\TEMPLATE_START
#ifdef WIN32
#define _CRT_SECURE_NO_WARNINGS
#pragma comment(lib, "libEasea.lib")
#pragma comment(lib, "Winmm.lib")
#endif
/**
This is program entry for STD template for EASEA
*/
\ANALYSE_PARAMETERS
#include <stdlib.h>
#include <iostream>
#include <time.h>
#include "COptionParser.h"
#include "CRandomGenerator.h"
#include "CEvolutionaryAlgorithm.h"
#include "global.h"
#include "EASEAIndividual.hpp"
using namespace std;
/** Global variables for the whole algorithm */
CIndividual** pPopulation = NULL;
CIndividual* bBest = NULL;
float* pEZ_MUT_PROB = NULL;
float* pEZ_XOVER_PROB = NULL;
size_t *EZ_NB_GEN;
size_t *EZ_current_generation;
CEvolutionaryAlgorithm* EA;
int main(int argc, char** argv){
parseArguments("EASEA.prm",argc,argv);
ParametersImpl p;
p.setDefaultParameters(argc,argv);
CEvolutionaryAlgorithm* ea = p.newEvolutionaryAlgorithm();
EA = ea;
EASEAInit(argc,argv);
CPopulation* pop = ea->getPopulation();
ea->runEvolutionaryLoop();
EASEAFinal(pop);
delete pop;
#ifdef WIN32
system("pause");
#endif
return 0;
}
\START_CUDA_GENOME_CU_TPL
#ifdef WIN32
#define _CRT_SECURE_NO_WARNINGS
#pragma comment(lib, "libEasea.lib")
#endif
#include <string.h>
#include <fstream>
#ifndef WIN32
#include <sys/time.h>
#else
#include <time.h>
#endif
#include "CRandomGenerator.h"
#include "CPopulation.h"
#include "COptionParser.h"
#include "CStoppingCriterion.h"
#include "CEvolutionaryAlgorithm.h"
#include "global.h"
#include "CIndividual.h"
using namespace std;
#include "EASEAIndividual.hpp"
CRandomGenerator* globalRandomGenerator;
extern CEvolutionaryAlgorithm* EA;
#define STD_TPL
\INSERT_USER_DECLARATIONS
\ANALYSE_USER_CLASSES
\INSERT_USER_CLASSES
\INSERT_USER_FUNCTIONS
\INSERT_INITIALISATION_FUNCTION
\INSERT_FINALIZATION_FUNCTION
\INSERT_BOUND_CHECKING
void EASEAInit(int argc, char** argv){
\INSERT_INIT_FCT_CALL
}
void EASEAFinal(CPopulation* pop){
\INSERT_FINALIZATION_FCT_CALL;
}
void AESAEBeginningGenerationFunction(CEvolutionaryAlgorithm* evolutionaryAlgorithm){
\INSERT_BEGIN_GENERATION_FUNCTION
}
void AESAEEndGenerationFunction(CEvolutionaryAlgorithm* evolutionaryAlgorithm){
\INSERT_END_GENERATION_FUNCTION
}
void AESAEGenerationFunctionBeforeReplacement(CEvolutionaryAlgorithm* evolutionaryAlgorithm){
\INSERT_GENERATION_FUNCTION_BEFORE_REPLACEMENT
}
IndividualImpl::IndividualImpl() : CIndividual() {
\GENOME_CTOR
\INSERT_EO_INITIALISER
valid = false;
}
CIndividual* IndividualImpl::clone(){
return new IndividualImpl(*this);
}
IndividualImpl::~IndividualImpl(){
\GENOME_DTOR
}
float IndividualImpl::evaluate(){
valid = true;
\INSERT_EVALUATOR
}
IndividualImpl::IndividualImpl(const IndividualImpl& genome){
// ********************
// Problem specific part
\COPY_CTOR
// ********************
// Generic part
this->valid = genome.valid;
this->fitness = genome.fitness;
}
CIndividual* IndividualImpl::crossover(CIndividual** ps){
// ********************
// Generic part
IndividualImpl** tmp = (IndividualImpl**)ps;
IndividualImpl parent1(*this);
IndividualImpl parent2(*tmp[0]);
IndividualImpl child(*this);
//DEBUG_PRT("Xover");
/* cout << "p1 : " << parent1 << endl; */
/* cout << "p2 : " << parent2 << endl; */
// ********************
// Problem specific part
\INSERT_CROSSOVER
child.valid = false;
/* cout << "child : " << child << endl; */
return new IndividualImpl(child);
}
void IndividualImpl::printOn(std::ostream& os) const{
\INSERT_DISPLAY
}
std::ostream& operator << (std::ostream& O, const IndividualImpl& B)
{
// ********************
// Problem specific part
O << "\nIndividualImpl : "<< 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 IndividualImpl::mutate( float pMutationPerGene ){
this->valid=false;
// ********************
// Problem specific part
\INSERT_MUTATOR
}
void IndividualImpl::optimiser(int currentIteration){
\INSERT_OPTIMISER
}
void PopulationImpl::optimisePopulation(CIndividual** population, size_t populationSize){
for(int iter=0; iter<params->optimiseIterations; iter++){
for(int i=0; i<(signed)populationSize; i++){
IndividualImpl* tmp = new IndividualImpl(*(IndividualImpl*)population[i]);
tmp->optimiser(iter);
tmp->evaluate();
if(params->baldwinism){
if((\MINIMAXI && tmp->fitness<population[i]->fitness) || (!\MINIMAXI && tmp->fitness>population[i]->fitness))
population[i]->fitness = tmp->fitness;
delete tmp;
}
else{
if((\MINIMAXI && tmp->fitness<population[i]->fitness) || (!\MINIMAXI && tmp->fitness>population[i]->fitness)){
delete population[i];
population[i]=tmp;
}
else
delete tmp;
}
}
}
}
void ParametersImpl::setDefaultParameters(int argc, char** argv){
this->minimizing = \MINIMAXI;
this->nbGen = setVariable("nbGen",(int)\NB_GEN);
selectionOperator = getSelectionOperator(setVariable("selectionOperator","\SELECTOR_OPERATOR"), this->minimizing, globalRandomGenerator);
replacementOperator = getSelectionOperator(setVariable("reduceFinalOperator","\RED_FINAL_OPERATOR"),this->minimizing, globalRandomGenerator);
parentReductionOperator = getSelectionOperator(setVariable("reduceParentsOperator","\RED_PAR_OPERATOR"),this->minimizing, globalRandomGenerator);
offspringReductionOperator = getSelectionOperator(setVariable("reduceOffspringOperator","\RED_OFF_OPERATOR"),this->minimizing, globalRandomGenerator);
selectionPressure = setVariable("selectionPressure",(float)\SELECT_PRM);
replacementPressure = setVariable("reduceFinalPressure",(float)\RED_FINAL_PRM);
parentReductionPressure = setVariable("reduceParentsPressure",(float)\RED_PAR_PRM);
offspringReductionPressure = setVariable("reduceOffspringPressure",(float)\RED_OFF_PRM);
pCrossover = \XOVER_PROB;
pMutation = \MUT_PROB;
pMutationPerGene = 0.05;
parentPopulationSize = setVariable("popSize",(int)\POP_SIZE);
offspringPopulationSize = setVariable("nbOffspring",(int)\OFF_SIZE);
parentReductionSize = setReductionSizes(parentPopulationSize, setVariable("survivingParents",(float)\SURV_PAR_SIZE));
offspringReductionSize = setReductionSizes(offspringPopulationSize, setVariable("survivingOffspring",(float)\SURV_OFF_SIZE));
this->elitSize = setVariable("elite",(int)\ELITE_SIZE);
this->strongElitism = setVariable("eliteType",(int)\ELITISM);
if((this->parentReductionSize + this->offspringReductionSize) < this->parentPopulationSize){
printf("*WARNING* parentReductionSize + offspringReductionSize < parentPopulationSize\n");
printf("*WARNING* change Sizes in .prm or .ez\n");
printf("EXITING\n");
exit(1);
}
if((this->parentPopulationSize-this->parentReductionSize)>this->parentPopulationSize-this->elitSize){
printf("*WARNING* parentPopulationSize - parentReductionSize > parentPopulationSize - elitSize\n");
printf("*WARNING* change Sizes in .prm or .ez\n");
printf("EXITING\n");
exit(1);
}
if(!this->strongElitism && ((this->offspringPopulationSize - this->offspringReductionSize)>this->offspringPopulationSize-this->elitSize)){
printf("*WARNING* offspringPopulationSize - offspringReductionSize > offspringPopulationSize - elitSize\n");
printf("*WARNING* change Sizes in .prm or .ez\n");
printf("EXITING\n");
exit(1);
}
/*
* The reduction is set to true if reductionSize (parent or offspring) is set to a size less than the
* populationSize. The reduction size is set to populationSize by default
*/
if(offspringReductionSize<offspringPopulationSize) offspringReduction = true;
else offspringReduction = false;
if(parentReductionSize<parentPopulationSize) parentReduction = true;
else parentReduction = false;
cout << "Parent red " << parentReduction << " " << parentReductionSize << "/"<< parentPopulationSize << endl;
cout << "Parent red " << offspringReduction << " " << offspringReductionSize << "/" << offspringPopulationSize << endl;
generationalCriterion = new CGenerationalCriterion(setVariable("nbGen",(int)\NB_GEN));
controlCStopingCriterion = new CControlCStopingCriterion();
timeCriterion = new CTimeCriterion(setVariable("timeLimit",\TIME_LIMIT));
this->optimise=1;
this->optimiseIterations = setVariable("optimiseIterations",(int)\NB_OPT_IT);
this->baldwinism = setVariable("baldwinism",(int)\BALDWINISM);
seed = setVariable("seed",(int)time(0));
globalRandomGenerator = new CRandomGenerator(seed);
this->randomGenerator = globalRandomGenerator;
this->printStats = setVariable("printStats",\PRINT_STATS);
this->generateCSVFile = setVariable("generateCSVFile",\GENERATE_CSV_FILE);
this->generateGnuplotScript = setVariable("generateGnuplotScript",\GENERATE_GNUPLOT_SCRIPT);
this->generateRScript = setVariable("generateRScript",\GENERATE_R_SCRIPT);
this->plotStats = setVariable("plotStats",\PLOT_STATS);
this->printInitialPopulation = setVariable("printInitialPopulation",0);
this->printFinalPopulation = setVariable("printFinalPopulation",0);
this->outputFilename = (char*)"EASEA";
this->plotOutputFilename = (char*)"EASEA.png";
}
CEvolutionaryAlgorithm* ParametersImpl::newEvolutionaryAlgorithm(){
pEZ_MUT_PROB = &pMutationPerGene;
pEZ_XOVER_PROB = &pCrossover;
EZ_NB_GEN = (size_t*)setVariable("nbGen",\NB_GEN);
EZ_current_generation=0;
CEvolutionaryAlgorithm* ea = new EvolutionaryAlgorithmImpl(this);
generationalCriterion->setCounterEa(ea->getCurrentGenerationPtr());
ea->addStoppingCriterion(generationalCriterion);
ea->addStoppingCriterion(controlCStopingCriterion);
ea->addStoppingCriterion(timeCriterion);
EZ_NB_GEN=((CGenerationalCriterion*)ea->stoppingCriteria[0])->getGenerationalLimit();
EZ_current_generation=&(ea->currentGeneration);
return ea;
}
void EvolutionaryAlgorithmImpl::initializeParentPopulation(){
for( unsigned int i=0 ; i< this->params->parentPopulationSize ; i++){
this->population->addIndividualParentPopulation(new IndividualImpl());
}
}
EvolutionaryAlgorithmImpl::EvolutionaryAlgorithmImpl(Parameters* params) : CEvolutionaryAlgorithm(params){
this->population = (CPopulation*)new PopulationImpl(this->params->parentPopulationSize,this->params->offspringPopulationSize, this->params->pCrossover,this->params->pMutation,this->params->pMutationPerGene,this->params->randomGenerator,this->params);
;
}
EvolutionaryAlgorithmImpl::~EvolutionaryAlgorithmImpl(){
}
PopulationImpl::PopulationImpl(size_t parentPopulationSize, size_t offspringPopulationSize, float pCrossover, float pMutation, float pMutationPerGene, CRandomGenerator* rg, Parameters* params) : CPopulation(parentPopulationSize, offspringPopulationSize, pCrossover, pMutation, pMutationPerGene, rg, params){
;
}
PopulationImpl::~PopulationImpl(){
}
\START_CUDA_GENOME_H_TPL
#ifndef PROBLEM_DEP_H
#define PROBLEM_DEP_H
//#include "CRandomGenerator.h"
#include <stdlib.h>
#include <iostream>
#include <CIndividual.h>
#include <Parameters.h>
class CRandomGenerator;
class CSelectionOperator;
class CGenerationalCriterion;
class CEvolutionaryAlgorithm;
class CPopulation;
class Parameters;
\INSERT_USER_CLASSES_DEFINITIONS
class IndividualImpl : public CIndividual {
public: // in EASEA the genome is public (for user functions,...)
// Class members
\INSERT_GENOME
public:
IndividualImpl();
IndividualImpl(const IndividualImpl& indiv);
virtual ~IndividualImpl();
float evaluate();
static size_t getCrossoverArrity(){ return 2; }
float getFitness(){ return this->fitness; }
CIndividual* crossover(CIndividual** p2);
void optimiser(int currentIteration);
void printOn(std::ostream& O) const;
CIndividual* clone();
size_t mutate(float pMutationPerGene);
friend std::ostream& operator << (std::ostream& O, const IndividualImpl& B) ;
void initRandomGenerator(CRandomGenerator* rg){ IndividualImpl::rg = rg;}
};
class ParametersImpl : public Parameters {
public:
void setDefaultParameters(int argc, char** argv);
CEvolutionaryAlgorithm* newEvolutionaryAlgorithm();
};
/**
* @TODO ces functions devraient s'appeler weierstrassInit, weierstrassFinal etc... (en gros EASEAFinal dans le tpl).
*
*/
void EASEAInit(int argc, char** argv);
void EASEAFinal(CPopulation* pop);
void EASEABeginningGenerationFunction(CEvolutionaryAlgorithm* evolutionaryAlgorithm);
void EASEAEndGenerationFunction(CEvolutionaryAlgorithm* evolutionaryAlgorithm);
void EASEAGenerationFunctionBeforeReplacement(CEvolutionaryAlgorithm* evolutionaryAlgorithm);
class EvolutionaryAlgorithmImpl: public CEvolutionaryAlgorithm {
public:
EvolutionaryAlgorithmImpl(Parameters* params);
virtual ~EvolutionaryAlgorithmImpl();
void initializeParentPopulation();
};
class PopulationImpl: public CPopulation {
public:
PopulationImpl(size_t parentPopulationSize, size_t offspringPopulationSize, float pCrossover, float pMutation, float pMutationPerGene, CRandomGenerator* rg, Parameters* params);
virtual ~PopulationImpl();
void optimisePopulation(CIndividual** population, size_t populationSize);
};
#endif /* PROBLEM_DEP_H */
\START_CUDA_MAKEFILE_TPL
EASEALIB_PATH=\EZ_PATHlibeasea/#/home/kruger/Bureau/Easea/libeasea/
CXXFLAGS = -O2 -g -Wall -fmessage-length=0 -I$(EASEALIB_PATH)include
OBJS = EASEA.o EASEAIndividual.o
LIBS = -lboost_program_options
TARGET = EASEA
$(TARGET): $(OBJS)
$(CXX) -o $(TARGET) $(OBJS) $(LIBS) -g $(EASEALIB_PATH)libeasea.a
#%.o:%.cpp
# $(CXX) -c $(CXXFLAGS) $^
all: $(TARGET)
clean:
rm -f $(OBJS) $(TARGET)
easeaclean: