diff options
-rw-r--r-- | src/jcgp/JCGP.java | 170 | ||||
-rw-r--r-- | src/jcgp/backend/exceptions/InsufficientConnectionsException.java (renamed from src/jcgp/exceptions/InsufficientConnectionsException.java) | 2 | ||||
-rw-r--r-- | src/jcgp/backend/exceptions/InvalidArgumentsException.java (renamed from src/jcgp/exceptions/InvalidArgumentsException.java) | 2 | ||||
-rw-r--r-- | src/jcgp/backend/exceptions/ManagedModuleException.java (renamed from src/jcgp/exceptions/ManagedModuleException.java) | 2 | ||||
-rw-r--r-- | src/jcgp/backend/exceptions/ParameterMismatchException.java (renamed from src/jcgp/exceptions/ParameterMismatchException.java) | 2 | ||||
-rw-r--r-- | src/jcgp/backend/function/Arithmetic.java (renamed from src/jcgp/function/Arithmetic.java) | 6 | ||||
-rw-r--r-- | src/jcgp/backend/function/BitwiseLogic.java (renamed from src/jcgp/function/BitwiseLogic.java) | 6 | ||||
-rw-r--r-- | src/jcgp/backend/function/BooleanLogic.java (renamed from src/jcgp/function/BooleanLogic.java) | 6 | ||||
-rw-r--r-- | src/jcgp/backend/function/Function.java (renamed from src/jcgp/function/Function.java) | 6 | ||||
-rw-r--r-- | src/jcgp/backend/function/FunctionSet.java (renamed from src/jcgp/function/FunctionSet.java) | 2 | ||||
-rw-r--r-- | src/jcgp/backend/modules/Module.java (renamed from src/jcgp/modules/Module.java) | 4 | ||||
-rw-r--r-- | src/jcgp/backend/modules/ModuleStatus.java (renamed from src/jcgp/modules/ModuleStatus.java) | 2 | ||||
-rw-r--r-- | src/jcgp/backend/modules/ea/EvolutionaryAlgorithm.java (renamed from src/jcgp/modules/ea/EvolutionaryAlgorithm.java) | 10 | ||||
-rw-r--r-- | src/jcgp/backend/modules/ea/MuPlusLambda.java (renamed from src/jcgp/modules/ea/MuPlusLambda.java) | 14 | ||||
-rw-r--r-- | src/jcgp/backend/modules/ea/TournamentSelection.java (renamed from src/jcgp/modules/ea/TournamentSelection.java) | 19 | ||||
-rw-r--r-- | src/jcgp/backend/modules/fitness/FitnessFunction.java (renamed from src/jcgp/modules/fitness/FitnessFunction.java) | 6 | ||||
-rw-r--r-- | src/jcgp/backend/modules/fitness/TestCase.java (renamed from src/jcgp/modules/fitness/TestCase.java) | 2 | ||||
-rw-r--r-- | src/jcgp/backend/modules/fitness/TestCaseEvaluator.java (renamed from src/jcgp/modules/fitness/TestCaseEvaluator.java) | 8 | ||||
-rw-r--r-- | src/jcgp/backend/modules/mutator/Mutator.java (renamed from src/jcgp/modules/mutator/Mutator.java) | 6 | ||||
-rw-r--r-- | src/jcgp/backend/modules/mutator/PointMutator.java (renamed from src/jcgp/modules/mutator/PointMutator.java) | 22 | ||||
-rw-r--r-- | src/jcgp/backend/parameters/BooleanParameter.java (renamed from src/jcgp/parameters/BooleanParameter.java) | 8 | ||||
-rw-r--r-- | src/jcgp/backend/parameters/DoubleParameter.java (renamed from src/jcgp/parameters/DoubleParameter.java) | 8 | ||||
-rw-r--r-- | src/jcgp/backend/parameters/IntegerParameter.java (renamed from src/jcgp/parameters/IntegerParameter.java) | 8 | ||||
-rw-r--r-- | src/jcgp/backend/parameters/Parameter.java | 35 | ||||
-rw-r--r-- | src/jcgp/backend/population/Chromosome.java (renamed from src/jcgp/population/Chromosome.java) | 4 | ||||
-rw-r--r-- | src/jcgp/backend/population/Connection.java (renamed from src/jcgp/population/Connection.java) | 2 | ||||
-rw-r--r-- | src/jcgp/backend/population/Gene.java (renamed from src/jcgp/population/Gene.java) | 2 | ||||
-rw-r--r-- | src/jcgp/backend/population/Input.java (renamed from src/jcgp/population/Input.java) | 2 | ||||
-rw-r--r-- | src/jcgp/backend/population/MutableElement.java (renamed from src/jcgp/population/MutableElement.java) | 2 | ||||
-rw-r--r-- | src/jcgp/backend/population/Node.java (renamed from src/jcgp/population/Node.java) | 8 | ||||
-rw-r--r-- | src/jcgp/backend/population/Output.java (renamed from src/jcgp/population/Output.java) | 2 | ||||
-rw-r--r-- | src/jcgp/backend/population/Population.java (renamed from src/jcgp/population/Population.java) | 2 | ||||
-rw-r--r-- | src/jcgp/backend/tests/ChromosomeTests.java (renamed from src/jcgp/tests/ChromosomeTests.java) | 14 | ||||
-rw-r--r-- | src/jcgp/backend/tests/InputTests.java (renamed from src/jcgp/tests/InputTests.java) | 4 | ||||
-rw-r--r-- | src/jcgp/backend/tests/NodeTests.java (renamed from src/jcgp/tests/NodeTests.java) | 12 | ||||
-rw-r--r-- | src/jcgp/backend/tests/OutputTests.java (renamed from src/jcgp/tests/OutputTests.java) | 9 | ||||
-rw-r--r-- | src/jcgp/backend/tests/PopulationTests.java (renamed from src/jcgp/tests/PopulationTests.java) | 6 | ||||
-rw-r--r-- | src/jcgp/gui/ChromosomePane.java | 28 | ||||
-rw-r--r-- | src/jcgp/gui/GUI.java (renamed from src/jcgp/GUI.java) | 138 | ||||
-rw-r--r-- | src/jcgp/gui/Messenger.java | 7 | ||||
-rw-r--r-- | src/jcgp/gui/console/Console.java | 11 | ||||
-rw-r--r-- | src/jcgp/gui/console/GUIConsole.java | 22 | ||||
-rw-r--r-- | src/jcgp/gui/population/GUIGene.java | 6 | ||||
-rw-r--r-- | src/jcgp/gui/population/GUIInput.java | 10 | ||||
-rw-r--r-- | src/jcgp/gui/population/GUINode.java | 10 | ||||
-rw-r--r-- | src/jcgp/gui/population/GUIOutput.java | 27 | ||||
-rw-r--r-- | src/jcgp/gui/settings/SettingsPane.java | 116 | ||||
-rw-r--r-- | src/jcgp/gui/settings/parameters/GUIBooleanParameter.java | 34 | ||||
-rw-r--r-- | src/jcgp/gui/settings/parameters/GUIDoubleParameter.java | 39 | ||||
-rw-r--r-- | src/jcgp/gui/settings/parameters/GUIIntegerParameter.java | 36 | ||||
-rw-r--r-- | src/jcgp/gui/settings/parameters/GUIParameter.java | 56 | ||||
-rw-r--r-- | src/jcgp/parameters/Parameter.java | 30 |
52 files changed, 602 insertions, 393 deletions
diff --git a/src/jcgp/JCGP.java b/src/jcgp/JCGP.java index 807739f..7451d4f 100644 --- a/src/jcgp/JCGP.java +++ b/src/jcgp/JCGP.java @@ -6,24 +6,27 @@ import java.util.Map.Entry; import java.util.Random; import javafx.beans.property.SimpleIntegerProperty; -import jcgp.function.Arithmetic; -import jcgp.function.BitwiseLogic; -import jcgp.function.BooleanLogic; -import jcgp.function.Function; -import jcgp.function.FunctionSet; -import jcgp.modules.ea.EvolutionaryAlgorithm; -import jcgp.modules.ea.MuPlusLambda; -import jcgp.modules.ea.TournamentSelection; -import jcgp.modules.fitness.FitnessFunction; -import jcgp.modules.fitness.TestCase; -import jcgp.modules.fitness.TestCaseEvaluator; -import jcgp.modules.mutator.Mutator; -import jcgp.modules.mutator.PointMutator; -import jcgp.parameters.BooleanParameter; -import jcgp.parameters.DoubleParameter; -import jcgp.parameters.IntegerParameter; -import jcgp.parameters.Parameter; -import jcgp.population.Population; +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.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.population.Population; +import jcgp.gui.console.Console; /** * @author Eduardo Pedroni @@ -33,6 +36,9 @@ 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 * @@ -51,8 +57,11 @@ public class JCGP { new BooleanLogic() }; private FunctionSet functionSet = functionSets[0]; + // GUI console + private Console console; + public Resources() { - createCoreParameters(); + createBaseParameters(); numberGenerator = new Random(getInt("seed")); set("arity", functionSet.getMaxArity()); @@ -104,7 +113,7 @@ public class JCGP { return parameters.containsKey(key); } - private void createCoreParameters() { + private void createBaseParameters() { parameters.put("rows", new IntegerParameter(8, "Rows")); parameters.put("columns", new IntegerParameter(9, "Columns")); parameters.put("inputs", new IntegerParameter(3, "Inputs")); @@ -112,21 +121,73 @@ public class JCGP { parameters.put("popSize", new IntegerParameter(5, "Population")); parameters.put("levelsBack", new IntegerParameter(2, "Levels back")); - IntegerParameter nodes = new IntegerParameter(1, "Nodes", false, true); + IntegerParameter nodes = new IntegerParameter(1, "Nodes", true, true, false); 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")); - parameters.put("currentGen", new IntegerParameter(1, "Generation", false, false)); + parameters.put("currentGen", new IntegerParameter(1, "Generation", true, false, false)); parameters.put("runs", new IntegerParameter(5, "Runs")); - parameters.put("currentRun", new IntegerParameter(1, "Run", false, false)); + parameters.put("currentRun", new IntegerParameter(1, "Run", true, false, false)); - parameters.put("arity", new IntegerParameter(0, "Max arity", true, true)); - parameters.put("seed", new IntegerParameter(123, "Seed")); + parameters.put("arity", new IntegerParameter(0, "Max arity", false, true, false)); + + IntegerParameter seed = new IntegerParameter(123, "Seed"); + 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("verbose", new BooleanParameter(false, "Verbose")); - parameters.put("report", new IntegerParameter(1, "Report")); + parameters.put("report", new IntegerParameter(1, "Report", false, false, false)); + } + + private boolean validateBaseParameters() { + boolean valid = true; + + if (getInt("rows") <= 0) { + valid = false; + println("Error: number of rows must be greater than 0."); + } + if (getInt("columns") <= 0) { + valid = false; + println("Error: number of columns must be greater than 0."); + } + if (getInt("inputs") <= 0) { + valid = false; + println("Error: number of inputs must be greater than 0."); + } + if (getInt("outputs") <= 0) { + println("Error: number of outputs must be greater than 0."); + valid = false; + } + if (getInt("popSize") <= 0) { + println("Error: population size must be greater than 0."); + valid = false; + } + if (getInt("levelsBack") <= 0 || getInt("levelsBack") > getInt("columns")) { + println("Error: levels back must be greater than 0 and no greater than the number of columns."); + valid = false; + } + if (getInt("generations") <= 0) { + println("Error: number of generations must be greater than 0."); + valid = false; + } + if (getInt("runs") <= 0) { + println("Error: number of runs must be greater than 0."); + valid = false; + } + if (getInt("report") < 0) { + println("Error: report frequency must not be smaller than 0."); + valid = false; + } + + return valid; } /** @@ -157,7 +218,8 @@ public class JCGP { * FunctionSet functions */ public Function getRandomFunction() { - return functionSet.getAllowedFunction(numberGenerator.nextInt(functionSet.getAllowedFunctionCount())); + Function f = functionSet.getAllowedFunction(numberGenerator.nextInt(functionSet.getAllowedFunctionCount())); + return f; } public Function getFunction(int index) { @@ -196,7 +258,27 @@ public class JCGP { 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 Resources resources = new Resources(); @@ -242,21 +324,12 @@ public class JCGP { resources.setTestCases(new TestCase(new Integer[]{1, 2, 3}, new Integer[]{4, 5, 6}), new TestCase(new Integer[]{1, 12, 4}, new Integer[]{6, 21, 2})); -// for (int i = 0; i < (int) resources.get("generations"); i++) { -// -// resources.set("currentGen", ((int) resources.get("currentGen")) + 1); -// -// fitnessFunction.evaluate(population, resources); -// evolutionaryAlgorithm.evolve(population, mutator, resources); -// -// System.out.println("fitness: " + evolutionaryAlgorithm.getFittestChromosome().getFitness()); -// -// if (evolutionaryAlgorithm.getFittestChromosome().getFitness() >= 6) { -// System.out.println("solution found"); -// evolutionaryAlgorithm.getFittestChromosome().printNodes(); -// break; -// } -// } + + } + + + public void remakePopulation() { + population = new Population(resources); } @@ -342,23 +415,22 @@ public class JCGP { } public void nextGeneration() { - resources.set("currentGen", resources.getInt("currentGen") + 1); fitnessFunction.evaluate(population, resources); evolutionaryAlgorithm.evolve(population, mutator, resources); if (evolutionaryAlgorithm.getFittestChromosome().getFitness() >= 6) { - System.out.println("solution found"); + resources.println("solution found"); evolutionaryAlgorithm.getFittestChromosome().printNodes(); } else { - System.out.println("Generation: " + resources.getInt("currentGen") + ", fitness: " + evolutionaryAlgorithm.getFittestChromosome().getFitness()); + resources.println("Generation: " + resources.getInt("currentGen") + ", fitness: " + evolutionaryAlgorithm.getFittestChromosome().getFitness()); } + resources.set("currentGen", resources.getInt("currentGen") + 1); } public void start() { while (resources.getInt("currentGen") <= resources.getInt("generations")) { nextGeneration(); } - // TODO print something? - } + } } diff --git a/src/jcgp/exceptions/InsufficientConnectionsException.java b/src/jcgp/backend/exceptions/InsufficientConnectionsException.java index 2ffc10f..15ac845 100644 --- a/src/jcgp/exceptions/InsufficientConnectionsException.java +++ b/src/jcgp/backend/exceptions/InsufficientConnectionsException.java @@ -1,4 +1,4 @@ -package jcgp.exceptions; +package jcgp.backend.exceptions; public class InsufficientConnectionsException extends RuntimeException { diff --git a/src/jcgp/exceptions/InvalidArgumentsException.java b/src/jcgp/backend/exceptions/InvalidArgumentsException.java index 537018d..bbae976 100644 --- a/src/jcgp/exceptions/InvalidArgumentsException.java +++ b/src/jcgp/backend/exceptions/InvalidArgumentsException.java @@ -1,4 +1,4 @@ -package jcgp.exceptions; +package jcgp.backend.exceptions; public class InvalidArgumentsException extends RuntimeException { diff --git a/src/jcgp/exceptions/ManagedModuleException.java b/src/jcgp/backend/exceptions/ManagedModuleException.java index a327dfb..3452d35 100644 --- a/src/jcgp/exceptions/ManagedModuleException.java +++ b/src/jcgp/backend/exceptions/ManagedModuleException.java @@ -1,4 +1,4 @@ -package jcgp.exceptions; +package jcgp.backend.exceptions; public class ManagedModuleException extends RuntimeException { diff --git a/src/jcgp/exceptions/ParameterMismatchException.java b/src/jcgp/backend/exceptions/ParameterMismatchException.java index 93a8f10..3ab9fa1 100644 --- a/src/jcgp/exceptions/ParameterMismatchException.java +++ b/src/jcgp/backend/exceptions/ParameterMismatchException.java @@ -1,4 +1,4 @@ -package jcgp.exceptions; +package jcgp.backend.exceptions; public class ParameterMismatchException extends RuntimeException { diff --git a/src/jcgp/function/Arithmetic.java b/src/jcgp/backend/function/Arithmetic.java index b61ee65..6971663 100644 --- a/src/jcgp/function/Arithmetic.java +++ b/src/jcgp/backend/function/Arithmetic.java @@ -1,10 +1,10 @@ -package jcgp.function; +package jcgp.backend.function; import java.util.ArrayList; import java.util.Arrays; -import jcgp.exceptions.InvalidArgumentsException; -import jcgp.population.Connection; +import jcgp.backend.exceptions.InvalidArgumentsException; +import jcgp.backend.population.Connection; public class Arithmetic extends FunctionSet { diff --git a/src/jcgp/function/BitwiseLogic.java b/src/jcgp/backend/function/BitwiseLogic.java index 7ced8e8..bfe361f 100644 --- a/src/jcgp/function/BitwiseLogic.java +++ b/src/jcgp/backend/function/BitwiseLogic.java @@ -1,10 +1,10 @@ -package jcgp.function; +package jcgp.backend.function; import java.util.ArrayList; import java.util.Arrays; -import jcgp.exceptions.InvalidArgumentsException; -import jcgp.population.Connection; +import jcgp.backend.exceptions.InvalidArgumentsException; +import jcgp.backend.population.Connection; public class BitwiseLogic extends FunctionSet { diff --git a/src/jcgp/function/BooleanLogic.java b/src/jcgp/backend/function/BooleanLogic.java index 7e441f2..e0b5c9c 100644 --- a/src/jcgp/function/BooleanLogic.java +++ b/src/jcgp/backend/function/BooleanLogic.java @@ -1,10 +1,10 @@ -package jcgp.function; +package jcgp.backend.function; import java.util.ArrayList; import java.util.Arrays; -import jcgp.exceptions.InvalidArgumentsException; -import jcgp.population.Connection; +import jcgp.backend.exceptions.InvalidArgumentsException; +import jcgp.backend.population.Connection; public class BooleanLogic extends FunctionSet { diff --git a/src/jcgp/function/Function.java b/src/jcgp/backend/function/Function.java index 64dd206..30bbcf0 100644 --- a/src/jcgp/function/Function.java +++ b/src/jcgp/backend/function/Function.java @@ -1,7 +1,7 @@ -package jcgp.function; +package jcgp.backend.function; -import jcgp.exceptions.InvalidArgumentsException; -import jcgp.population.Connection; +import jcgp.backend.exceptions.InvalidArgumentsException; +import jcgp.backend.population.Connection; public abstract class Function { diff --git a/src/jcgp/function/FunctionSet.java b/src/jcgp/backend/function/FunctionSet.java index fef8f88..4470ac8 100644 --- a/src/jcgp/function/FunctionSet.java +++ b/src/jcgp/backend/function/FunctionSet.java @@ -1,4 +1,4 @@ -package jcgp.function; +package jcgp.backend.function; import java.util.ArrayList; import java.util.Iterator; diff --git a/src/jcgp/modules/Module.java b/src/jcgp/backend/modules/Module.java index 9e0b267..f9114de 100644 --- a/src/jcgp/modules/Module.java +++ b/src/jcgp/backend/modules/Module.java @@ -1,9 +1,9 @@ -package jcgp.modules; +package jcgp.backend.modules; import java.util.HashMap; import jcgp.JCGP.Resources; -import jcgp.parameters.Parameter; +import jcgp.backend.parameters.Parameter; public interface Module { public HashMap<String, Parameter> getLocalParameters(); diff --git a/src/jcgp/modules/ModuleStatus.java b/src/jcgp/backend/modules/ModuleStatus.java index 02e2c01..fec8490 100644 --- a/src/jcgp/modules/ModuleStatus.java +++ b/src/jcgp/backend/modules/ModuleStatus.java @@ -1,4 +1,4 @@ -package jcgp.modules; +package jcgp.backend.modules; public enum ModuleStatus { ERROR, WARNING, READY; diff --git a/src/jcgp/modules/ea/EvolutionaryAlgorithm.java b/src/jcgp/backend/modules/ea/EvolutionaryAlgorithm.java index 3bc7fcf..ce457ef 100644 --- a/src/jcgp/modules/ea/EvolutionaryAlgorithm.java +++ b/src/jcgp/backend/modules/ea/EvolutionaryAlgorithm.java @@ -1,10 +1,10 @@ -package jcgp.modules.ea; +package jcgp.backend.modules.ea; import jcgp.JCGP.Resources; -import jcgp.modules.Module; -import jcgp.modules.mutator.Mutator; -import jcgp.population.Chromosome; -import jcgp.population.Population; +import jcgp.backend.modules.Module; +import jcgp.backend.modules.mutator.Mutator; +import jcgp.backend.population.Chromosome; +import jcgp.backend.population.Population; public interface EvolutionaryAlgorithm extends Module { diff --git a/src/jcgp/modules/ea/MuPlusLambda.java b/src/jcgp/backend/modules/ea/MuPlusLambda.java index 94900ca..fcfba05 100644 --- a/src/jcgp/modules/ea/MuPlusLambda.java +++ b/src/jcgp/backend/modules/ea/MuPlusLambda.java @@ -1,14 +1,14 @@ -package jcgp.modules.ea; +package jcgp.backend.modules.ea; import java.util.HashMap; import jcgp.JCGP.Resources; -import jcgp.modules.ModuleStatus; -import jcgp.modules.mutator.Mutator; -import jcgp.parameters.IntegerParameter; -import jcgp.parameters.Parameter; -import jcgp.population.Chromosome; -import jcgp.population.Population; +import jcgp.backend.modules.ModuleStatus; +import jcgp.backend.modules.mutator.Mutator; +import jcgp.backend.parameters.IntegerParameter; +import jcgp.backend.parameters.Parameter; +import jcgp.backend.population.Chromosome; +import jcgp.backend.population.Population; /** * (μ + λ) EA. diff --git a/src/jcgp/modules/ea/TournamentSelection.java b/src/jcgp/backend/modules/ea/TournamentSelection.java index c2915a5..6cbaa45 100644 --- a/src/jcgp/modules/ea/TournamentSelection.java +++ b/src/jcgp/backend/modules/ea/TournamentSelection.java @@ -1,14 +1,14 @@ -package jcgp.modules.ea; +package jcgp.backend.modules.ea; import java.util.HashMap; import jcgp.JCGP.Resources; -import jcgp.modules.ModuleStatus; -import jcgp.modules.mutator.Mutator; -import jcgp.parameters.IntegerParameter; -import jcgp.parameters.Parameter; -import jcgp.population.Chromosome; -import jcgp.population.Population; +import jcgp.backend.modules.ModuleStatus; +import jcgp.backend.modules.mutator.Mutator; +import jcgp.backend.parameters.IntegerParameter; +import jcgp.backend.parameters.Parameter; +import jcgp.backend.population.Chromosome; +import jcgp.backend.population.Population; public class TournamentSelection implements EvolutionaryAlgorithm { @@ -18,7 +18,7 @@ public class TournamentSelection implements EvolutionaryAlgorithm { private HashMap<String, Parameter> localParameters; public TournamentSelection() { - tournament = new IntegerParameter(1, "Tournament size"); + tournament = new IntegerParameter(1, "Tournament size"); localParameters = new HashMap<String, Parameter>(); localParameters.put("tournament", tournament); @@ -32,7 +32,8 @@ public class TournamentSelection implements EvolutionaryAlgorithm { @Override public void evolve(Population population, Mutator mutator, Resources parameters) { - + tournament.set(tournament.get() + 1); + fittestChromosome = population.getChromosome(0); // TODO implement this } diff --git a/src/jcgp/modules/fitness/FitnessFunction.java b/src/jcgp/backend/modules/fitness/FitnessFunction.java index f0800b0..ffce9b7 100644 --- a/src/jcgp/modules/fitness/FitnessFunction.java +++ b/src/jcgp/backend/modules/fitness/FitnessFunction.java @@ -1,8 +1,8 @@ -package jcgp.modules.fitness; +package jcgp.backend.modules.fitness; import jcgp.JCGP.Resources; -import jcgp.modules.Module; -import jcgp.population.Population; +import jcgp.backend.modules.Module; +import jcgp.backend.population.Population; public interface FitnessFunction extends Module { diff --git a/src/jcgp/modules/fitness/TestCase.java b/src/jcgp/backend/modules/fitness/TestCase.java index 081a257..23f7ecf 100644 --- a/src/jcgp/modules/fitness/TestCase.java +++ b/src/jcgp/backend/modules/fitness/TestCase.java @@ -1,4 +1,4 @@ -package jcgp.modules.fitness; +package jcgp.backend.modules.fitness; public class TestCase { diff --git a/src/jcgp/modules/fitness/TestCaseEvaluator.java b/src/jcgp/backend/modules/fitness/TestCaseEvaluator.java index d8c1255..3b67f28 100644 --- a/src/jcgp/modules/fitness/TestCaseEvaluator.java +++ b/src/jcgp/backend/modules/fitness/TestCaseEvaluator.java @@ -1,11 +1,11 @@ -package jcgp.modules.fitness; +package jcgp.backend.modules.fitness; import java.util.HashMap; import jcgp.JCGP.Resources; -import jcgp.modules.ModuleStatus; -import jcgp.parameters.Parameter; -import jcgp.population.Population; +import jcgp.backend.modules.ModuleStatus; +import jcgp.backend.parameters.Parameter; +import jcgp.backend.population.Population; public class TestCaseEvaluator implements FitnessFunction { diff --git a/src/jcgp/modules/mutator/Mutator.java b/src/jcgp/backend/modules/mutator/Mutator.java index 8dfa0f9..fd7cd27 100644 --- a/src/jcgp/modules/mutator/Mutator.java +++ b/src/jcgp/backend/modules/mutator/Mutator.java @@ -1,8 +1,8 @@ -package jcgp.modules.mutator; +package jcgp.backend.modules.mutator; import jcgp.JCGP.Resources; -import jcgp.modules.Module; -import jcgp.population.Chromosome; +import jcgp.backend.modules.Module; +import jcgp.backend.population.Chromosome; public interface Mutator extends Module { diff --git a/src/jcgp/modules/mutator/PointMutator.java b/src/jcgp/backend/modules/mutator/PointMutator.java index 2298368..62d827d 100644 --- a/src/jcgp/modules/mutator/PointMutator.java +++ b/src/jcgp/backend/modules/mutator/PointMutator.java @@ -1,15 +1,16 @@ -package jcgp.modules.mutator; +package jcgp.backend.modules.mutator; import java.util.HashMap; -import jcgp.modules.ModuleStatus; -import jcgp.parameters.DoubleParameter; -import jcgp.parameters.Parameter; +import jcgp.backend.function.Function; +import jcgp.backend.modules.ModuleStatus; +import jcgp.backend.parameters.DoubleParameter; +import jcgp.backend.parameters.Parameter; +import jcgp.backend.population.Chromosome; +import jcgp.backend.population.MutableElement; +import jcgp.backend.population.Node; +import jcgp.backend.population.Output; import jcgp.JCGP.Resources; -import jcgp.population.Chromosome; -import jcgp.population.MutableElement; -import jcgp.population.Node; -import jcgp.population.Output; public class PointMutator implements Mutator { @@ -19,7 +20,7 @@ public class PointMutator implements Mutator { private ModuleStatus status = ModuleStatus.READY; public PointMutator() { - mutationRate = new DoubleParameter(0.5, "Percent mutation"); + mutationRate = new DoubleParameter(0.5, "Percent mutation", false, false, false); localParameters = new HashMap<String, Parameter>(); localParameters.put("mutRate", mutationRate); @@ -36,7 +37,8 @@ public class PointMutator implements Mutator { } else if (m instanceof Node) { int geneType = resources.getRandomInt(1 + resources.getInt("arity")); if (geneType < 1) { - ((Node) m).setFunction(resources.getRandomFunction()); + Function f = resources.getRandomFunction(); + ((Node) m).setFunction(f); } else { m.setConnection(resources.getRandomInt(resources.getInt("arity")), chromosome.getRandomConnection(((Node) m).getColumn())); } diff --git a/src/jcgp/parameters/BooleanParameter.java b/src/jcgp/backend/parameters/BooleanParameter.java index 63e9c73..d5904cd 100644 --- a/src/jcgp/parameters/BooleanParameter.java +++ b/src/jcgp/backend/parameters/BooleanParameter.java @@ -1,4 +1,4 @@ -package jcgp.parameters; +package jcgp.backend.parameters; import javafx.beans.property.SimpleBooleanProperty; @@ -6,13 +6,13 @@ public class BooleanParameter extends Parameter { private SimpleBooleanProperty value; - public BooleanParameter(boolean value, String name, boolean editable, boolean hidden) { - super(name, editable, hidden); + public BooleanParameter(boolean value, String name, boolean monitor, boolean hidden, boolean critical) { + super(name, monitor, hidden, critical); this.value = new SimpleBooleanProperty(value); } public BooleanParameter(boolean value, String name) { - super(name, true, false); + super(name, false, false, true); this.value = new SimpleBooleanProperty(value); } diff --git a/src/jcgp/parameters/DoubleParameter.java b/src/jcgp/backend/parameters/DoubleParameter.java index d555452..26031be 100644 --- a/src/jcgp/parameters/DoubleParameter.java +++ b/src/jcgp/backend/parameters/DoubleParameter.java @@ -1,4 +1,4 @@ -package jcgp.parameters; +package jcgp.backend.parameters; import javafx.beans.property.SimpleDoubleProperty; @@ -6,13 +6,13 @@ public class DoubleParameter extends Parameter { protected SimpleDoubleProperty value; - public DoubleParameter(double value, String name, boolean editable, boolean hidden) { - super(name, editable, hidden); + public DoubleParameter(double value, String name, boolean monitor, boolean hidden, boolean critical) { + super(name, monitor, hidden, critical); this.value = new SimpleDoubleProperty(value); } public DoubleParameter(double value, String name) { - super(name, true, false); + super(name, false, false, true); this.value = new SimpleDoubleProperty(value); } diff --git a/src/jcgp/parameters/IntegerParameter.java b/src/jcgp/backend/parameters/IntegerParameter.java index c743e97..dbfa5c5 100644 --- a/src/jcgp/parameters/IntegerParameter.java +++ b/src/jcgp/backend/parameters/IntegerParameter.java @@ -1,4 +1,4 @@ -package jcgp.parameters; +package jcgp.backend.parameters; import javafx.beans.property.SimpleIntegerProperty; @@ -6,13 +6,13 @@ public class IntegerParameter extends Parameter { protected SimpleIntegerProperty value; - public IntegerParameter(int value, String name, boolean editable, boolean hidden) { - super(name, editable, hidden); + public IntegerParameter(int value, String name, boolean monitor, boolean hidden, boolean critical) { + super(name, monitor, hidden, critical); this.value = new SimpleIntegerProperty(value); } public IntegerParameter(int value, String name) { - super(name, true, false); + super(name, false, false, true); this.value = new SimpleIntegerProperty(value); } diff --git a/src/jcgp/backend/parameters/Parameter.java b/src/jcgp/backend/parameters/Parameter.java new file mode 100644 index 0000000..2f584a4 --- /dev/null +++ b/src/jcgp/backend/parameters/Parameter.java @@ -0,0 +1,35 @@ +package jcgp.backend.parameters; + +import javafx.beans.property.Property; + +public abstract class Parameter { + + protected boolean hidden, monitor, critical; + + protected String name; + + public Parameter(String name, boolean monitor, boolean hidden, boolean critical) { + this.name = name; + this.hidden = hidden; + this.monitor = monitor; + this.critical = critical; + } + + public boolean isHidden() { + return hidden; + } + + public boolean isMonitor() { + return monitor; + } + + public boolean isCritical() { + return critical; + } + + public String getName() { + return name; + } + + public abstract Property<?> valueProperty(); +} diff --git a/src/jcgp/population/Chromosome.java b/src/jcgp/backend/population/Chromosome.java index 297d298..18ae9bb 100644 --- a/src/jcgp/population/Chromosome.java +++ b/src/jcgp/backend/population/Chromosome.java @@ -1,9 +1,9 @@ -package jcgp.population; +package jcgp.backend.population; import java.util.ArrayList; import jcgp.JCGP.Resources; -import jcgp.exceptions.ParameterMismatchException; +import jcgp.backend.exceptions.ParameterMismatchException; public class Chromosome { diff --git a/src/jcgp/population/Connection.java b/src/jcgp/backend/population/Connection.java index 63a171e..ea4f10f 100644 --- a/src/jcgp/population/Connection.java +++ b/src/jcgp/backend/population/Connection.java @@ -1,4 +1,4 @@ -package jcgp.population; +package jcgp.backend.population; public interface Connection { diff --git a/src/jcgp/population/Gene.java b/src/jcgp/backend/population/Gene.java index 8865a01..6b90949 100644 --- a/src/jcgp/population/Gene.java +++ b/src/jcgp/backend/population/Gene.java @@ -1,4 +1,4 @@ -package jcgp.population; +package jcgp.backend.population; public abstract class Gene { diff --git a/src/jcgp/population/Input.java b/src/jcgp/backend/population/Input.java index cfcb3ce..83fba07 100644 --- a/src/jcgp/population/Input.java +++ b/src/jcgp/backend/population/Input.java @@ -1,4 +1,4 @@ -package jcgp.population; +package jcgp.backend.population; public class Input extends Gene implements Connection { diff --git a/src/jcgp/population/MutableElement.java b/src/jcgp/backend/population/MutableElement.java index 12f6bd1..8548e63 100644 --- a/src/jcgp/population/MutableElement.java +++ b/src/jcgp/backend/population/MutableElement.java @@ -1,4 +1,4 @@ -package jcgp.population; +package jcgp.backend.population; public interface MutableElement { diff --git a/src/jcgp/population/Node.java b/src/jcgp/backend/population/Node.java index 141a32a..f1d37a1 100644 --- a/src/jcgp/population/Node.java +++ b/src/jcgp/backend/population/Node.java @@ -1,10 +1,10 @@ -package jcgp.population; +package jcgp.backend.population; import java.util.ArrayList; import java.util.Arrays; -import jcgp.exceptions.InsufficientConnectionsException; -import jcgp.function.Function; +import jcgp.backend.exceptions.InsufficientConnectionsException; +import jcgp.backend.function.Function; public class Node extends Gene implements MutableElement, Connection { @@ -22,13 +22,11 @@ public class Node extends Gene implements MutableElement, Connection { @Override public Object getValue() { - //System.out.print("Calculating node: (" + row + ", " + column + ") > "); return function.run(Arrays.copyOfRange(connections, 0, function.getArity())); } public void setFunction(Function newFunction) { function = newFunction; - chromosome.recomputeActiveNodes(); } @Override diff --git a/src/jcgp/population/Output.java b/src/jcgp/backend/population/Output.java index 5cc6dcf..aa94ab6 100644 --- a/src/jcgp/population/Output.java +++ b/src/jcgp/backend/population/Output.java @@ -1,4 +1,4 @@ -package jcgp.population; +package jcgp.backend.population; import java.util.ArrayList; diff --git a/src/jcgp/population/Population.java b/src/jcgp/backend/population/Population.java index f5e0517..7049d79 100644 --- a/src/jcgp/population/Population.java +++ b/src/jcgp/backend/population/Population.java @@ -1,4 +1,4 @@ -package jcgp.population; +package jcgp.backend.population; import jcgp.JCGP.Resources; diff --git a/src/jcgp/tests/ChromosomeTests.java b/src/jcgp/backend/tests/ChromosomeTests.java index eb4b5d1..1cd067e 100644 --- a/src/jcgp/tests/ChromosomeTests.java +++ b/src/jcgp/backend/tests/ChromosomeTests.java @@ -1,14 +1,14 @@ -package jcgp.tests; +package jcgp.backend.tests; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import jcgp.JCGP.Resources; -import jcgp.population.Chromosome; -import jcgp.population.Connection; -import jcgp.population.Input; -import jcgp.population.MutableElement; -import jcgp.population.Node; -import jcgp.population.Output; +import jcgp.backend.population.Chromosome; +import jcgp.backend.population.Connection; +import jcgp.backend.population.Input; +import jcgp.backend.population.MutableElement; +import jcgp.backend.population.Node; +import jcgp.backend.population.Output; import org.junit.Before; import org.junit.BeforeClass; diff --git a/src/jcgp/tests/InputTests.java b/src/jcgp/backend/tests/InputTests.java index 012a734..4d15667 100644 --- a/src/jcgp/tests/InputTests.java +++ b/src/jcgp/backend/tests/InputTests.java @@ -1,7 +1,7 @@ -package jcgp.tests; +package jcgp.backend.tests; import static org.junit.Assert.assertTrue; -import jcgp.population.Input; +import jcgp.backend.population.Input; import org.junit.Before; import org.junit.Test; diff --git a/src/jcgp/tests/NodeTests.java b/src/jcgp/backend/tests/NodeTests.java index d8aa742..7121e81 100644 --- a/src/jcgp/tests/NodeTests.java +++ b/src/jcgp/backend/tests/NodeTests.java @@ -1,12 +1,12 @@ -package jcgp.tests; +package jcgp.backend.tests; import static org.junit.Assert.assertTrue; import jcgp.JCGP.Resources; -import jcgp.function.Arithmetic; -import jcgp.function.Function; -import jcgp.population.Chromosome; -import jcgp.population.Connection; -import jcgp.population.Node; +import jcgp.backend.function.Arithmetic; +import jcgp.backend.function.Function; +import jcgp.backend.population.Chromosome; +import jcgp.backend.population.Connection; +import jcgp.backend.population.Node; import org.junit.Before; import org.junit.BeforeClass; diff --git a/src/jcgp/tests/OutputTests.java b/src/jcgp/backend/tests/OutputTests.java index 8658fa4..7ff8a4a 100644 --- a/src/jcgp/tests/OutputTests.java +++ b/src/jcgp/backend/tests/OutputTests.java @@ -1,11 +1,10 @@ -package jcgp.tests; +package jcgp.backend.tests; import static org.junit.Assert.assertTrue; - import jcgp.JCGP.Resources; -import jcgp.population.Chromosome; -import jcgp.population.Connection; -import jcgp.population.Output; +import jcgp.backend.population.Chromosome; +import jcgp.backend.population.Connection; +import jcgp.backend.population.Output; import org.junit.Before; import org.junit.BeforeClass; diff --git a/src/jcgp/tests/PopulationTests.java b/src/jcgp/backend/tests/PopulationTests.java index a11becf..51b5168 100644 --- a/src/jcgp/tests/PopulationTests.java +++ b/src/jcgp/backend/tests/PopulationTests.java @@ -1,9 +1,9 @@ -package jcgp.tests; +package jcgp.backend.tests; import static org.junit.Assert.assertTrue; import jcgp.JCGP.Resources; -import jcgp.population.Chromosome; -import jcgp.population.Population; +import jcgp.backend.population.Chromosome; +import jcgp.backend.population.Population; import org.junit.Before; import org.junit.BeforeClass; diff --git a/src/jcgp/gui/ChromosomePane.java b/src/jcgp/gui/ChromosomePane.java index b4a628f..b1f4bf0 100644 --- a/src/jcgp/gui/ChromosomePane.java +++ b/src/jcgp/gui/ChromosomePane.java @@ -6,14 +6,14 @@ import javafx.scene.control.ScrollPane; import javafx.scene.layout.Pane; import javafx.scene.shape.Line; import jcgp.JCGP.Resources; +import jcgp.backend.population.Chromosome; +import jcgp.backend.population.Connection; +import jcgp.backend.population.Input; +import jcgp.backend.population.Node; import jcgp.gui.population.GUIGene; import jcgp.gui.population.GUIInput; import jcgp.gui.population.GUINode; import jcgp.gui.population.GUIOutput; -import jcgp.population.Chromosome; -import jcgp.population.Connection; -import jcgp.population.Input; -import jcgp.population.Node; public class ChromosomePane extends ScrollPane { @@ -26,14 +26,14 @@ public class ChromosomePane extends ScrollPane { private ArrayList<Line> connectionLines; + private ArrayList<GUIOutput> relock = new ArrayList<GUIOutput>(); + private boolean target = false; public ChromosomePane(Chromosome chromosome, Resources resources) { super(); connectionLines = new ArrayList<Line>(); - //setMouseTransparent(true); - content = new Pane(); content.setId("content pane for genes"); @@ -119,4 +119,20 @@ public class ChromosomePane extends ScrollPane { guiOutputs[i].updateLines(); } } + + public void unlockOutputs() { + relock.clear(); + for (int i = 0; i < guiOutputs.length; i++) { + if (guiOutputs[i].isLocked()) { + guiOutputs[i].unlock(); + relock.add(guiOutputs[i]); + } + } + } + + public void relockOutputs() { + for (int i = 0; i < relock.size(); i++) { + relock.get(i).lock(); + } + } } diff --git a/src/jcgp/GUI.java b/src/jcgp/gui/GUI.java index d81e760..7e7f385 100644 --- a/src/jcgp/GUI.java +++ b/src/jcgp/gui/GUI.java @@ -1,6 +1,4 @@ -package jcgp; - -import java.util.concurrent.ExecutionException; +package jcgp.gui; import javafx.application.Application; import javafx.application.Platform; @@ -12,8 +10,8 @@ import javafx.scene.control.TabPane; import javafx.scene.control.TabPane.TabClosingPolicy; import javafx.scene.layout.BorderPane; import javafx.stage.Stage; +import jcgp.JCGP; import jcgp.JCGP.Resources; -import jcgp.gui.ChromosomePane; import jcgp.gui.console.GUIConsole; import jcgp.gui.settings.SettingsPane; @@ -40,7 +38,7 @@ public class GUI extends Application { public static final double SETTINGS_WIDTH = 200; public static final double CONSOLE_HEIGHT = 100; - + public static final double WRAP_WIDTH = 90; private static JCGP cgp; @@ -50,40 +48,55 @@ public class GUI extends Application { private BorderPane window; private ChromosomePane[] chromosomes; - private TabPane mainPane; + private TabPane chromosomeTabs; private GUIConsole console = new GUIConsole(); private SettingsPane settings; - private Service<Integer> cgpService; + private Service<Void> cgpService; + + private boolean evolving = false; - private static boolean evolving = false; + private Object printLock = new Object(); + + private Runnable consoleFlush = new Runnable() { + @Override + public void run() { + synchronized(printLock) { + console.flush(); + printLock.notifyAll(); + } + } + }; public static void main(String[] args) { cgp = new JCGP(); - resources = cgp.getResources(); + resources = cgp.getResources(); launch(); } @Override public void start(Stage primaryStage) throws Exception { - - cgpService = new Service<Integer> () { - + resources.setConsole(console); + + cgpService = new Service<Void> () { @Override - protected Task<Integer> createTask() { + protected Task<Void> createTask() { - Task<Integer> t = new Task<Integer>() { + Task<Void> t = new Task<Void>() { @Override - protected Integer call() throws Exception { + protected Void call() throws Exception { while (!isCancelled()) { - cgp.nextGeneration(); + Platform.runLater(consoleFlush); + synchronized (printLock) { + cgp.nextGeneration(); + printLock.wait(); + } } return null; } }; - return t; } }; @@ -94,23 +107,15 @@ public class GUI extends Application { * */ - mainPane = new TabPane(); - mainPane.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE); - chromosomes = new ChromosomePane[cgp.getResources().getInt("popSize")]; - Tab tab; - for (int i = 0; i < chromosomes.length; i++) { - chromosomes[i] = new ChromosomePane(cgp.getPopulation().getChromosome(i), resources); - tab = new Tab("Chr " + i); - tab.setContent(chromosomes[i]); - mainPane.getTabs().add(tab); - } + leftPane = new BorderPane(); + + chromosomeTabs = new TabPane(); + chromosomeTabs.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE); + makeChromosomeTabPane(); settings = new SettingsPane(cgp, this); - //mainPane.setPrefHeight(500); - - leftPane = new BorderPane(); - leftPane.setCenter(mainPane); + leftPane.setCenter(chromosomeTabs); leftPane.setBottom(console); window = new BorderPane(); @@ -118,52 +123,89 @@ public class GUI extends Application { window.setCenter(leftPane); window.setRight(settings); - //primaryStage.setMinHeight(600); - //primaryStage.setMinWidth(800); - primaryStage.setTitle("JCGP"); primaryStage.setScene(new Scene(window)); primaryStage.show(); } + + /** + * + */ + private void makeChromosomeTabPane() { + chromosomeTabs.getTabs().clear(); + + chromosomes = new ChromosomePane[cgp.getResources().getInt("popSize")]; + Tab tab; + for (int i = 0; i < chromosomes.length; i++) { + chromosomes[i] = new ChromosomePane(cgp.getPopulation().getChromosome(i), resources); + tab = new Tab("Chr " + i); + tab.setContent(chromosomes[i]); + chromosomeTabs.getTabs().add(tab); + } + } - public void updateNodeGrids() { + private void updateNodeGrids() { for (int i = 0; i < chromosomes.length; i++) { chromosomes[i].update(); } } + + private void unlockOutputs() { + for (int i = 0; i < chromosomes.length; i++) { + chromosomes[i].unlockOutputs(); + } + } + + private void relockOutputs() { + for (int i = 0; i < chromosomes.length; i++) { + chromosomes[i].relockOutputs(); + } + } + + public void disableChromosomePanes(boolean value) { + chromosomeTabs.setDisable(value); + } - public void playPause() { + public void playPause() { if (!evolving) { + settings.disableSettings(true); + disableChromosomePanes(true); + unlockOutputs(); evolving = true; cgpService.restart(); } else { - cgpService.cancel(); + settings.disableSettings(false); + disableChromosomePanes(false); + updateNodeGrids(); evolving = false; + cgpService.cancel(); + relockOutputs(); } } public void step() { if (!evolving) { - Thread t = new Thread(new Task<Object>() { + Thread t = new Thread(new Task<Void>() { @Override - protected Object call() throws Exception { + protected Void call() throws Exception { + unlockOutputs(); cgp.nextGeneration(); - evolving = false; + console.flush(); + updateNodeGrids(); + relockOutputs(); return null; } }); - evolving = true; t.start(); } } - public boolean isEvolving() { - return evolving; - } - - public Service<Integer> getCGPService() { - return cgpService; + public void resetCGP() { + cgp.remakePopulation(); + makeChromosomeTabPane(); + + resources.set("currentGen", 1); + resources.set("currentRun", 1); } - } diff --git a/src/jcgp/gui/Messenger.java b/src/jcgp/gui/Messenger.java deleted file mode 100644 index becf47c..0000000 --- a/src/jcgp/gui/Messenger.java +++ /dev/null @@ -1,7 +0,0 @@ -package jcgp.gui; - -public class Messenger { - - - -} diff --git a/src/jcgp/gui/console/Console.java b/src/jcgp/gui/console/Console.java new file mode 100644 index 0000000..63c7f5b --- /dev/null +++ b/src/jcgp/gui/console/Console.java @@ -0,0 +1,11 @@ +package jcgp.gui.console; + +public interface Console { + + public void println(String s); + + public void print(String s); + + public void flush(); + +} diff --git a/src/jcgp/gui/console/GUIConsole.java b/src/jcgp/gui/console/GUIConsole.java index 0ef2be3..8fdb1a5 100644 --- a/src/jcgp/gui/console/GUIConsole.java +++ b/src/jcgp/gui/console/GUIConsole.java @@ -5,13 +5,15 @@ import javafx.scene.Cursor; import javafx.scene.control.TextArea; import javafx.scene.input.MouseEvent; import javafx.scene.layout.AnchorPane; -import jcgp.GUI; +import jcgp.gui.GUI; -public class GUIConsole extends AnchorPane { +public class GUIConsole extends AnchorPane implements Console { private boolean dragging; private TextArea textArea = new TextArea("Welcome to JCGP!\n"); + private StringBuffer printBuffer = new StringBuffer(); + public GUIConsole() { super(); textArea.setEditable(false); @@ -87,8 +89,20 @@ public class GUIConsole extends AnchorPane { return event.getY() < (GUI.RESIZE_MARGIN); } - public TextArea getTextArea() { - return textArea; + @Override + public void println(String s) { + printBuffer.append(s + "\n"); + } + + @Override + public void print(String s) { + printBuffer.append(s); + } + + @Override + public void flush() { + textArea.appendText(printBuffer.toString()); + printBuffer = new StringBuffer(); } } diff --git a/src/jcgp/gui/population/GUIGene.java b/src/jcgp/gui/population/GUIGene.java index a37eb19..26be2a5 100644 --- a/src/jcgp/gui/population/GUIGene.java +++ b/src/jcgp/gui/population/GUIGene.java @@ -4,9 +4,9 @@ import javafx.beans.property.SimpleObjectProperty; import javafx.scene.Group; import javafx.scene.shape.Circle; import javafx.scene.text.Text; +import jcgp.backend.population.Connection; +import jcgp.backend.population.Gene; import jcgp.gui.ChromosomePane; -import jcgp.population.Connection; -import jcgp.population.Gene; enum GUIGeneState { NEUTRAL, @@ -59,7 +59,7 @@ public abstract class GUIGene extends Group { return locked; } - public abstract void setLocked(boolean value); + abstract void setLocked(boolean value); public abstract void addLocks(int value); diff --git a/src/jcgp/gui/population/GUIInput.java b/src/jcgp/gui/population/GUIInput.java index 30ce4ac..f47186c 100644 --- a/src/jcgp/gui/population/GUIInput.java +++ b/src/jcgp/gui/population/GUIInput.java @@ -11,11 +11,11 @@ import javafx.scene.shape.Circle; import javafx.scene.text.Font; import javafx.scene.text.Text; import javafx.scene.text.TextAlignment; -import jcgp.GUI; +import jcgp.backend.population.Connection; +import jcgp.backend.population.Input; +import jcgp.backend.population.Output; import jcgp.gui.ChromosomePane; -import jcgp.population.Connection; -import jcgp.population.Input; -import jcgp.population.Output; +import jcgp.gui.GUI; public class GUIInput extends GUIGene { @@ -212,7 +212,7 @@ public class GUIInput extends GUIGene { } @Override - public void setLocked(boolean value) { + void setLocked(boolean value) { locked += value ? 1 : -1; stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER); } diff --git a/src/jcgp/gui/population/GUINode.java b/src/jcgp/gui/population/GUINode.java index 6fc84da..450647f 100644 --- a/src/jcgp/gui/population/GUINode.java +++ b/src/jcgp/gui/population/GUINode.java @@ -13,11 +13,11 @@ import javafx.scene.shape.Line; import javafx.scene.text.Font; import javafx.scene.text.Text; import javafx.scene.text.TextAlignment; -import jcgp.GUI; +import jcgp.backend.population.Connection; +import jcgp.backend.population.Input; +import jcgp.backend.population.Node; import jcgp.gui.ChromosomePane; -import jcgp.population.Connection; -import jcgp.population.Input; -import jcgp.population.Node; +import jcgp.gui.GUI; public class GUINode extends GUIGene { @@ -429,7 +429,7 @@ public class GUINode extends GUIGene { } @Override - public void setLocked(boolean value) { + void setLocked(boolean value) { locked += value ? 1 : -1; stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER); diff --git a/src/jcgp/gui/population/GUIOutput.java b/src/jcgp/gui/population/GUIOutput.java index 16d95f0..9c5dfa5 100644 --- a/src/jcgp/gui/population/GUIOutput.java +++ b/src/jcgp/gui/population/GUIOutput.java @@ -13,12 +13,12 @@ import javafx.scene.shape.Line; import javafx.scene.text.Font; import javafx.scene.text.Text; import javafx.scene.text.TextAlignment; -import jcgp.GUI; +import jcgp.backend.population.Connection; +import jcgp.backend.population.Input; +import jcgp.backend.population.Node; +import jcgp.backend.population.Output; import jcgp.gui.ChromosomePane; -import jcgp.population.Connection; -import jcgp.population.Input; -import jcgp.population.Node; -import jcgp.population.Output; +import jcgp.gui.GUI; public class GUIOutput extends GUIGene { @@ -281,7 +281,7 @@ public class GUIOutput extends GUIGene { } @Override - public void setLocked(boolean value) { + void setLocked(boolean value) { locked += value ? 1 : -1; setConnections(value ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER); @@ -314,5 +314,20 @@ public class GUIOutput extends GUIGene { sourceLine.setEndX(gene.getLayoutX() + NODE_RADIUS); sourceLine.setEndY(gene.getLayoutY()); } + + public void unlock() { + if (isLocked()) { + setLocked(false); + stateProperty.set(GUIGeneState.NEUTRAL); + setConnections(GUIGeneState.NEUTRAL); + } + } + + public void lock() { + if (!isLocked()) { + stateProperty.set(GUIGeneState.HOVER); + setLocked(true); + } + } } diff --git a/src/jcgp/gui/settings/SettingsPane.java b/src/jcgp/gui/settings/SettingsPane.java index 9edcbdb..61011aa 100644 --- a/src/jcgp/gui/settings/SettingsPane.java +++ b/src/jcgp/gui/settings/SettingsPane.java @@ -5,7 +5,6 @@ import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; -import javafx.beans.property.SimpleIntegerProperty; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; @@ -22,14 +21,15 @@ import javafx.scene.layout.VBox; import javafx.scene.text.Font; import javafx.scene.text.FontSmoothingType; import javafx.scene.text.Text; -import jcgp.GUI; import jcgp.JCGP; -import jcgp.function.FunctionSet; +import jcgp.backend.function.FunctionSet; +import jcgp.backend.modules.ea.EvolutionaryAlgorithm; +import jcgp.backend.modules.fitness.FitnessFunction; +import jcgp.backend.modules.mutator.Mutator; +import jcgp.backend.parameters.IntegerParameter; +import jcgp.backend.parameters.Parameter; +import jcgp.gui.GUI; import jcgp.gui.settings.parameters.*; -import jcgp.modules.ea.EvolutionaryAlgorithm; -import jcgp.modules.fitness.FitnessFunction; -import jcgp.modules.mutator.Mutator; -import jcgp.parameters.*; public class SettingsPane extends AnchorPane { @@ -84,31 +84,28 @@ public class SettingsPane extends AnchorPane { bpPane.getChildren().add(header); - final GUIIntegerParameter generation = new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("currentGen")); - final GUIIntegerParameter run = new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("currentRun")); + GUIParameter rows = GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("rows")); + parameters.add(rows); + parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("columns"))); + parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("inputs"))); + parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("outputs"))); + parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("levelsBack"))); - parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("rows"))); - parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("columns"))); - parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("inputs"))); - parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("outputs"))); - parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("levelsBack"))); + parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("popSize"))); + parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("generations"))); + parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("runs"))); - parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("popSize"))); - parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("generations"))); - parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("runs"))); + parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("currentGen"))); + parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("currentRun"))); - parameters.add(generation); - parameters.add(run); - - parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("seed"))); - parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("report"))); - parameters.add(new GUIBooleanParameter((BooleanParameter) cgp.getResources().getParameter("verbose"))); + parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("seed"))); + parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("report"))); bpPane.getChildren().addAll(parameters); mainContainer.getChildren().add(bpPane); - generation.getTextField().textProperty().bind(((SimpleIntegerProperty) cgp.getResources().getParameter("currentGen").valueProperty()).asString()); + } private void initialiseEAParameters(final JCGP cgp) { @@ -245,13 +242,16 @@ public class SettingsPane extends AnchorPane { play.setOnAction(new EventHandler<ActionEvent>() { @Override - public void handle(ActionEvent event) { - gui.playPause(); - if (gui.isEvolving()) { + public void handle(ActionEvent event) { + if (play.getText() == "Run") { + if (applyChanges()) { + gui.resetCGP(); + } play.setText("Pause"); } else { play.setText("Run"); } + gui.playPause(); } }); @@ -260,6 +260,9 @@ public class SettingsPane extends AnchorPane { step.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { + if (applyChanges()) { + gui.resetCGP(); + } gui.step(); } }); @@ -274,8 +277,7 @@ public class SettingsPane extends AnchorPane { controls.getChildren().add(flowButtons); - mainContainer.getChildren().add(controls); - + mainContainer.getChildren().add(controls); } /** @@ -287,19 +289,10 @@ public class SettingsPane extends AnchorPane { vb.getChildren().clear(); while (it.hasNext()) { Parameter parameter = ((Map.Entry<String, Parameter>) it.next()).getValue(); - if (parameter instanceof IntegerParameter) { - GUIIntegerParameter gip = new GUIIntegerParameter((IntegerParameter) parameter); - parameters.add(gip); - vb.getChildren().add(gip); - } else if (parameter instanceof DoubleParameter) { - GUIDoubleParameter gdp = new GUIDoubleParameter((DoubleParameter) parameter); - parameters.add(gdp); - vb.getChildren().add(gdp); - } else if (parameter instanceof BooleanParameter) { - GUIBooleanParameter gbp = new GUIBooleanParameter((BooleanParameter) parameter); - parameters.add(gbp); - vb.getChildren().add(gbp); - } + GUIParameter gp = GUIParameter.create(parameter); + + parameters.add(gp); + vb.getChildren().add(gp); } } @@ -371,30 +364,29 @@ public class SettingsPane extends AnchorPane { return event.getX() < (GUI.RESIZE_MARGIN); } - public void refreshValues() { - for (GUIParameter parameter : parameters) { - parameter.refreshValue(); - } - //parent.updateNodeGrids(); - } - -// public void bindParameters() { -// for (GUIParameter parameter : parameters) { -// parameter.doBindings(); -// } -// } -// -// public void unbindParameters() { -// for (GUIParameter parameter : parameters) { -// parameter.undoBindings(); -// } -// } - - public void toggleSettings(boolean value) { + public void disableSettings(boolean value) { bpPane.setDisable(value); eaPane.setDisable(value); mutatorPane.setDisable(value); ffPane.setDisable(value); nfPane.setDisable(value); } + + /** + * Writes the GUI parameter value back to the resources parameter, + * if any changes were made. + * + * @return true if the experiment needs to be reset, false otherwise. + */ + private boolean applyChanges() { + boolean reset = false; + + for (GUIParameter parameter : parameters) { + reset |= parameter.applyChange(); + } + + return reset; + } + + } diff --git a/src/jcgp/gui/settings/parameters/GUIBooleanParameter.java b/src/jcgp/gui/settings/parameters/GUIBooleanParameter.java index a9f6753..8acd6dd 100644 --- a/src/jcgp/gui/settings/parameters/GUIBooleanParameter.java +++ b/src/jcgp/gui/settings/parameters/GUIBooleanParameter.java @@ -1,11 +1,11 @@ package jcgp.gui.settings.parameters; import javafx.scene.control.CheckBox; -import jcgp.parameters.BooleanParameter; +import jcgp.backend.parameters.BooleanParameter; public class GUIBooleanParameter extends GUIParameter { - public GUIBooleanParameter(BooleanParameter parameter) { + GUIBooleanParameter(BooleanParameter parameter) { super(); this.parameter = parameter; @@ -13,22 +13,16 @@ public class GUIBooleanParameter extends GUIParameter { value = new CheckBox(parameter.getName()); ((CheckBox) value).setSelected(parameter.get()); - value.setDisable(!parameter.isEditable()); + value.setDisable(parameter.isMonitor()); - getChildren().add(value); + if (parameter.isMonitor()) { + makeLightBinding(); + System.out.println("light binding made for " + name); + } + getChildren().add(value); } -// @Override -// public void doBindings() { -// ((CheckBox) value).selectedProperty().bind(((BooleanParameter) parameter).valueProperty()); -// } -// -// @Override -// public void undoBindings() { -// ((CheckBox) value).selectedProperty().unbind(); -// } - @Override public void refreshValue() { if (!((CheckBox) value).selectedProperty().isBound()) { @@ -36,5 +30,17 @@ public class GUIBooleanParameter extends GUIParameter { } } + + @Override + public boolean applyChange() { + if (((CheckBox) value).isSelected() != ((BooleanParameter) parameter).get() && (!parameter.isMonitor())) { + // apply value + ((BooleanParameter) parameter).set(((CheckBox) value).isSelected()); + if (parameter.isCritical()) { + return true; + } + } + return false; + } } diff --git a/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java b/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java index 25d5b9f..4b74c6e 100644 --- a/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java +++ b/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java @@ -4,12 +4,12 @@ import javafx.geometry.Pos; import javafx.scene.control.TextField; import javafx.scene.layout.Priority; import javafx.scene.text.Text; -import jcgp.GUI; -import jcgp.parameters.DoubleParameter; +import jcgp.backend.parameters.DoubleParameter; +import jcgp.gui.GUI; public class GUIDoubleParameter extends GUIParameter { - public GUIDoubleParameter(DoubleParameter parameter) { + GUIDoubleParameter(DoubleParameter parameter) { super(); this.parameter = parameter; @@ -23,26 +23,29 @@ public class GUIDoubleParameter extends GUIParameter { name.setWrappingWidth(GUI.WRAP_WIDTH); - ((TextField) value).setEditable(parameter.isEditable()); + ((TextField) value).setEditable(!parameter.isMonitor()); + + if (parameter.isMonitor()) { + makeLightBinding(); + } getChildren().addAll(name, value); } -// @Override -// public void doBindings() { -// ((TextField) value).textProperty().bind(((DoubleParameter) parameter).valueProperty().asString()); -// } -// -// @Override -// public void undoBindings() { -// ((TextField) value).textProperty().unbind(); -// } - @Override public void refreshValue() { - if (!((TextField) value).textProperty().isBound()) { - ((TextField) value).setText(String.valueOf(((DoubleParameter) parameter).get())); - } + ((TextField) value).setText(String.valueOf(((DoubleParameter) parameter).get())); } - + + @Override + public boolean applyChange() { + if (Double.valueOf(((TextField) value).getText()) != ((DoubleParameter) parameter).get() && (!parameter.isMonitor())) { + // apply value + ((DoubleParameter) parameter).set(Double.valueOf(((TextField) value).getText())); + if (parameter.isCritical()) { + return true; + } + } + return false; + } } diff --git a/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java b/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java index 6bcfd55..70b78a6 100644 --- a/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java +++ b/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java @@ -4,12 +4,12 @@ import javafx.geometry.Pos; import javafx.scene.control.TextField; import javafx.scene.layout.Priority; import javafx.scene.text.Text; -import jcgp.GUI; -import jcgp.parameters.IntegerParameter; +import jcgp.backend.parameters.IntegerParameter; +import jcgp.gui.GUI; public class GUIIntegerParameter extends GUIParameter { - public GUIIntegerParameter(IntegerParameter parameter) { + GUIIntegerParameter(IntegerParameter parameter) { super(); this.parameter = parameter; @@ -23,27 +23,27 @@ public class GUIIntegerParameter extends GUIParameter { name.setWrappingWidth(GUI.WRAP_WIDTH); - ((TextField) value).setEditable(parameter.isEditable()); + ((TextField) value).setEditable(!parameter.isMonitor()); + + if (parameter.isMonitor()) { + makeLightBinding(); + } getChildren().addAll(name, value); } -// @Override -// public void doBindings() { -// ((TextField) value).textProperty().bind(((IntegerParameter) parameter).valueProperty().asString()); -// } -// -// @Override -// public void undoBindings() { -// ((TextField) value).textProperty().unbind(); -// } - - public TextField getTextField() { - return (TextField) value; - } - @Override public void refreshValue() { ((TextField) value).setText(String.valueOf(((IntegerParameter) parameter).get())); } + + @Override + public boolean applyChange() { + if (Integer.valueOf(((TextField) value).getText()) != ((IntegerParameter) parameter).get() && (!parameter.isMonitor())) { + // apply value + ((IntegerParameter) parameter).set(Integer.valueOf(((TextField) value).getText())); + return parameter.isCritical(); + } + return false; + } } diff --git a/src/jcgp/gui/settings/parameters/GUIParameter.java b/src/jcgp/gui/settings/parameters/GUIParameter.java index a2f2f9c..a783d71 100644 --- a/src/jcgp/gui/settings/parameters/GUIParameter.java +++ b/src/jcgp/gui/settings/parameters/GUIParameter.java @@ -1,10 +1,18 @@ package jcgp.gui.settings.parameters; +import java.util.concurrent.atomic.AtomicBoolean; + +import javafx.application.Platform; +import javafx.beans.value.ChangeListener; +import javafx.beans.value.ObservableValue; import javafx.geometry.Pos; import javafx.scene.control.Control; import javafx.scene.layout.HBox; import javafx.scene.text.Text; -import jcgp.parameters.Parameter; +import jcgp.backend.parameters.BooleanParameter; +import jcgp.backend.parameters.DoubleParameter; +import jcgp.backend.parameters.IntegerParameter; +import jcgp.backend.parameters.Parameter; public abstract class GUIParameter extends HBox { @@ -12,19 +20,51 @@ public abstract class GUIParameter extends HBox { protected Text name; protected Control value; - public GUIParameter() { + protected AtomicBoolean updateCheck = new AtomicBoolean(true); + + protected GUIParameter() { setAlignment(Pos.CENTER_LEFT); setSpacing(5); } - public Parameter getParameter() { - return parameter; + protected final void makeLightBinding() { + parameter.valueProperty().addListener(new ChangeListener<Object>() { + @Override + public void changed( + ObservableValue<? extends Object> observable, + Object oldValue, Object newValue) { + if (updateCheck.getAndSet(false)) { + Platform.runLater(new Runnable() { + @Override + public void run() { + updateCheck.set(true); + refreshValue(); + } + }); + } + } + }); } -// public abstract void doBindings(); -// -// public abstract void undoBindings(); - public abstract void refreshValue(); + public static GUIParameter create(Parameter parameter) { + if (parameter instanceof IntegerParameter) { + return new GUIIntegerParameter((IntegerParameter) parameter); + } else if (parameter instanceof DoubleParameter) { + return new GUIDoubleParameter((DoubleParameter) parameter); + } else if (parameter instanceof BooleanParameter) { + return new GUIBooleanParameter((BooleanParameter) parameter); + } else { + throw new ClassCastException("No GUIParameter subclass exists for argument of type " + parameter.getClass()); + } + } + + /** + * Writes the GUI parameter value back to the resources parameter, + * if any changes were made. + * + * @return true if the experiment needs to be reset, false otherwise. + */ + public abstract boolean applyChange(); } diff --git a/src/jcgp/parameters/Parameter.java b/src/jcgp/parameters/Parameter.java deleted file mode 100644 index a5ecf9e..0000000 --- a/src/jcgp/parameters/Parameter.java +++ /dev/null @@ -1,30 +0,0 @@ -package jcgp.parameters; - -import javafx.beans.property.Property; - -public abstract class Parameter { - - protected boolean hidden = false, editable = true; - - protected String name; - - public Parameter(String name, boolean editable, boolean hidden) { - this.name = name; - this.hidden = hidden; - this.editable = editable; - } - - public boolean isHidden() { - return hidden; - } - - public boolean isEditable() { - return editable; - } - - public String getName() { - return name; - } - - public abstract Property<?> valueProperty(); -} |