I'm using a gene expression programming library demo to obtain alternative mathematical expressions. I downloaded all the class files for uncommons.watchmaker framework and created a new project that runs without jar files. Java Project (full source code) is attached here.
I have modified the demo a little bit to produce alternative mathematical expressions for a given number. For example let's say I want to get all the combinations of numbers between 2 - 11 which would multiply to give 12. I would get 6 * 2, 3 * 4, 3 * 2 * 2, 2 * 6, 4 * 3, 2 * 2 * 3. The main program is TestMainProg.java
I am interested in knowing how to print the population of the final generation.
Findings:
In the watchmaker API it says evolvePopulation() in EvolutionEngine interface can be used to get the final population data. However I am not sure how to invoke the method and print the data. Looking at the EvolutionEngine.java, EvaluatedCandidate.java and AbstractEvolutionEngine.java will be useful.
Below is the code I use:
import java.util.ArrayList;
import java.util.List;
import org.gep4j.GeneFactory;
import org.gep4j.INode;
import org.gep4j.INodeFactory;
import org.gep4j.IntegerConstantFactory;
import org.gep4j.KarvaEvaluator;
import org.gep4j.MutationOperator;
import org.gep4j.RecombinationOperator;
import org.gep4j.SimpleNodeFactory;
import org.gep4j.math.Multiply;
import org.uncommons.maths.random.MersenneTwisterRNG;
import org.uncommons.maths.random.Probability;
import org.uncommons.watchmaker.framework.EvolutionEngine;
import org.uncommons.watchmaker.framework.EvolutionObserver;
import org.uncommons.watchmaker.framework.EvolutionaryOperator;
import org.uncommons.watchmaker.framework.FitnessEvaluator;
import org.uncommons.watchmaker.framework.GenerationalEvolutionEngine;
import org.uncommons.watchmaker.framework.PopulationData;
import org.uncommons.watchmaker.framework.operators.EvolutionPipeline;
import org.uncommons.watchmaker.framework.selection.RouletteWheelSelection;
import org.uncommons.watchmaker.framework.termination.TargetFitness;
public class TestMainProg {
final KarvaEvaluator karvaEvaluator = new KarvaEvaluator();
public INode[] bestIndividual=null;
public void go() {
List<INodeFactory> factories = new ArrayList<INodeFactory>();
// init the GeneFactory that will create the individuals
//factories.add(new SimpleNodeFactory(new Add()));
factories.add(new SimpleNodeFactory(new Multiply()));
factories.add(new IntegerConstantFactory(2, 35)); //12,60,1 and the target number
double num = 36.0;
GeneFactory factory = new GeneFactory(factories, 20); //20 is the gene size
List<EvolutionaryOperator<INode[]>> operators = new ArrayList<EvolutionaryOperator<INode[]>>();
operators.add(new MutationOperator<INode[]>(factory, new Probability(0.01d)));
operators.add(new RecombinationOperator<INode[]>(factory, new Probability(0.5d)));
EvolutionaryOperator<INode[]> pipeline = new EvolutionPipeline<INode[]>(operators);
FitnessEvaluator<INode[]> evaluator = new FitnessEvaluator<INode[]>() {
@Override
public double getFitness(INode[] candidate, List<? extends INode[]> population) {
double result = (Double) karvaEvaluator.evaluate(candidate);
double error = Math.abs(num - result);
return error;
}
@Override
public boolean isNatural() {
return false;
}
};
EvolutionEngine<INode[]> engine = new GenerationalEvolutionEngine<INode[]>(factory, pipeline, evaluator,
new RouletteWheelSelection(), new MersenneTwisterRNG());
// add an EvolutionObserver so we can print out the status.
EvolutionObserver<INode[]> observer = new EvolutionObserver<INode[]>() {
@Override
public void populationUpdate(PopulationData<? extends INode[]> data) {
bestIndividual = data.getBestCandidate();
System.out.printf("Generation %d, PopulationSize = %d, error = %.1f, value = %.1f, %s\n",
data.getGenerationNumber(), data.getPopulationSize(),
Math.abs(/*Math.PI*/ num - (Double)karvaEvaluator.evaluate(bestIndividual)),
(Double)karvaEvaluator.evaluate(bestIndividual),
karvaEvaluator.print(bestIndividual));
}
};
engine.addEvolutionObserver(observer);
//to get the total population
engine.evolvePopulation(100,10,new TargetFitness(0.0001, false));
}
public static final void main(String args[]) {
new TestMainProg().go();
}
}
Printing all the correct candidates in the final population is simple:
Getting multiple two number combinations, however, is more tricky:
GeneFactory
with a gene length of 5 or above may produceA x B x C
, e.g. 2 x 2 x 9 = 36First point should be easy to fix. For the second, we can run the evolution a few times and consolidate the results. There is no guarantee you'll get all combinations, but the more you run the higher chance it will be.
My solution: