Clone wiki

GAF / Creating an Auto-Mutate Operator

Creating an Auto-Mutate Operator

Introduction

There are two basic methods for producing a custom Genetic Operator for use with the Genetic Algorithm Framework for .Net. The the most flexible involves creating a C# class that implements the GAF.IGeneticOperator interface (see [[Genetic_Operators#Custom_Operators|Custom Operators]]). However, the recommended approach is to derive a new Genetic Operator from an existing operator base class. The following example demonstrates this approach
by creating an 'Auto-Mutate' Genetic Operator.

Auto-Mutation

Watson (2003) discussed an approach that used a non-phenotype gene within the chromosome that could be used to increase the mutation probability. This additional gene was treated to the same genetic operations as the other genes, however, it was not used during chromosome decoding process. The gene was simply used to modify the mutation probability.

The class AutoMutate in the code below shows an Auto-Mutate operator that has been built by deriving from the existing MutateBase base class. This process makes it very simple to create an operator that could increase the mutation probability depending upon the non-phenotype gene’s value.

In this implementation, a value of 1 increases the probability by a factor of 5, 10 or 20 depending upon the configuration. A value of 0 has no effect on the mutation probability. The code for this extended operator is shown below. As the non-phenotype gene is subject itself, to this increased probability, there is a greater probability that the gene will be changed from 1 to 0 than from 0 to 1. The effect therefore, is that as convergence occurs, less and less chromosomes are subject to this increased mutation rate. However, if the landscape changes significantly, other chromosomes not affected by genetic operators come in to play. Those with the non-phenotype gene will increase the mutation probability rate once again, until the GA converges towards the new solution. The process will continue in this manner at every significant change in landscape. This Auto-Mutation process is explained in greater detail in Watsons paper (see References below).

In this example the last gene is assumed to be the non-phenotype gene. In order to use this operator, simply create a chromosome with an extra gene. Set this gene to a random value and do not use the gene to store information (non-phenotype gene).

Example Code

This code and the compiled assembly is avalaible via [Docker and BitBucket].

namespace CustomOperators
{
    public class AutoMutate : MutateBase, IGeneticOperator
    {
        private AutoMutateFactor _autoMutationFactorS;
        private readonly object _syncLock = new object ();

        public AutoMutate2 (double mutationProbability)
            : base (mutationProbability)
        {
        }

        protected override void Mutate (Chromosome child)
        {
            //store the defined mutation probability
            var tempProbability = MutationProbability;

            //adjust and scale for AutoMutate Factor based on the value of the last gene
            var nonPhenotypeGene = child.Genes.Last ();

            if (nonPhenotypeGene.BinaryValue == 1) {
                MutationProbability = MutationProbability * (int)AutoMutationFactor;
            }

            base.Mutate (child);

            //restore the original probability
            MutationProbability = tempProbability;

        }

        protected override void MutateGene (Gene gene)
        {
            // This example mutates Binary, Real and Integer types and raises 
            // an exception if the Gene is any other type.

            if (gene.GeneType == GeneType.Binary) {
                gene.ObjectValue = !(bool)gene.ObjectValue;
            } else {
                throw new OperatorException ("Genes with this GeneType cannot be mutated by this operator.");
            }
        }

        public AutoMutateFactor AutoMutationFactor {
            get {
                lock (_syncLock) {
                    return _autoMutationFactorS;
                }
            }
            set {
                lock (_syncLock) {
                    _autoMutationFactorS = value;
                }
            }
        }
    }
}

The following enumerator is used within the example above.

namespace CustomOperators
{
    public enum AutoMutateFactor
    {
        None = 1,
        Factor5 = 5,
        Factor10 = 10,
        Factor20 = 20,
        Factor50 = 50
    }
}

References:

Watson, T. (2003) An Investigation into Cooperative Behaviour: Altrurism and Evolutionary Computing. ''Submitted in partial fulfilment of the requirements for the degree of Doctor Of Philosophy DeMontfort Universiity 2003..

Updated