Comparing Different Genetic Programming Packages (June 2007)

There exists many packages that make use of Evolutionary Algorithms. Presenting them all would be a very tedious exercice, and I don't pretend to actually know them all. We will focus exclusively on the ones that specifically offer Genetic Programming (GP) functionalities. To gain time, I have chosen to exclude packages using programming languages with a slow learning curve : no c, c++, no perl. This is a bit unfair, because this takes away some very interesting and useful packages such as Lil-GP or Open Beagle, but this also simplifies life greatly if you don't have years of programming experience in these languages. If you really want to go in this direction, have a look at the bottom of the wikipedia page dedicated to GP, and also see this paper from Christian Gagné [1]. Having a limited amount of funding, we discard MATLAB or commercial packages which are anyway not the best option. Now, here is a list of what is left:

ECJ - Evolutionary Computation/Genetic Programming research system (Java)
Genetic Programming in Java by Russell Wallace
DGPF - simple Genetic Programming research system (Java)
DRP - Directed Ruby Programming, Genetic Programming & Grammatical Evolution Library (Ruby)
gpsys (Java)
JAGA - Extensible and pluggable open source API for implementing genetic algorithms and genetic programming applications (Java)
JavaEvA
JGAP - Java Genetic Algorithms and Genetic Programming, an open-source framework (Java)
JGProg
jrgp
n-genes - Java Genetic Algorithms and Genetic Programming (stack oriented) framework (Java)
PushGP
PyRobot Evolutionary Algorithms (GA + GP) Modules, Open Source (Python)
Sutherland (contact Nicholas McPhee)

 

To evaluate and compare these packages, we will use several criteria. Some of them come from the paper referenced above, and others are just the result of a painful experience practicing obscure and badly documented packages... Here they are:

The comparaison table is not complete, as I did not have the opportunity to experiment in depth with every package. Anybody whishing to add some information and comment will be very much welcome to email me as it will produce a more complete description of what is available.

Name

Documentation (weight = 3)

Activity (weight =2.5) Generic Representation (weight =2) Generic Fitness (weight =2) Generic Operations (weight =2) Parameters (weight =1.5) Output (weight =1) Score
ECJ 6 - good and many examples. The complexity of the package would ask for more detail ,though... 9 - Excellent. Very active community. Nice people 5 - The best of the lot (ADFs, ADMs ...) 8 - Very nice to be able to evaluate the fitness of the sub trees... 8 8 8 52
JGAP 6 - better explanations but fewer examples 8 - Very Good. Large community and active. 4 - A bit more simple. Lacks some interesting features. 7 - Simpler but less powerful 6 - The random generator uses Java.Random which is not very random 7 8 43
PushGP 5 - Good explanation but very general. Detailed stuff is "pythonic"... 5 - Nice and Cosy. Medium sized community 3 - Original, but difficult to use ADFs. 5 - Difficult to get fitness of sub trees... 8 6 8 40
DRP 5 - Good explanation but very general. Detailed stuff is "pythonic"... And fewer examples 4 - Small group. 3 - Interesting, but incomplete 4 - Incomplete 8 6 8 38
JRGP 4 - Confusing. Java doc mostly 1 - Dead 2 - Needs extra work 5 - Workable 7 6 8 33
JGPROG 4 - Confusing. Java doc mostly 1 - Even more dead 2 - Needs extra work 5 - Workable 7 5 8 32

 

[1] Christian Gagné and Marc Parizeau, Genericity in Evolutionary Computation Software Tools: Principles and Case-Study,International Journal on Artificial Intelligence Tools, vol. 15, no. 2, p. 173-194, April 2006 (http://cgagne.googlepages.com/ijait2006.pdf).

 

ECJ Tutorial using Eclipse

Preliminary steps :

library

importing

eclipse path

One useful tip is to put all "params." files in one so you don't have to go through several parameters files for one run. To do it, make a copy of "ec.params" and append to it successively "simple.params", "koza.params", and your custom parameter file (e.g. "tutorial.params"). Then, take away the lines starting with "parent.0 = ". Working on one unified parameter file will avoid you a lot of troubles...

example1

example2

 

A quick and simple way to write detailed individuals on a file with ECJ

No need for using "statistics" classes, or other complications. You can just introduce the following piece of code in the evaluate() method of your class that is extending GPProblem. Example with a modification of tutorial 4 (see the code in bold-red):

/*
Copyright 2006 by Sean Luke
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/

package ec.app.tutorial4;
import ec.util.*;
import ec.*;
import ec.gp.*;
import ec.gp.koza.*;
import ec.simple.*;

public class MultiValuedRegression extends GPProblem implements SimpleProblemForm{

    public double currentX;
    public double currentY;
    public DoubleData input;

    public Object clone(){
        MultiValuedRegression newobj = (MultiValuedRegression) (super.clone());
        newobj.input = (DoubleData)(input.clone());
        return newobj;
    }

    public void setup(final EvolutionState state,final Parameter base){
        // very important, remember this
        super.setup(state,base);
        // set up our input -- don't want to use the default base, it's unsafe here
        input = (DoubleData) state.parameters.getInstanceForParameterEq(
        base.push(P_DATA), null, DoubleData.class);
        input.setup(state,base.push(P_DATA));
    }

    public void evaluate(final EvolutionState state, final Individual ind, final int threadnum){
        if (!ind.evaluated) // don't bother reevaluating{
            int hits = 0;
            double sum = 0.0;
            double expectedResult;
            double result;
            try{
                PrintWriter writer = new PrintWriter(new PrintWriter(new FileWriter("myOutput", true)));
                writer.write("\n ============================= \n");

                for (int y=0;y<10;y++){
                currentX = state.random[threadnum].nextDouble();
                currentY = state.random[threadnum].nextDouble();
                expectedResult = currentX*currentX*currentY + currentX*currentY + currentY;
                ((GPIndividual)ind).trees[0].child.eval(
                state,threadnum,input,stack,((GPIndividual)ind),this);
                result = Math.abs(expectedResult - input.x);
                if (result <= 0.01) hits++;
                sum += result;
                }
                // the fitness better be KozaFitness!
                KozaFitness f = ((KozaFitness)ind.fitness);
                f.setStandardizedFitness(state,(float)sum);
                f.hits = hits;
                ind.evaluated = true;
                ind.printIndividual(state, writer); // print the detail of the individual
                writer.close();
            } catch (Exception e){System.err.println ("Error writing to file");}

        }
    }
}

 

Project (a light Python API) pySTEP: Python Strongly Typed gEnetic Programming

A functional version of the pySTEP distribution is now available.

See the pySTEP website :)

Problem: Lack of simplicity and flexibility of existing Genetic Programming APIs when using Strongly-Typed and Grammar based structures.

The goal is: create a simple and flexible Strongly-Typed Genetic Programming API using a simple and flexible programming language : Python.

The goal is NOT : a super-optimized, hyper-performant marvel of software engineering that computes huge populations using obfuscated code. We will be happy to play with relatively small populations of let say 10000 individuals maximum. What we want is not raw power, but rather control on how we investigate the search space by establishing elaborate constraints and structures defining the shapes of the trees generated.

This would be a package that allows you to evolve any kind of weird graph, object, hierachical and complex composite structure in general, given this thing can be encoded inside a tree structure.

In Python, the following tree could be represented by a nested list:

Python Nested List

Nested list representation(Assumption: First element of a list or a nested list is always a head node) :

individual = ['A', ['B', ['D', 'H', 'I'], 'E'], ['C','F', 'G']]

This simple representation is the starting point of the project.

 

.Note: ECJ code might be outdated as the last time I had a look on ECJ was in mid 2007...