package jcgp; import java.io.File; import jcgp.backend.modules.es.EvolutionaryStrategy; import jcgp.backend.modules.es.MuPlusLambda; import jcgp.backend.modules.es.TournamentSelection; import jcgp.backend.modules.mutator.Mutator; import jcgp.backend.modules.mutator.PointMutator; import jcgp.backend.modules.problem.DigitalCircuitProblem; import jcgp.backend.modules.problem.Problem; import jcgp.backend.modules.problem.SymbolicRegressionProblem; import jcgp.backend.modules.problem.TestCaseProblem; import jcgp.backend.parsers.ChromosomeParser; import jcgp.backend.parsers.FunctionParser; import jcgp.backend.parsers.ParameterParser; import jcgp.backend.parsers.TestCaseParser; import jcgp.backend.population.Population; import jcgp.backend.resources.Console; import jcgp.backend.resources.ModifiableResources; import jcgp.backend.resources.Resources; /** * * Top-level CGP class. This class is the entry point for a CGP experiment. *
* An instance of JCGP encapsulates the entire experiment. It contains a Resources * object which can be retrieved via a getter. Modules can be selected using their * respective setters and function sets can be selected through the resources. * * The flow of the experiment is controlled using start() and nextGeneration(). The * experiment can be reset with reset(), TODO comment * * * @author Eduardo Pedroni * @see Resources, Module, FunctionSet */ public class JCGP { // make resources private final ModifiableResources resources = new ModifiableResources(); /* * The following arrays contain all available modules. These collections are read by the GUI * when generating menus, so modules not added here will *NOT* be selectable in the GUI. * * Each array is accompanied by a field which contains a reference to the currently selected * module, 0 by default. */ // mutators private Mutator[] mutators = new Mutator[] { new PointMutator(resources) }; private Mutator mutator = mutators[0]; // evolutionary algorithms private EvolutionaryStrategy[] evolutionaryStrategies = new EvolutionaryStrategy[] { new MuPlusLambda(resources), new TournamentSelection(resources) }; private EvolutionaryStrategy evolutionaryStrategy = evolutionaryStrategies[0]; // problem types private Problem[] problems = new Problem[] { new SymbolicRegressionProblem(resources), new DigitalCircuitProblem(resources) }; private Problem problem = problems[0]; /* * the population of chromosomes */ private Population population; private boolean finished = false; /** * TODO comment this! * * @param args */ public static void main(String... args) { if (args.length < 1) { System.err.println("JCGP requires at least a .par file."); System.exit(1); } JCGP jcgp = new JCGP(); jcgp.loadParameters(new File(args[0])); if (jcgp.getProblem() instanceof TestCaseProblem) { TestCaseParser.parse(new File(args[2]), (TestCaseProblem) jcgp.getProblem(), jcgp.getResources()); } jcgp.start(); } public JCGP() { resources.setFunctionSet(problem.getFunctionSet()); population = new Population(resources); } public ModifiableResources getResources() { return resources; } public Population getPopulation() { return population; } /** * @return the mutators */ public Mutator[] getMutators() { return mutators; } /** * @return the mutator */ public Mutator getMutator() { return mutator; } /** * @return the evolutionaryAlgorithms */ public EvolutionaryStrategy[] getEvolutionaryStrategies() { return evolutionaryStrategies; } /** * @return the evolutionaryAlgorithm */ public EvolutionaryStrategy getEvolutionaryStrategy() { return evolutionaryStrategy; } /** * @return the fitnessFunctions */ public Problem[] getProblems() { return problems; } /** * @return the fitnessFunction */ public Problem getProblem() { return problem; } /** * @param mutator the mutator to set */ public void setMutator(int index) { this.mutator = mutators[index]; resources.println("[CGP] Mutator selected: " + mutator.toString()); } /** * @param evolutionaryStrategy the evolutionaryAlgorithm to set */ public void setEvolutionaryStrategy(int index) { this.evolutionaryStrategy = evolutionaryStrategies[index]; resources.println("[CGP] Evolutionary strategy selected: " + evolutionaryStrategy.toString()); } /** * @param problem the fitnessFunction to set */ public void setProblem(int index) { this.problem = problems[index]; resources.setFunctionSet(problem.getFunctionSet()); } public void nextGeneration() { System.out.println("service: doing next gen"); if (!finished) { problem.evaluate(population, (Resources) resources); reportGeneration(); if (resources.currentGeneration() < resources.generations()) { // we still have generations left to go if (problem.isPerfectSolution(population.getFittest())) { // solution has been found, start next run resources.println("[CGP] Solution found, generation " + resources.currentGeneration() + ", chromosome " + population.getFittestIndex()); if (resources.currentRun() < resources.runs()) { // there are still runs left resources.setCurrentRun(resources.currentRun() + 1); resources.setCurrentGeneration(0); // start a new population population.reinitialise(); } else { // no more generations and no more runs, we're done finished = true; } } else { resources.setCurrentGeneration(resources.currentGeneration() + 1); // solution isn't perfect and we still have generations left, evolve more! evolutionaryStrategy.evolve(population, mutator, (Resources) resources); } } else { // the run has ended, check if any more runs must be done resources.println("[CGP] Solution not found, highest fitness achieved was " + population.getFittest().getFitness() + " by chromosome " + population.getFittestIndex()); if (resources.currentRun() < resources.runs()) { // the run has ended but there are still runs left resources.setCurrentRun(resources.currentRun() + 1); resources.setCurrentGeneration(0); // start a new population population.reinitialise(); } else { // no more generations and no more runs, we're done finished = true; } } } } private void reportGeneration() { resources.reportln("[CGP] Generation: " + resources.currentGeneration() + ", fittest chromosome (" + population.getFittestIndex() + ") has fitness: " + population.getFittest().getFitness()); } public void start() { if (!finished) { while (!finished) { nextGeneration(); } } } public void reset() { finished = false; population = new Population(resources); resources.setCurrentGeneration(1); resources.setCurrentRun(1); resources.println("*********************************************************"); resources.println("[CGP] New experiment: " + problem.toString()); resources.println("[CGP] Rows: " + resources.rows()); resources.println("[CGP] Columns: " + resources.columns()); resources.println("[CGP] Levels back: " + resources.levelsBack()); resources.println("[CGP] Population size: " + resources.populationSize()); resources.println("[CGP] Total generations: " + resources.generations()); resources.println("[CGP] Total runs: " + resources.runs()); resources.println("[CGP] Report interval: " + resources.reportInterval()); resources.println("[CGP] Seed: " + resources.seed()); resources.println(""); resources.println("[CGP] Evolutionary strategy: " + evolutionaryStrategy.toString()); resources.println("[CGP] Mutator: " + mutator.toString()); } public void loadParameters(File file) { ParameterParser.parseParameters(file, resources); FunctionParser.parseFunctions(file, problem, resources); reset(); } public void loadTestCases(File file) { if (problem instanceof TestCaseProblem) { TestCaseParser.parseParameters(file, resources); reset(); TestCaseParser.parse(file, (TestCaseProblem) problem, resources); } } public void loadChromosome(File file, int chromosomeIndex) { ChromosomeParser.parse(file, population.getChromosome(chromosomeIndex), resources); } public void saveChromosome(File file, int chromosomeIndex) { ChromosomeParser.save(file, population.getChromosome(chromosomeIndex), resources); } public boolean isFinished() { return finished; } public void setConsole(Console console) { resources.setConsole(console); } }