Example of SimpleGA
This example load a file called 'ga.conf' where it read the configurations.
A template for ga.conf is the following: <pre> [COMMON] randomSeed = 25 [GA] type = SimpleGA numThreads = 2 ### number of threads to use ngenerations = 200 [GA/EVALUATION] type = FitnessFunction ### Custom settings of ga1 example ### Choose among: square, abs, mexhat functionTarget = square [GA/GENOME] type = Genome nindividuals = 100 [GA/GENOME/GENOTYPE] ### Choose between SignedRange and Real type = SignedRange ngenes = 2 ### Parameters for SignedRange nbits = 8 maxValue = 20 ### Parameters for Real # maxValue = +20 # minValue = -20 [GA/REPRODUCTION] type = FixedSize crossoverRate = 0 elitism = false nelited = 10 [GA/REPRODUCTION/CROSSOVER] type = OnePoint ## OnePoint crossover doesn't need any parameter [GA/REPRODUCTION/MUTATION] type = RandomFloat ### Choose between FlipBit and RandomFloat mutation_rate = 0.015 [GA/REPRODUCTION/SELECTION] type = DeterministicRank ### Parameters for DeterministicRank nTruncation = 20
#include "gaconfig.h"
#include "configuration/configurationparameters.h"
#include "configuration/inifilesupport.h"
#include "factory/factory.h"
#include "core/randomgenerator.h"
#include "core/evaluation.h"
#include "genotypes/doublegenotype.h"
#include "core/genome.h"
#include "core/geneticalgo.h"
#include <cmath>
#include <QDebug>
class FitnessFunction : public Evaluation {
public:
FitnessFunction() : Evaluation() {
functype = square;
};
// custom configuration
// This fitness function can be customized by 'functionTarget' parameter of EVALUATOR group
// Possibile functionTarget value are:
// - square : compute the sum of square of genes as fitness
// - abs : compute the sum of the distances from the id of gene and gene value
// Example of use:
//
// [EVALUATOR]
// functionTarget = square
virtual void configure( const ConfigurationParameters& params, QString prefix ) {
QString ft = params.getValue( prefix + QString( "functionTarget" ) );
if ( ft == "square" ) functype = square;
if ( ft == "abs" ) functype = abs;
if ( ft == "mexhat" ) functype = mexhat;
};
virtual FitnessFunction* clone() const {
FitnessFunction* ret = new FitnessFunction();
ret->functype = functype;
return ret;
};
protected:
void init() {
};
void step() {
double fit = 0.0;
//--- calculate the fitness function
DoubleGenotype* gen = (DoubleGenotype*)( genotype() );
for( unsigned int i=0; i<gen->numGenes(); i++ ) {
switch( functype ) {
case square:
case mexhat:
fit += gen->at(i)*gen->at(i);
break;
case abs:
fit += -fabs( gen->at(i) - i );
break;
default:
fit = 0;
break;
}
}
if ( functype == mexhat ) {
fit = cos( sqrt(fit) ) * exp( -fit/40.0 );
}
genotype()->setFitness( fit );
evaluationDone();
};
void fini() {
};
private:
typedef enum { square, abs, mexhat } functionType;
functionType functype;
};
int main( int argc, char* argv[] ) {
Q_UNUSED( argc );
Q_UNUSED( argv );
//--- IMPORTANT !!! You Have To Register your fitness function
Factory::getInstance().registerClass<FitnessFunction>( "FitnessFunction" );
//--- Parameters Loaded from file ga.ini (case sensitive)
ConfigurationParameters params(true);
if (!params.loadParameters("ga.ini")) {
qWarning() << "Loading parameters from file ga.ini failed";
return 1;
}
//--- Initialize the globalRNG with seed
if ( params.getValue( "COMMON/randomSeed" ) == "random" ) {
globalRNG->setSeed( time(0) );
qDebug() << "Random Seed:" << globalRNG->seed();
} else {
globalRNG->setSeed( params.getValue( "COMMON/randomSeed" ).toInt() );
}
//--- create and configure the Genetic Algorithm
GeneticAlgo* ga = Factory::getInstance().createFromParameter<GeneticAlgo>( params, "GA" );
ga->initialize();
//--- Evolve for all Generations
ga->evolve();
//--- print out the best individuals
DoubleGenotype* best = (DoubleGenotype*)(ga->genome()->bestGenotype());
qDebug() << "Fitness:" << best->fitness();
qDebug() << best->toString();
for( unsigned int i=0; i<best->numGenes(); i++ ) {
qDebug() << "Gene:" << i << "Value:" << best->at(i);
}
return 0;
}