package jcgp; import java.util.Random; import jcgp.ea.EvolutionaryAlgorithm; import jcgp.ea.StandardEA; import jcgp.ea.StandardMutator; import jcgp.fitness.FitnessFunction; import jcgp.fitness.TestFitFunction; import jcgp.function.Addition; import jcgp.function.Function; import jcgp.function.FunctionSet; import jcgp.function.Subtraction; import jcgp.population.*; public final class CGP { public static class Parameters { private static int rows, columns, inputs, outputs, mutationRate, generations, runs, populationSize, levelsBack; /** * @return the number of nodes */ public static int getNodeNumber() { return rows * columns; } /** * @return the levelsBack */ public static int getLevelsBack() { return levelsBack; } /** * @param levelsBack the levelsBack to set */ private static void setLevelsBack(int levelsBack) { Parameters.levelsBack = levelsBack; } /** * @return the populationSize */ public static int getPopulationSize() { return populationSize; } /** * @param populationSize the populationSize to set */ private static void setPopulationSize(int populationSize) { Parameters.populationSize = populationSize; } /** * @return the rows */ public static int getRows() { return rows; } /** * @return the columns */ public static int getColumns() { return columns; } /** * @return the inputs */ public static int getInputs() { return inputs; } /** * @return the outputs */ public static int getOutputs() { return outputs; } /** * @return the mutationRate */ public static int getMutationRate() { return mutationRate; } /** * @return the generations */ public static int getGenerations() { return generations; } /** * @return the runs */ public static int getRuns() { return runs; } /** * @param rows the rows to set */ private static void setRows(int rows) { Parameters.rows = rows; } /** * @param columns the columns to set */ private static void setColumns(int columns) { Parameters.columns = columns; } /** * @param inputs the inputs to set */ private static void setInputs(int inputs) { Parameters.inputs = inputs; } /** * @param outputs the outputs to set */ private static void setOutputs(int outputs) { Parameters.outputs = outputs; } /** * @param mutationRate the mutationRate to set */ private static void setMutationRate(int mutationRate) { Parameters.mutationRate = mutationRate; } /** * @param generations the generations to set */ private static void setGenerations(int generations) { Parameters.generations = generations; } /** * @param runs the runs to set */ private static void setRuns(int runs) { Parameters.runs = runs; } } public static class Utilities { public static int getRandomInt(int limit){ return numberGenerator.nextInt(limit); } public static double getRandomDouble(int limit){ return numberGenerator.nextDouble() * limit; } /** * Returns a random allowed connection respecting levels back. * This method may always pick inputs, as they can be picked * regardless of the column. * * @param chromosome the chromosome to pick from * @param column the column to use as reference * @return a random connection */ public static Connection getRandomConnection(Chromosome chromosome, int column){ // work out the allowed range obeying levels back int allowedColumns = ((column >= Parameters.getLevelsBack()) ? Parameters.getLevelsBack() : column); int offset = column - allowedColumns; // choose input or node int connectionType = getRandomInt(Parameters.getInputs() + (Parameters.getRows() * allowedColumns)); if (connectionType < Parameters.getInputs()) { // input return chromosome.getInput(getRandomInt(Parameters.getInputs())); } else { // node return chromosome.getNode(getRandomInt(Parameters.getRows()), getRandomInt(allowedColumns) + offset); } } /** * Returns a random allowed connection. * * This method may always pick inputs, as they can be picked * regardless of the column. * * @param chromosome the chromosome to pick from * @param column the column to use as reference * @param levelsBack whether or not to respect levels back * @return a random connection */ public static Connection getRandomConnection(Chromosome chromosome, int column, boolean levelsBack){ if (levelsBack) { return getRandomConnection(chromosome, column); } else { // choose input or node int connectionType = getRandomInt(Parameters.getInputs() + (Parameters.getRows() * column)); if (connectionType < Parameters.getInputs()) { // input return chromosome.getInput(getRandomInt(Parameters.getInputs())); } else { // node return chromosome.getNode(getRandomInt(Parameters.getRows()), getRandomInt(column)); } } } /** * @param chromosome the chromosome to choose from * @return a random input */ public static Input getRandomInput(Chromosome chromosome){ return chromosome.getInput(getRandomInt(Parameters.getInputs())); } /** * Returns a random allowed node respecting levels back. * * This method will NOT pick inputs. * * @param chromosome the chromosome to pick from * @param column the column to use as reference * @return a random node */ public static Node getRandomNode(Chromosome chromosome, int column){ // work out the allowed range obeying levels back int allowedColumns = ((column >= Parameters.getLevelsBack()) ? Parameters.getLevelsBack() : column); int offset = column - allowedColumns; // pick a random allowed column and row int randomColumn = (getRandomInt(allowedColumns) + offset); int randomRow = (getRandomInt(Parameters.getRows())); return chromosome.getNode(randomRow, randomColumn); } /** * Returns a random allowed node. * * This method will NOT pick inputs. * * @param chromosome the chromosome to pick from * @param column the column to use as reference * @param levelsBack whether or not to respect levels back * @return a random node */ public static Node getRandomNode(Chromosome chromosome, int column, boolean levelsBack){ if (levelsBack) { return getRandomNode(chromosome, column); } else { // pick any random column before the given column int randomColumn = (getRandomInt(column)); // pick a random rowgetColumns int randomRow = (getRandomInt(Parameters.getRows())); return chromosome.getNode(randomRow, randomColumn); } } /** * This method picks a random mutable element from the given chromosome. * * It will pick outputs or nodes fairly. * * @param chromosome the chromosome to pick from * @return a random mutable element */ public static MutableElement getRandomMutable(Chromosome chromosome){ // choose output or node int connectionType = getRandomInt(Parameters.getOutputs() + Parameters.getNodeNumber()); if (connectionType < Parameters.getOutputs()) { // outputs return chromosome.getOutput(getRandomInt(Parameters.getOutputs())); } else { // node return chromosome.getNode(getRandomInt(Parameters.getRows()), getRandomInt(Parameters.getRows())); } } /** * pick from any column - use this for setting outputs * * @param chromosome * @return */ public static Node getRandomNode(Chromosome chromosome) { return chromosome.getNode(getRandomInt(Parameters.getRows()), getRandomInt(Parameters.getColumns())); } public static Function getRandomFunction() { return functionSet.getFunction(Utilities.getRandomInt(functionSet.getFunctionCount())); } public static Function getFunction(int index) { return functionSet.getFunction(index); } public static int getMaxArity() { return maxArity; } } // system-wide resources private static FunctionSet functionSet; private static Random numberGenerator; private static int maxArity = 0; // private FitnessFunction fitnessFunction; private EvolutionaryAlgorithm ea; private Population population; public CGP() { initialise(); fitnessFunction.evaluatePopulation(population); ea.evolve(population); } /** * */ private void initialise() { // initialise random number generator numberGenerator = new Random(1234); // initialise parameters Parameters.setInputs(3); Parameters.setColumns(3); Parameters.setRows(3); Parameters.setOutputs(3); Parameters.setGenerations(10); Parameters.setMutationRate(1); Parameters.setRuns(5); Parameters.setPopulationSize(5); Parameters.setLevelsBack(1); // initialise function set functionSet = new FunctionSet(new Addition(), new Subtraction()); // compute and set maximum arity maxArity = functionSet.getMaxArity(); // initialise EA ea = new StandardEA(new StandardMutator()); // initialise fitness function fitnessFunction = new TestFitFunction(); // initialise population population = new Population(); } }