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;
}