/* * This file is part of JGAP. * * JGAP offers a dual license model containing the LGPL as well as the MPL. * * For licensing information please see the file license.txt included with JGAP * or have a look at the top of class org.jgap.Chromosome which representatively * includes the JGAP license policy applicable for any file delivered with JGAP. */ package examples.gp; import org.jgap.*; import org.jgap.event.*; import org.jgap.gp.*; import org.jgap.gp.function.*; import org.jgap.gp.impl.*; import org.jgap.gp.terminal.*; import org.jgap.util.*; /** * Simple example of Genetic Programming to discover the formula * (X > 0) OR (X == -8) OR (X == - 5) * given a set of inputs from -10 to 10 and expected outputs (true or false). * * The fitness function used in this example cares about deviation from the * expected result as well as the complexity of the solution (the easier the * solution, the better it is, mutatis mutandis). * * @author Klaus Meffert * @since 3.5 */ public class SimpleExample extends GPProblem { protected static Variable vx; public GPGenotype create() throws InvalidConfigurationException { GPConfiguration conf = getGPConfiguration(); // The resulting GP program returns a boolean. // ------------------------------------------- Class[] types = {CommandGene.BooleanClass}; Class[][] argTypes = { {} }; // The commands and terminals allowed to find a solution. // ------------------------------------------------------ CommandGene[][] nodeSets = { { // We need a variable to feed in data (see fitness function). // ---------------------------------------------------------- vx = Variable.create(conf, "X", CommandGene.IntegerClass), // Define the terminals (here: numbers) to try: // Easiest: Define two constants // More challenging: Define a terminal that can be within -10 and 10 // new Constant(conf, CommandGene.IntegerClass, 0), // new Constant(conf, CommandGene.IntegerClass, -8), new Terminal(conf, CommandGene.IntegerClass,-10,10,true), // Boolean operators to use. // _------------------------ new GreaterThan(conf, CommandGene.IntegerClass), new Or(conf), new Equals(conf, CommandGene.IntegerClass), // Define complex operator. // ------------------------ new If(conf, CommandGene.BooleanClass), // Boolean terminals to use (they do not appear in an optimal solution // and make the task more challenging) --> Leave away if needed // ------------------------------------------------------------------- // new True(conf, CommandGene.BooleanClass), new False(conf, CommandGene.BooleanClass) } }; // Initialize the GPGenotype. // -------------------------- return GPGenotype.randomInitialGenotype(conf, types, argTypes, nodeSets, 100, true); } public void start() throws Exception { GPConfiguration config = new GPConfiguration(); config.setMaxInitDepth(5); config.setPopulationSize(80); config.setFitnessFunction(new SimpleFitnessFunction()); config.setStrictProgramCreation(false); config.setProgramCreationMaxTries(5); config.setMaxCrossoverDepth(5); // Lower fitness value is better as fitness value indicates error rate. // -------------------------------------------------------------------- config.setGPFitnessEvaluator(new DeltaGPFitnessEvaluator()); super.setGPConfiguration(config); GPGenotype geno = create(); // Simple implementation of running evolution in a thread. // ------------------------------------------------------- config.getEventManager().addEventListener(GeneticEvent. GPGENOTYPE_EVOLVED_EVENT, new GeneticEventListener() { public void geneticEventFired(GeneticEvent a_firedEvent) { GPGenotype genotype = (GPGenotype) a_firedEvent.getSource(); int evno = genotype.getGPConfiguration().getGenerationNr(); double freeMem = SystemKit.getFreeMemoryMB(); if (evno % 100 == 0) { IGPProgram best = genotype.getAllTimeBest(); System.out.println("Evolving generation " + evno); genotype.outputSolution(best); } if (evno > 3000) { System.exit(1); } } }); config.getEventManager().addEventListener(GeneticEvent. GPGENOTYPE_NEW_BEST_SOLUTION, new GeneticEventListener() { /** * New best solution found. * * @param a_firedEvent GeneticEvent */ public void geneticEventFired(GeneticEvent a_firedEvent) { GPGenotype genotype = (GPGenotype) a_firedEvent.getSource(); IGPProgram best = genotype.getAllTimeBest(); double bestFitness = genotype.getFittestProgram(). getFitnessValue(); if (bestFitness < 0.1) { // Quit, when the solutions seems perfect. // --------------------------------------- genotype.outputSolution(best); System.exit(0); } } }); geno.evolve(10000); } public static void main(String[] args) throws Exception { SimpleExample example = new SimpleExample(); example.start(); } class SimpleFitnessFunction extends GPFitnessFunction { protected double evaluate(final IGPProgram ind) { int error = 0; Object[] noargs = new Object[0]; int maxDepth = ind.getChromosome(0).getDepth(0); if (maxDepth > 2) { error += maxDepth - 2; } for (int i = -10; i < 10; i++) { vx.set(new Integer(i)); boolean y; if (i > 0) { y = true; } else { if (i != -8 && i != - 5) { y = false; } else { y = true; } } try { boolean result = ind.execute_boolean(0, noargs); if (result != y) { error += 10; } } catch (ArithmeticException ex) { // some illegal operation was executed. System.out.println("x = " + i); System.out.println(ind); throw ex; } } return error; } } }