Custom Reproduction Scheme

This tutorial introduces the use of custom reproduction schemes.

By default CGP-Library uses the mutate random parent reproduction scheme which simply creates each child as a mutated randomly selected parent.  This tutorial will demonstrate how to define and use alternative custom reproduction schemes.

Summary
Custom Reproduction SchemeThis tutorial introduces the use of custom reproduction schemes.
The ProgramA simple program showing how to uses a custom reproduction scheme.
Stepping Through the CodeA close look at each line of the example code.

The Program

A simple program showing how to uses a custom reproduction scheme.

The program below is provided in the CGP-Library download within /examples/customReproductionScheme.c and is included in the code::blocks project.

#include <stdio.h>
#include <stdlib.h>
#include "../src/cgp.h"

void mutateEveryParent(struct parameters *params, struct chromosome **parents, struct chromosome **children, int numParents, int numChildren){

    int i;
    int selectedParent;

    /* for each child */
    for(i=0; i< numChildren; i++){

        selectedParent = i % numParents;

        /* set child as clone of selected parent */
        copyChromosome(children[i], parents[selectedParent]);

        /* mutate newly cloned child */
        mutateChromosome(params, children[i]);
    }
}

int main(void){

    struct parameters *params = NULL;
    struct dataSet *trainingData = NULL;
    struct chromosome *chromo = NULL;

    int numInputs = 1;
    int numNodes = 50;
    int numOutputs = 1;
    int arity = 2;

    int mu = 4;
    int lambda = 8;

    double targetFitness = 0.1;
    int updateFrequency = 1000;
    int numGens = 10000;

    params = initialiseParameters(numInputs, numNodes, numOutputs, arity);

    addNodeFunction(params, "add,sub,mul,div,sin");

    setTargetFitness(params, targetFitness);

    setUpdateFrequency(params, updateFrequency);

    setCustomReproductionScheme(params, mutateEveryParent, "mutateEveryParent");

    setMu(params, mu);
    setLambda(params, lambda);

    trainingData = initialiseDataSetFromFile("./dataSets/symbolic.data");

    chromo = runCGP(params, trainingData, numGens);

    freeChromosome(chromo);
    freeDataSet(trainingData);
    freeParameters(params);

    return 0;
}

Stepping Through the Code

A close look at each line of the example code.

First standard headers and cgp.h are included.

#include <stdio.h>
#include <stdlib.h>
#include "../src/cgp.h"

Next we defined our custom reproduction scheme to be used.

The custom reproduction scheme prototype must take the following form.  Where params is a pointer to an initialised parameters structure, parents is a pointer to an array of chromosomes which contains the parents to select for reproduction, children is a pointer to an array of chromosomes which will contain the created children after reproduction, numParents gives the number of parent chromosomes to be selected from and numChildren gives the number of children to be created.

void reproductionSchemeName(struct parameters *params, struct chromosome **parents, struct chromosome **children, int numParents, int numChildren);

Here the custom reproduction scheme will attempt to use each parent at least once when creating the children.  The reason this is an attempt and not a guarantee is that it is dependant upon the mu and lambda values.  For instance if mu is 10 and lambda is 2 then each parent cannot possibly be used.

The mutate every parent reproduction scheme sets the children as mutated versions of each parent in turn.  For instance the first child will be a mutated version of the first parent and the second child will be a mutated version of the second parent.  If the final parent is reached that the next parent used is the first parent and the process continues.

void mutateEveryParent(struct parameters *params, struct chromosome **parents, struct chromosome **children, int numParents, int numChildren){

    int i;
    int selectedParent;

    /* for each child */
    for(i=0; i< numChildren; i++){

        selectedParent = i % numParents;

        /* set child as clone of selected parent */
        copyChromosome(children[i], parents[selectedParent]);

        /* mutate newly cloned child */
        mutateChromosome(params, children[i]);
    }
}

Much of the main function has been introduced in the Getting Started tutorial and is not re-described here.

In order to use our new reproduction scheme it must be set in the parameters structure using setCustomReproductionScheme.  Where the first variable is the parameters structure, the second is our custom reproduction scheme and the third is a user defined name for the reproduction scheme.  Now when runCGP or repeatCGP is called this custom reproduction scheme will be used in place of the default mutate random parent reproduction scheme.

setCustomReproductionScheme(params, mutateEveryParent, "mutateEveryParent");

In this example, in order for our new reproduction scheme to be effective, the mu and lambda variables must be changed form their default values in parameters.  This is because when mu is set as one, mutate random parent and mutate every parent are equivalent.

setMu(params, mu);
setLambda(params, lambda);

And that’s it, in order to used a custom reproduction scheme it must be defined using the specific prototype and then added as the reproduction scheme to be used by calling setCustomReproductionScheme.  To revert back to the default reproduction scheme simply call setCustomReproductionScheme with the reproduction scheme variable set as NULL.

struct parameters
Stores general evolutionary and chromosome parameters used by the CGP-Library.
struct chromosome
Stores a CGP chromosome instances used by the CGP-Library.
This tutorial introduces and steps through a simple program which uses the CGP-Library to solve a symbolic regression problem.
DLL_EXPORT void setCustomReproductionScheme(
   struct parameters *params,
   void (*reproductionScheme)(struct parameters *params, struct chromosome **parents, struct chromosome **children, int numParents, int numChildren),
   char const *reproductionSchemeName
)
Sets custom reproduction scheme.
DLL_EXPORT struct chromosome* runCGP(struct parameters *params,
struct dataSet *data,
int numGens)
Applies CGP to the given task.
DLL_EXPORT struct results* repeatCGP(struct parameters *params,
struct dataSet *data,
int numGens,
int numRuns)
Repeatedly applies CGP to the given task.
Close