Creating Custom Genetic Operators

[JGAP Home]

Preface: This document corresponds to an earlier JGAP version. The introduced ReproductionOperator is no longer in use. Now, reproduction takes place via natural selectors.

It may be you want to experiment around with new or different genetic operators to assess their impact upon the performance of the genetic algorithm. Or maybe you wish to replace the random number generator with a more rigorous implementation. Customizing JGAP is intended to be easy and straight-forward. JGAP supports a Configuration mechanism that easily allows you to add your own genetic operators to the mix, as well as replace certain components such as the natural selector, the random number generator, and the event manager.

Creating a new genetic operator is probably the second-most common form of JGAP customization, after the creation of custom Genes. We'll look at an existing operator, the ReproductionOperator, as an example of how to create your own genetic operator. As you'll see, it's extremely simple.

Step 1: Implement GeneticOperator

To create your own genetic operator, you'll need to implement the org.jgap.GeneticOperator interface. This interface only has one method, operate(), which is the method that will be invoked by the genetic engine when it's time for your genetic operator to do its work. Let's look at the source for the ReproductionOperator:

package org.jgap.impl;

import org.jgap.Chromosome;
import org.jgap.Configuration;
import org.jgap.GeneticOperator;

import java.util.List;

* The reproduction operator makes a copy of each Chromosome in the
* population and adds it to the list of candidate chromosomes. This
* essentially guarantees that each Chromosome in the current population
* remains a candidate for selection for the next population.
public class ReproductionOperator implements GeneticOperator
* The operate method will be invoked on each of the genetic operators
* referenced by the current Configuration object during the evolution
* phase. Operators are given an opportunity to run in the order that
* they are added to the Configuration. Implementations of this method
* may reference the population of Chromosomes as it was at the beginning
* of the evolutionary phase or the candidate Chromosomes, which are the
* results of prior genetic operators. In either case, only Chromosomes
* added to the list of candidate chromosomes will be considered for
* natural selection. Implementations should never modify the original
* population.
* @param a_population the population of chromosomes from the current
* evolution prior to exposure to any genetic operators
* @param a_candidateChromosomes the pool of chromosomes that are candidates
* for the next evolved population. Any chromosomes that are modified by this
* genetic operator that should be considered for natural selection should be
* added to the candidate chromosomes
    public void operate( final Population a_population,
                         final List a_candidateChromosomes )
        // Just loop over the chromosomes in the population, make a copy of
        // each one, and then add that copy to the candidate chromosomes
        // pool so that it'll be considered for natural selection during the
        // next phase of evolution.
        // -----------------------------------------------------------------
        int len = a_population.size();
        for ( int i = 0; i < len; i++ )
            a_candidateChromosomes.add( a_population.getChromosome(i).clone() );

The purpose of this operator is simply to create a copy of each of the Chromosomes in the population. This is done to ensure that the original Chromosomes will have a chance to be selected, in addition to their offspring. As can be seen from the code, the operate() method accepts three parameters: the active Configuration object, an array of Chromosomes that make up the current population, and a List of candidate chromosomes that will ultimately go to the natural selection phase. The population array should never be modified--it is intended to represent the population as it was before any genetic operators have been invoked. If you wish to alter a Chromosome, you should first make a copy of it via the clone() method and then alter the copy. Any altered Chromosomes that you wish to go on to the natural selection phase must be added to the list of candidate chromosomes.

Step 2: Add the Operator to the Configuration

Now that we've written our operator, we need to tell JGAP to use it. This just requires a single additional call to the Configuration object during your normal setup phase:

Configuration conf = new DefaultConfiguration();
conf.addGeneticOperator( new ReproductionOperator() );

The genetic engine will run the population of Chromosomes through each of the active genetic operators in the order in which they were added to the Configuration object. It's worth noting that there is no way to remove an operator from the Configuration object, which means that if you want to replace an existing operator with your own implementation, or place your genetic operator "in front" of an existing operator, you won't be able to rely on the DefaultConfiguration convenience class, since it automatically adds all of the stock genetic operators. Instead, you'll need to setup your Configuration from scratch, which isn't all that daunting a task. Just have a look at the DefaultConfiguration class to see what it does. If you're just adding new genetic operators (and not replacing existing ones) and are content with them being at the end of the operator chain, then you should be able to continue using the DefaultConfiguration class.

Important Note! When using your own set of genetic operators, please be aware that if you do not include a reproduction operator, then the chromosomes in your population will not automatically become candidates for natural selection. It is the reproduction operator that guarantees that each of the chromosomes in the current population become candidates for the next generation.

Other Customizations

As mentioned above, it's also possible to replace the JGAP natural selector, random number generator, and event manager. Details of these customizations are beyond the scope of this document, but performing them follows a similar process to creating a new genetic operator: first, the new implementation must be written and implement the appropriate interface; and second, the Configuration object must be setup to use your new implementation. Unlike genetic operators, the Configuration object allows these other components to be replaced, so you can continue using the DefaultConfiguration convenience class if desired.

The appropriate interfaces to implement for the various customizations are as follows:

Please see the Javadocs for each of the above for further information on what is required for each implementation.

[Documentation Index]
SourceForge Logo