aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp/JCGP.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/jcgp/JCGP.java')
-rw-r--r--src/jcgp/JCGP.java400
1 files changed, 30 insertions, 370 deletions
diff --git a/src/jcgp/JCGP.java b/src/jcgp/JCGP.java
index 962ddec..2c7023e 100644
--- a/src/jcgp/JCGP.java
+++ b/src/jcgp/JCGP.java
@@ -1,375 +1,36 @@
package jcgp;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map.Entry;
-import java.util.Random;
-
-import javafx.beans.property.SimpleIntegerProperty;
-import javafx.beans.value.ChangeListener;
-import javafx.beans.value.ObservableValue;
-import jcgp.backend.function.Arithmetic;
-import jcgp.backend.function.BitwiseLogic;
-import jcgp.backend.function.BooleanLogic;
-import jcgp.backend.function.Function;
-import jcgp.backend.function.FunctionSet;
import jcgp.backend.modules.ea.EvolutionaryAlgorithm;
import jcgp.backend.modules.ea.MuPlusLambda;
import jcgp.backend.modules.ea.TournamentSelection;
import jcgp.backend.modules.fitness.FitnessFunction;
-import jcgp.backend.modules.fitness.TestCase;
-import jcgp.backend.modules.fitness.TestCaseEvaluator;
+import jcgp.backend.modules.fitness.testcase.TestCaseEvaluator.TestCase;
import jcgp.backend.modules.mutator.Mutator;
import jcgp.backend.modules.mutator.PointMutator;
-import jcgp.backend.parameters.BooleanParameter;
-import jcgp.backend.parameters.DoubleParameter;
-import jcgp.backend.parameters.IntegerParameter;
-import jcgp.backend.parameters.Parameter;
-import jcgp.backend.parameters.ParameterStatus;
import jcgp.backend.population.Population;
-import jcgp.gui.console.Console;
+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.
+ * <p>
+ * 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(),
+ *
+ *
* @author Eduardo Pedroni
- *
+ * @see Resources, Module, FunctionSet
*/
public class JCGP {
-
- /**
- *
- * The resources class encapsulates all of the resources based on which the program operates.
- * Each instance of JCGP contains a single instance of Resources, which gets passed to the selected
- * modules as the program executes.
- *
- * @author Eduardo Pedroni
- *
- */
- public static class Resources {
- private HashMap<String, Parameter> parameters = new HashMap<String, Parameter>();
-
- private Random numberGenerator;
-
- private TestCase[] testCases;
-
- // function sets
- private FunctionSet[] functionSets = new FunctionSet[] {
- new Arithmetic(),
- new BitwiseLogic(),
- new BooleanLogic() };
- private FunctionSet functionSet = functionSets[0];
-
- // GUI console
- private Console console;
-
- public Resources() {
- createBaseParameters();
-
- numberGenerator = new Random(getInt("seed"));
- set("arity", functionSet.getMaxArity());
- }
-
- public int getInt(String key) {
- if (parameters.get(key) instanceof IntegerParameter) {
- return ((IntegerParameter) parameters.get(key)).get();
- } else if (parameters.get(key) instanceof DoubleParameter) {
- return (int) ((DoubleParameter) parameters.get(key)).get();
- } else {
- throw new ClassCastException("Could not cast " + parameters.get(key).getClass() + " to int.");
- }
- }
-
- public double getDouble(String key) {
- if (parameters.get(key) instanceof IntegerParameter) {
- return (double) ((IntegerParameter) parameters.get(key)).get();
- } else if (parameters.get(key) instanceof DoubleParameter) {
- return ((DoubleParameter) parameters.get(key)).get();
- } else {
- throw new ClassCastException("Could not cast " + parameters.get(key).getClass() + " to double.");
- }
- }
-
- public boolean getBoolean(String key) {
- if (parameters.get(key) instanceof BooleanParameter) {
- return ((BooleanParameter) parameters.get(key)).get();
- } else {
- throw new ClassCastException("Could not cast " + parameters.get(key).getClass() + " to int.");
- }
- }
-
- public void set(String key, Object value) {
- if (parameters.get(key) instanceof IntegerParameter) {
- ((IntegerParameter) parameters.get(key)).set(((Integer) value).intValue());
- } else if (parameters.get(key) instanceof DoubleParameter) {
- ((DoubleParameter) parameters.get(key)).set(((Double) value).doubleValue());
- } else if (parameters.get(key) instanceof BooleanParameter) {
- ((BooleanParameter) parameters.get(key)).set(((Boolean) value).booleanValue());
- }
- }
-
- public Parameter getParameter(String key) {
- return parameters.get(key);
- }
-
- public boolean contains(String key) {
- return parameters.containsKey(key);
- }
-
- private void createBaseParameters() {
- parameters.put("rows", new IntegerParameter(8, "Rows", false, true) {
- @Override
- public void validate(int newValue) {
- if (newValue <= 0) {
- status = ParameterStatus.INVALID;
- status.setDetails("Chromosome must have at least 1 row.");
- } else {
- status = ParameterStatus.VALID;
- }
- }
- });
- parameters.put("columns", new IntegerParameter(9, "Columns", false, true) {
- @Override
- public void validate(int newValue) {
- if (newValue <= 0) {
- status = ParameterStatus.INVALID;
- status.setDetails("Chromosome must have at least 1 column.");
- } else {
- status = ParameterStatus.VALID;
- }
- }
- });
- parameters.put("inputs", new IntegerParameter(3, "Inputs", false, true) {
- @Override
- public void validate(int newValue) {
- if (newValue <= 0) {
- status = ParameterStatus.INVALID;
- status.setDetails("Chromosome must have at least 1 input.");
- } else {
- status = ParameterStatus.VALID;
- }
- }
- });
- parameters.put("outputs", new IntegerParameter(3, "Outputs", false, true) {
- @Override
- public void validate(int newValue) {
- if (newValue <= 0) {
- status = ParameterStatus.INVALID;
- status.setDetails("Chromosome must have at least 1 output.");
- } else {
- status = ParameterStatus.VALID;
- }
- }
- });
- parameters.put("popSize", new IntegerParameter(5, "Population", false, true) {
- @Override
- public void validate(int newValue) {
- if (newValue <= 0) {
- status = ParameterStatus.INVALID;
- status.setDetails("Population size must be at least 1.");
- } else {
- status = ParameterStatus.VALID;
- }
- }
- });
- parameters.put("levelsBack", new IntegerParameter(2, "Levels back", false, true) {
- @Override
- public void validate(int newValue) {
- if (newValue <= 0) {
- status = ParameterStatus.INVALID;
- status.setDetails("Levels back must be at least 1.");
- } else if (newValue > getInt("columns")) {
- status = ParameterStatus.INVALID;
- status.setDetails("Levels back must be less than or equal to the number of columns.");
- } else {
- status = ParameterStatus.VALID;
- }
- }
- });
-
- IntegerParameter nodes = new IntegerParameter(1, "Nodes", true, false) {
- @Override
- public void validate(int newValue) {
- // blank
- }
- };
- nodes.valueProperty().bind(((SimpleIntegerProperty) ((IntegerParameter) parameters.get("rows")).valueProperty()).multiply((SimpleIntegerProperty) ((IntegerParameter) parameters.get("columns")).valueProperty()));
- parameters.put("nodes", nodes);
-
- parameters.put("generations", new IntegerParameter(1000000, "Generations") {
- @Override
- public void validate(int newValue) {
- if (newValue <= 0) {
- status = ParameterStatus.INVALID;
- status.setDetails("Number of generations must be greater than 0.");
- } else if (newValue < getInt("currentGen")) {
- status = ParameterStatus.WARNING_RESET;
- status.setDetails("Setting generations to less than the current generation will cause the experiment to restart.");
- } else {
- status = ParameterStatus.VALID;
- }
- }
- });
- parameters.put("currentGen", new IntegerParameter(1, "Generation", true, false) {
- @Override
- public void validate(int newValue) {
- // blank
- }
- });
-
- parameters.put("runs", new IntegerParameter(5, "Runs") {
- @Override
- public void validate(int newValue) {
- if (newValue <= 0) {
- status = ParameterStatus.INVALID;
- status.setDetails("Number of runs must be greater than 0.");
- } else if (newValue < getInt("currentRun")) {
- status = ParameterStatus.WARNING_RESET;
- status.setDetails("Setting runs to less than the current run will cause the experiment to restart.");
- } else {
- status = ParameterStatus.VALID;
- }
- }
- });
- parameters.put("currentRun", new IntegerParameter(1, "Run", true, false) {
- @Override
- public void validate(int newValue) {
- // blank
- }
- });
-
- parameters.put("arity", new IntegerParameter(0, "Max arity", true, false) {
- @Override
- public void validate(int newValue) {
- // blank
- }
- });
- parameters.put("maxFitness", new IntegerParameter(3, "Max fitness", true, true) {
- @Override
- public void validate(int newValue) {
- // blank
- }
- });
-
- IntegerParameter seed = new IntegerParameter(123, "Seed", false, true) {
- @Override
- public void validate(int newValue) {
- status = ParameterStatus.VALID;
- }
- };
- seed.valueProperty().addListener(new ChangeListener<Number>() {
- @Override
- public void changed(
- ObservableValue<? extends Number> observable,
- Number oldValue, Number newValue) {
- numberGenerator.setSeed(newValue.longValue());
- }
- });
- parameters.put("seed", seed);
-
- parameters.put("report", new IntegerParameter(1, "Report", false, false) {
- @Override
- public void validate(int newValue) {
- if (newValue > getInt("generations")) {
- status = ParameterStatus.WARNING;
- status.setDetails("No reports will be printed.");
- } else {
- status = ParameterStatus.VALID;
- }
- }
- });
- }
-
- /**
- *
- *
- * @return the iterator for the set of base parameters
- */
- public Iterator<Entry<String, Parameter>> iterator() {
- return parameters.entrySet().iterator();
- }
-
- /*
- * Utility functions
- */
- public int getRandomInt(int limit) {
- return numberGenerator.nextInt(limit);
- }
-
- public double getRandomDouble(int limit) {
- return numberGenerator.nextDouble() * limit;
- }
-
- public double getRandomDouble() {
- return numberGenerator.nextDouble();
- }
-
- /*
- * FunctionSet functions
- */
- public Function getRandomFunction() {
- Function f = functionSet.getAllowedFunction(numberGenerator.nextInt(functionSet.getAllowedFunctionCount()));
- return f;
- }
-
- public Function getFunction(int index) {
- return functionSet.getAllowedFunction(index);
- }
-
- public void setFunctionSet(int index) {
- functionSet = functionSets[index];
- }
-
- /**
- * @return the functionSets
- */
- public FunctionSet[] getFunctionSets() {
- return functionSets;
- }
-
- /**
- * @return the functionSet
- */
- public FunctionSet getFunctionSet() {
- return functionSet;
- }
-
- /*
- * Test cases
- */
- public void setTestCases(TestCase ... testCases) {
- this.testCases = testCases;
- }
-
- public TestCase getTestCase(int index) {
- return testCases[index];
- }
-
- public int getTestCaseCount() {
- return testCases.length;
- }
- /*
- * Console functionality
- */
- public void setConsole(Console console) {
- this.console = console;
- }
-
- public void println(String s) {
- System.out.println(s);
- if (console != null) {
- console.println(s);
- }
- }
-
- public void print(String s) {
- System.out.print(s);
- if (console != null) {
- console.print(s);
- }
- }
- }
-
- private final Resources resources = new Resources();
+ // make resources
+ private final ModifiableResources resources = new ModifiableResources();
/*
* The following arrays contain all available modules. These collections are read by the GUI
@@ -380,7 +41,7 @@ public class JCGP {
*/
// mutators
private Mutator[] mutators = new Mutator[] {
- new PointMutator() };
+ new PointMutator(resources) };
private Mutator mutator;
// evolutionary algorithms
@@ -391,7 +52,7 @@ public class JCGP {
// fitness evaluators
private FitnessFunction[] fitnessFunctions = new FitnessFunction[] {
- new TestCaseEvaluator() };
+ /*new TestCaseEvaluator()*/ };
private FitnessFunction fitnessFunction;
/*
@@ -401,7 +62,6 @@ public class JCGP {
private boolean finished = false;
-
public JCGP() {
population = new Population(resources);
@@ -411,20 +71,17 @@ public class JCGP {
mutator = mutators[0];
fitnessFunction = fitnessFunctions[0];
-
- resources.setTestCases(new TestCase(new Integer[]{1, 2, 3}, new Integer[]{-4, 5, 6}));
}
- public Resources getResources() {
+ public ModifiableResources getResources() {
return resources;
}
-
+
public Population getPopulation() {
return population;
}
-
/**
* @return the mutators
*/
@@ -498,7 +155,7 @@ public class JCGP {
public void nextGeneration() {
if (!finished) {
- fitnessFunction.evaluate(population, resources);
+ fitnessFunction.evaluate(population, (Resources) resources);
report();
@@ -506,7 +163,7 @@ public class JCGP {
// we still have generations left to go
if (population.getChromosome(evolutionaryAlgorithm.getFittestChromosome()).getFitness() >= resources.getInt("maxFitness")) {
// solution has been found, start next run
- resources.println("Solution found in generation " + resources.getInt("currentGen") + ", chromosome: " + evolutionaryAlgorithm.getFittestChromosome());
+ resources.println("Solution found on generation " + resources.getInt("currentGen") + ", chromosome: " + evolutionaryAlgorithm.getFittestChromosome());
if (resources.getInt("currentRun") < resources.getInt("runs")) {
// there are still runs left
@@ -514,7 +171,7 @@ public class JCGP {
resources.set("currentGen", 0);
// start a new population
- population = new Population(resources);
+ population = new Population((Resources) resources);
} else {
// no more generations and no more runs, we're done
finished = true;
@@ -543,7 +200,7 @@ public class JCGP {
}
}
- evolutionaryAlgorithm.evolve(population, mutator, resources);
+ evolutionaryAlgorithm.evolve(population, mutator, (Resources) resources);
}
@@ -553,7 +210,6 @@ public class JCGP {
resources.println("Generation: " + resources.getInt("currentGen") + ", fitness: " + population.getChromosome(evolutionaryAlgorithm.getFittestChromosome()).getFitness());
}
}
-
}
public void start() {
@@ -581,4 +237,8 @@ public class JCGP {
return finished;
}
+ public void setConsole(Console console) {
+ resources.setConsole(console);
+ }
+
}