aboutsummaryrefslogtreecommitdiffstats
path: root/src/jcgp
diff options
context:
space:
mode:
authorEduardo Pedroni <ep625@york.ac.uk>2014-04-06 21:58:53 +0100
committerEduardo Pedroni <ep625@york.ac.uk>2014-04-06 21:58:53 +0100
commite6dd7711c7dad5e000445208eb5845801f4ccffc (patch)
tree1454bd20a8dd7069b1283184c42f4def6d5f7e6f /src/jcgp
parentc7969623b44f375e30fa3f15dcd7581609276a0f (diff)
About to make big changes to the way fitness works, committing just in case
Diffstat (limited to 'src/jcgp')
-rw-r--r--src/jcgp/JCGP.java400
-rw-r--r--src/jcgp/backend/exceptions/ManagedModuleException.java10
-rw-r--r--src/jcgp/backend/function/BitwiseLogic.java61
-rw-r--r--src/jcgp/backend/function/BooleanLogic.java60
-rw-r--r--src/jcgp/backend/function/FunctionSet.java32
-rw-r--r--src/jcgp/backend/function/IntegerArithmetic.java (renamed from src/jcgp/backend/function/Arithmetic.java)39
-rw-r--r--src/jcgp/backend/modules/Module.java4
-rw-r--r--src/jcgp/backend/modules/ModuleStatus.java16
-rw-r--r--src/jcgp/backend/modules/ea/EvolutionaryAlgorithm.java2
-rw-r--r--src/jcgp/backend/modules/ea/MuPlusLambda.java20
-rw-r--r--src/jcgp/backend/modules/ea/TournamentSelection.java12
-rw-r--r--src/jcgp/backend/modules/fitness/FitnessFunction.java2
-rw-r--r--src/jcgp/backend/modules/fitness/TestCase.java29
-rw-r--r--src/jcgp/backend/modules/fitness/TestCaseEvaluator.java43
-rw-r--r--src/jcgp/backend/modules/fitness/testcase/TestCaseEvaluator.java75
-rw-r--r--src/jcgp/backend/modules/mutator/Mutator.java2
-rw-r--r--src/jcgp/backend/modules/mutator/PointMutator.java40
-rw-r--r--src/jcgp/backend/population/Chromosome.java2
-rw-r--r--src/jcgp/backend/population/Node.java2
-rw-r--r--src/jcgp/backend/population/Population.java6
-rw-r--r--src/jcgp/backend/resources/Console.java (renamed from src/jcgp/gui/console/Console.java)2
-rw-r--r--src/jcgp/backend/resources/ModifiableResources.java42
-rw-r--r--src/jcgp/backend/resources/Resources.java310
-rw-r--r--src/jcgp/backend/resources/parameters/BooleanParameter.java (renamed from src/jcgp/backend/parameters/BooleanParameter.java)3
-rw-r--r--src/jcgp/backend/resources/parameters/DoubleParameter.java (renamed from src/jcgp/backend/parameters/DoubleParameter.java)3
-rw-r--r--src/jcgp/backend/resources/parameters/IntegerParameter.java (renamed from src/jcgp/backend/parameters/IntegerParameter.java)3
-rw-r--r--src/jcgp/backend/resources/parameters/Parameter.java (renamed from src/jcgp/backend/parameters/Parameter.java)2
-rw-r--r--src/jcgp/backend/resources/parameters/ParameterStatus.java (renamed from src/jcgp/backend/parameters/ParameterStatus.java)2
-rw-r--r--src/jcgp/backend/tests/ChromosomeTests.java6
-rw-r--r--src/jcgp/backend/tests/NodeTests.java32
-rw-r--r--src/jcgp/backend/tests/OutputTests.java2
-rw-r--r--src/jcgp/backend/tests/PopulationTests.java2
-rw-r--r--src/jcgp/gui/GUI.java172
-rw-r--r--src/jcgp/gui/console/GUIConsole.java63
-rw-r--r--src/jcgp/gui/dragresize/HorizontalDragResize.java90
-rw-r--r--src/jcgp/gui/dragresize/VerticalDragResize.java90
-rw-r--r--src/jcgp/gui/population/ChromosomePane.java (renamed from src/jcgp/gui/ChromosomePane.java)19
-rw-r--r--src/jcgp/gui/population/FunctionSelector.java73
-rw-r--r--src/jcgp/gui/population/GUIGene.java40
-rw-r--r--src/jcgp/gui/population/GUIInput.java145
-rw-r--r--src/jcgp/gui/population/GUINode.java207
-rw-r--r--src/jcgp/gui/population/GUIOutput.java142
-rw-r--r--src/jcgp/gui/population/PopulationPane.java49
-rw-r--r--src/jcgp/gui/settings/SettingsPane.java184
-rw-r--r--src/jcgp/gui/settings/parameters/GUIBooleanParameter.java11
-rw-r--r--src/jcgp/gui/settings/parameters/GUIDoubleParameter.java17
-rw-r--r--src/jcgp/gui/settings/parameters/GUIIntegerParameter.java17
-rw-r--r--src/jcgp/gui/settings/parameters/GUIParameter.java18
48 files changed, 1329 insertions, 1274 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);
+ }
+
}
diff --git a/src/jcgp/backend/exceptions/ManagedModuleException.java b/src/jcgp/backend/exceptions/ManagedModuleException.java
deleted file mode 100644
index 3452d35..0000000
--- a/src/jcgp/backend/exceptions/ManagedModuleException.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package jcgp.backend.exceptions;
-
-public class ManagedModuleException extends RuntimeException {
-
- /**
- *
- */
- private static final long serialVersionUID = -3450063156524494967L;
-
-}
diff --git a/src/jcgp/backend/function/BitwiseLogic.java b/src/jcgp/backend/function/BitwiseLogic.java
index bfe361f..5d47ff7 100644
--- a/src/jcgp/backend/function/BitwiseLogic.java
+++ b/src/jcgp/backend/function/BitwiseLogic.java
@@ -1,8 +1,5 @@
package jcgp.backend.function;
-import java.util.ArrayList;
-import java.util.Arrays;
-
import jcgp.backend.exceptions.InvalidArgumentsException;
import jcgp.backend.population.Connection;
@@ -19,15 +16,13 @@ public class BitwiseLogic extends FunctionSet {
new Nor(),
new Xnor()};
- allowedFunctions = new ArrayList<Function>(Arrays.asList(functionList));
+ enableAll();
}
- public static class And extends Function {
- private int arity = 2;
-
+ public static class And extends Function {
@Override
public Object run(Connection... connections) {
- if (connections.length < arity) {
+ if (connections.length < 2) {
throw new InvalidArgumentsException("Not enough connections were given.");
} else {
int arg1 = ((int) connections[0].getValue());
@@ -40,7 +35,7 @@ public class BitwiseLogic extends FunctionSet {
@Override
public int getArity() {
- return arity;
+ return 2;
}
@Override
@@ -49,12 +44,10 @@ public class BitwiseLogic extends FunctionSet {
}
}
- public static class Or extends Function {
- private int arity = 2;
-
+ public static class Or extends Function {
@Override
public Object run(Connection... connections) {
- if (connections.length < arity) {
+ if (connections.length < 2) {
throw new InvalidArgumentsException("Not enough connections were given.");
} else {
int arg1 = ((int) connections[0].getValue());
@@ -67,7 +60,7 @@ public class BitwiseLogic extends FunctionSet {
@Override
public int getArity() {
- return arity;
+ return 2;
}
@Override
@@ -76,12 +69,10 @@ public class BitwiseLogic extends FunctionSet {
}
}
- public static class Not extends Function {
- private int arity = 1;
-
+ public static class Not extends Function {
@Override
public Object run(Connection... connections) {
- if (connections.length < arity) {
+ if (connections.length < 1) {
throw new InvalidArgumentsException("Not enough connections were given.");
} else {
int arg1 = ((int) connections[0].getValue());
@@ -93,7 +84,7 @@ public class BitwiseLogic extends FunctionSet {
@Override
public int getArity() {
- return arity;
+ return 1;
}
@Override
@@ -102,12 +93,10 @@ public class BitwiseLogic extends FunctionSet {
}
}
- public static class Xor extends Function {
- private int arity = 2;
-
+ public static class Xor extends Function {
@Override
public Object run(Connection... connections) {
- if (connections.length < arity) {
+ if (connections.length < 2) {
throw new InvalidArgumentsException("Not enough connections were given.");
} else {
int arg1 = ((int) connections[0].getValue());
@@ -120,7 +109,7 @@ public class BitwiseLogic extends FunctionSet {
@Override
public int getArity() {
- return arity;
+ return 2;
}
@Override
@@ -129,12 +118,10 @@ public class BitwiseLogic extends FunctionSet {
}
}
- public static class Nand extends Function {
- private int arity = 2;
-
+ public static class Nand extends Function {
@Override
public Object run(Connection... connections) {
- if (connections.length < arity) {
+ if (connections.length < 2) {
throw new InvalidArgumentsException("Not enough connections were given.");
} else {
int arg1 = ((int) connections[0].getValue());
@@ -147,7 +134,7 @@ public class BitwiseLogic extends FunctionSet {
@Override
public int getArity() {
- return arity;
+ return 2;
}
@Override
@@ -156,12 +143,10 @@ public class BitwiseLogic extends FunctionSet {
}
}
- public static class Nor extends Function {
- private int arity = 2;
-
+ public static class Nor extends Function {
@Override
public Object run(Connection... connections) {
- if (connections.length < arity) {
+ if (connections.length < 2) {
throw new InvalidArgumentsException("Not enough connections were given.");
} else {
int arg1 = ((int) connections[0].getValue());
@@ -174,7 +159,7 @@ public class BitwiseLogic extends FunctionSet {
@Override
public int getArity() {
- return arity;
+ return 2;
}
@Override
@@ -183,12 +168,10 @@ public class BitwiseLogic extends FunctionSet {
}
}
- public static class Xnor extends Function {
- private int arity = 2;
-
+ public static class Xnor extends Function {
@Override
public Object run(Connection... connections) {
- if (connections.length < arity) {
+ if (connections.length < 2) {
throw new InvalidArgumentsException("Not enough connections were given.");
} else {
int arg1 = ((int) connections[0].getValue());
@@ -201,7 +184,7 @@ public class BitwiseLogic extends FunctionSet {
@Override
public int getArity() {
- return arity;
+ return 2;
}
@Override
diff --git a/src/jcgp/backend/function/BooleanLogic.java b/src/jcgp/backend/function/BooleanLogic.java
index e0b5c9c..9e7d1ff 100644
--- a/src/jcgp/backend/function/BooleanLogic.java
+++ b/src/jcgp/backend/function/BooleanLogic.java
@@ -1,7 +1,5 @@
package jcgp.backend.function;
-import java.util.ArrayList;
-import java.util.Arrays;
import jcgp.backend.exceptions.InvalidArgumentsException;
import jcgp.backend.population.Connection;
@@ -19,15 +17,13 @@ public class BooleanLogic extends FunctionSet {
new Nor(),
new Xnor()};
- allowedFunctions = new ArrayList<Function>(Arrays.asList(functionList));
+ enableAll();
}
- public static class And extends Function {
- private int arity = 2;
-
+ public static class And extends Function {
@Override
public Boolean run(Connection... connections) {
- if (connections.length < arity) {
+ if (connections.length < 2) {
throw new InvalidArgumentsException("Not enough connections were given.");
} else {
Boolean arg1 = ((Boolean) connections[0].getValue());
@@ -40,7 +36,7 @@ public class BooleanLogic extends FunctionSet {
@Override
public int getArity() {
- return arity;
+ return 2;
}
@Override
@@ -49,12 +45,10 @@ public class BooleanLogic extends FunctionSet {
}
}
- public static class Or extends Function {
- private int arity = 2;
-
+ public static class Or extends Function {
@Override
public Boolean run(Connection... connections) {
- if (connections.length < arity) {
+ if (connections.length < 2) {
throw new InvalidArgumentsException("Not enough connections were given.");
} else {
Boolean arg1 = ((Boolean) connections[0].getValue());
@@ -67,7 +61,7 @@ public class BooleanLogic extends FunctionSet {
@Override
public int getArity() {
- return arity;
+ return 2;
}
@Override
@@ -76,12 +70,10 @@ public class BooleanLogic extends FunctionSet {
}
}
- public static class Not extends Function {
- private int arity = 1;
-
+ public static class Not extends Function {
@Override
public Boolean run(Connection... connections) {
- if (connections.length < arity) {
+ if (connections.length < 1) {
throw new InvalidArgumentsException("Not enough connections were given.");
} else {
Boolean arg1 = ((Boolean) connections[0].getValue());
@@ -93,7 +85,7 @@ public class BooleanLogic extends FunctionSet {
@Override
public int getArity() {
- return arity;
+ return 1;
}
@Override
@@ -102,12 +94,10 @@ public class BooleanLogic extends FunctionSet {
}
}
- public static class Xor extends Function {
- private int arity = 2;
-
+ public static class Xor extends Function {
@Override
public Boolean run(Connection... connections) {
- if (connections.length < arity) {
+ if (connections.length < 2) {
throw new InvalidArgumentsException("Not enough connections were given.");
} else {
Boolean arg1 = ((Boolean) connections[0].getValue());
@@ -120,7 +110,7 @@ public class BooleanLogic extends FunctionSet {
@Override
public int getArity() {
- return arity;
+ return 2;
}
@Override
@@ -129,12 +119,10 @@ public class BooleanLogic extends FunctionSet {
}
}
- public static class Nand extends Function {
- private int arity = 2;
-
+ public static class Nand extends Function {
@Override
public Boolean run(Connection... connections) {
- if (connections.length < arity) {
+ if (connections.length < 2) {
throw new InvalidArgumentsException("Not enough connections were given.");
} else {
Boolean arg1 = ((Boolean) connections[0].getValue());
@@ -147,7 +135,7 @@ public class BooleanLogic extends FunctionSet {
@Override
public int getArity() {
- return arity;
+ return 2;
}
@Override
@@ -156,12 +144,10 @@ public class BooleanLogic extends FunctionSet {
}
}
- public static class Nor extends Function {
- private int arity = 2;
-
+ public static class Nor extends Function {
@Override
public Boolean run(Connection... connections) {
- if (connections.length < arity) {
+ if (connections.length < 2) {
throw new InvalidArgumentsException("Not enough connections were given.");
} else {
Boolean arg1 = ((Boolean) connections[0].getValue());
@@ -174,7 +160,7 @@ public class BooleanLogic extends FunctionSet {
@Override
public int getArity() {
- return arity;
+ return 2;
}
@Override
@@ -183,12 +169,10 @@ public class BooleanLogic extends FunctionSet {
}
}
- public static class Xnor extends Function {
- private int arity = 2;
-
+ public static class Xnor extends Function {
@Override
public Boolean run(Connection... connections) {
- if (connections.length < arity) {
+ if (connections.length < 2) {
throw new InvalidArgumentsException("Not enough connections were given.");
} else {
Boolean arg1 = ((Boolean) connections[0].getValue());
@@ -201,7 +185,7 @@ public class BooleanLogic extends FunctionSet {
@Override
public int getArity() {
- return arity;
+ return 2;
}
@Override
diff --git a/src/jcgp/backend/function/FunctionSet.java b/src/jcgp/backend/function/FunctionSet.java
index 4470ac8..78801fc 100644
--- a/src/jcgp/backend/function/FunctionSet.java
+++ b/src/jcgp/backend/function/FunctionSet.java
@@ -1,6 +1,7 @@
package jcgp.backend.function;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Iterator;
@@ -11,7 +12,7 @@ import java.util.Iterator;
*/
public abstract class FunctionSet {
protected Function[] functionList;
- protected ArrayList<Function> allowedFunctions;
+ protected ArrayList<Integer> allowedFunctions;
protected String name;
public int getAllowedFunctionCount() {
@@ -23,7 +24,7 @@ public abstract class FunctionSet {
}
public Function getAllowedFunction(int index) {
- return allowedFunctions.get(index);
+ return functionList[allowedFunctions.get(index)];
}
public Function getFunction(int index) {
@@ -32,7 +33,7 @@ public abstract class FunctionSet {
public int getMaxArity(){
int arity = 0;
- for (Function function : allowedFunctions) {
+ for (Function function : functionList) {
if (function.getArity() > arity) {
arity = function.getArity();
}
@@ -46,9 +47,9 @@ public abstract class FunctionSet {
public void disableFunction(int index) {
if (index < functionList.length) {
- for (Iterator<Function> iterator = allowedFunctions.iterator(); iterator.hasNext();) {
- Function function = (Function) iterator.next();
- if (function == functionList[index]) {
+ for (Iterator<Integer> iterator = allowedFunctions.iterator(); iterator.hasNext();) {
+ int function = iterator.next();
+ if (function == index) {
iterator.remove();
}
}
@@ -58,8 +59,9 @@ public abstract class FunctionSet {
}
public void enableFunction(int index) {
- if (!allowedFunctions.contains(functionList[index])) {
- allowedFunctions.add(functionList[index]);
+ if (!allowedFunctions.contains(index)) {
+ allowedFunctions.add(index);
+ Collections.sort(allowedFunctions);
}
}
@@ -69,6 +71,18 @@ public abstract class FunctionSet {
}
public boolean isEnabled(Function f) {
- return allowedFunctions.contains(f);
+ for (int i = 0; i < allowedFunctions.size(); i++) {
+ if (functionList[allowedFunctions.get(i)] == f) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected void enableAll() {
+ allowedFunctions = new ArrayList<Integer>();
+ for (int i = 0; i < functionList.length; i++) {
+ allowedFunctions.add(i);
+ }
}
} \ No newline at end of file
diff --git a/src/jcgp/backend/function/Arithmetic.java b/src/jcgp/backend/function/IntegerArithmetic.java
index 6971663..c08a72a 100644
--- a/src/jcgp/backend/function/Arithmetic.java
+++ b/src/jcgp/backend/function/IntegerArithmetic.java
@@ -1,31 +1,25 @@
package jcgp.backend.function;
-import java.util.ArrayList;
-import java.util.Arrays;
-
import jcgp.backend.exceptions.InvalidArgumentsException;
import jcgp.backend.population.Connection;
-public class Arithmetic extends FunctionSet {
+public class IntegerArithmetic extends FunctionSet {
- public Arithmetic() {
- name = "Arithmetic";
+ public IntegerArithmetic() {
+ name = "Integer Arithmetic";
functionList = new Function[]{
new Addition(),
new Subtraction(),
new Multiplication(),
new Division()};
- allowedFunctions = new ArrayList<Function>(Arrays.asList(functionList));
+ enableAll();
}
public static class Addition extends Function {
-
- private int arity = 2;
-
@Override
public Integer run(Connection... connections) {
- if (connections.length < arity) {
+ if (connections.length < 2) {
throw new InvalidArgumentsException("Not enough connections were given.");
} else {
Integer arg1 = ((Integer) connections[0].getValue());
@@ -38,7 +32,7 @@ public class Arithmetic extends FunctionSet {
@Override
public int getArity() {
- return arity;
+ return 2;
}
@Override
@@ -48,12 +42,9 @@ public class Arithmetic extends FunctionSet {
}
public static class Subtraction extends Function {
-
- private int arity = 2;
-
@Override
public Integer run(Connection... connections) {
- if (connections.length < arity) {
+ if (connections.length < 2) {
throw new InvalidArgumentsException("Not enough connections were given.");
} else {
Integer arg1 = ((Integer) connections[0].getValue());
@@ -66,7 +57,7 @@ public class Arithmetic extends FunctionSet {
@Override
public int getArity() {
- return arity;
+ return 2;
}
@Override
@@ -76,12 +67,9 @@ public class Arithmetic extends FunctionSet {
}
public static class Multiplication extends Function {
-
- private int arity = 2;
-
@Override
public Integer run(Connection... connections) {
- if (connections.length < arity) {
+ if (connections.length < 2) {
throw new InvalidArgumentsException("Not enough connections were given.");
} else {
Integer arg1 = ((Integer) connections[0].getValue());
@@ -94,7 +82,7 @@ public class Arithmetic extends FunctionSet {
@Override
public int getArity() {
- return arity;
+ return 2;
}
@Override
@@ -104,12 +92,9 @@ public class Arithmetic extends FunctionSet {
}
public static class Division extends Function {
-
- private int arity = 2;
-
@Override
public Integer run(Connection... connections) {
- if (connections.length < arity) {
+ if (connections.length < 2) {
throw new InvalidArgumentsException("Not enough connections were given.");
} else {
Integer arg1 = ((Integer) connections[0].getValue());
@@ -127,7 +112,7 @@ public class Arithmetic extends FunctionSet {
@Override
public int getArity() {
- return arity;
+ return 2;
}
@Override
diff --git a/src/jcgp/backend/modules/Module.java b/src/jcgp/backend/modules/Module.java
index 82c3d80..f2b91b0 100644
--- a/src/jcgp/backend/modules/Module.java
+++ b/src/jcgp/backend/modules/Module.java
@@ -1,11 +1,9 @@
package jcgp.backend.modules;
-import jcgp.JCGP.Resources;
-import jcgp.backend.parameters.Parameter;
+import jcgp.backend.resources.parameters.Parameter;
public interface Module {
public Parameter[] getLocalParameters();
- public ModuleStatus getStatus(Resources resources);
}
diff --git a/src/jcgp/backend/modules/ModuleStatus.java b/src/jcgp/backend/modules/ModuleStatus.java
deleted file mode 100644
index fec8490..0000000
--- a/src/jcgp/backend/modules/ModuleStatus.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package jcgp.backend.modules;
-
-public enum ModuleStatus {
- ERROR, WARNING, READY;
-
- private String details;
-
- public void setDetails(String details) {
- this.details = details;
- }
-
- public String getDetails() {
- return details;
- }
-
-}
diff --git a/src/jcgp/backend/modules/ea/EvolutionaryAlgorithm.java b/src/jcgp/backend/modules/ea/EvolutionaryAlgorithm.java
index 7719111..3aca104 100644
--- a/src/jcgp/backend/modules/ea/EvolutionaryAlgorithm.java
+++ b/src/jcgp/backend/modules/ea/EvolutionaryAlgorithm.java
@@ -1,9 +1,9 @@
package jcgp.backend.modules.ea;
-import jcgp.JCGP.Resources;
import jcgp.backend.modules.Module;
import jcgp.backend.modules.mutator.Mutator;
import jcgp.backend.population.Population;
+import jcgp.backend.resources.Resources;
public interface EvolutionaryAlgorithm extends Module {
diff --git a/src/jcgp/backend/modules/ea/MuPlusLambda.java b/src/jcgp/backend/modules/ea/MuPlusLambda.java
index ad8c5d8..0d16111 100644
--- a/src/jcgp/backend/modules/ea/MuPlusLambda.java
+++ b/src/jcgp/backend/modules/ea/MuPlusLambda.java
@@ -1,13 +1,12 @@
package jcgp.backend.modules.ea;
-import jcgp.JCGP.Resources;
-import jcgp.backend.modules.ModuleStatus;
import jcgp.backend.modules.mutator.Mutator;
-import jcgp.backend.parameters.BooleanParameter;
-import jcgp.backend.parameters.IntegerParameter;
-import jcgp.backend.parameters.Parameter;
-import jcgp.backend.parameters.ParameterStatus;
import jcgp.backend.population.Population;
+import jcgp.backend.resources.Resources;
+import jcgp.backend.resources.parameters.BooleanParameter;
+import jcgp.backend.resources.parameters.IntegerParameter;
+import jcgp.backend.resources.parameters.Parameter;
+import jcgp.backend.resources.parameters.ParameterStatus;
/**
* (μ + λ) EA.
@@ -62,8 +61,7 @@ public class MuPlusLambda implements EvolutionaryAlgorithm {
@Override
public void evolve(Population population, Mutator mutator, Resources resources) {
- // TODO actually use parents and offspring
- // select fittest chromosome
+ // select fittest chromosomes
fittestChromosome = 0;
for (int i = 1; i < resources.getInt("popSize"); i++) {
@@ -79,6 +77,7 @@ public class MuPlusLambda implements EvolutionaryAlgorithm {
mutator.mutate(population.getChromosome(i), resources);
}
}
+
}
@Override
@@ -95,10 +94,5 @@ public class MuPlusLambda implements EvolutionaryAlgorithm {
public String toString() {
return "(μ + λ)";
}
-
- @Override
- public ModuleStatus getStatus(Resources resources) {
- return ModuleStatus.READY;
- }
}
diff --git a/src/jcgp/backend/modules/ea/TournamentSelection.java b/src/jcgp/backend/modules/ea/TournamentSelection.java
index 32ac54d..baf6704 100644
--- a/src/jcgp/backend/modules/ea/TournamentSelection.java
+++ b/src/jcgp/backend/modules/ea/TournamentSelection.java
@@ -2,12 +2,11 @@ package jcgp.backend.modules.ea;
import java.util.HashMap;
-import jcgp.JCGP.Resources;
-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.Population;
+import jcgp.backend.resources.Resources;
+import jcgp.backend.resources.parameters.IntegerParameter;
+import jcgp.backend.resources.parameters.Parameter;
public class TournamentSelection implements EvolutionaryAlgorithm {
@@ -51,9 +50,4 @@ public class TournamentSelection implements EvolutionaryAlgorithm {
public String toString() {
return "Tournament";
}
-
- @Override
- public ModuleStatus getStatus(Resources resources) {
- return null;
- }
}
diff --git a/src/jcgp/backend/modules/fitness/FitnessFunction.java b/src/jcgp/backend/modules/fitness/FitnessFunction.java
index ffce9b7..d3b76cb 100644
--- a/src/jcgp/backend/modules/fitness/FitnessFunction.java
+++ b/src/jcgp/backend/modules/fitness/FitnessFunction.java
@@ -1,8 +1,8 @@
package jcgp.backend.modules.fitness;
-import jcgp.JCGP.Resources;
import jcgp.backend.modules.Module;
import jcgp.backend.population.Population;
+import jcgp.backend.resources.Resources;
public interface FitnessFunction extends Module {
diff --git a/src/jcgp/backend/modules/fitness/TestCase.java b/src/jcgp/backend/modules/fitness/TestCase.java
deleted file mode 100644
index 23f7ecf..0000000
--- a/src/jcgp/backend/modules/fitness/TestCase.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package jcgp.backend.modules.fitness;
-
-public class TestCase {
-
- private Object[] inputs;
- private Object[] outputs;
-
- public TestCase(Object[] inputs, Object[] outputs) {
- this.inputs = inputs;
- this.outputs = outputs;
- }
-
- public Object getInput(int index) {
- return inputs[index];
- }
-
- public Object getOutput(int index) {
- return outputs[index];
- }
-
- public Object[] getInputs() {
- return inputs;
- }
-
- public Object[] getOutputs() {
- return outputs;
- }
-
-}
diff --git a/src/jcgp/backend/modules/fitness/TestCaseEvaluator.java b/src/jcgp/backend/modules/fitness/TestCaseEvaluator.java
deleted file mode 100644
index 5ff6973..0000000
--- a/src/jcgp/backend/modules/fitness/TestCaseEvaluator.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package jcgp.backend.modules.fitness;
-
-import jcgp.JCGP.Resources;
-import jcgp.backend.modules.ModuleStatus;
-import jcgp.backend.parameters.Parameter;
-import jcgp.backend.population.Population;
-
-public class TestCaseEvaluator implements FitnessFunction {
-
- @Override
- public void evaluate(Population population, Resources resources) {
- // for every chromosome in the population
- for (int i = 0; i < resources.getInt("popSize"); i++) {
- int fitness = 0;
- // for every test case
- for (int t = 0; t < resources.getTestCaseCount(); t++) {
- population.getChromosome(i).setInputs(resources.getTestCase(t).getInputs());
- // check every output
- for (int o = 0; o < resources.getInt("outputs"); o++) {
- if (population.getChromosome(i).getOutput(o).calculate() == resources.getTestCase(t).getOutput(o)) {
- fitness++;
- }
- }
- }
- population.getChromosome(i).setFitness(fitness);
- }
- }
-
- @Override
- public Parameter[] getLocalParameters() {
- return null;
- }
-
- @Override
- public String toString() {
- return "Test case";
- }
-
- @Override
- public ModuleStatus getStatus(Resources resources) {
- return null;
- }
-}
diff --git a/src/jcgp/backend/modules/fitness/testcase/TestCaseEvaluator.java b/src/jcgp/backend/modules/fitness/testcase/TestCaseEvaluator.java
new file mode 100644
index 0000000..51676e3
--- /dev/null
+++ b/src/jcgp/backend/modules/fitness/testcase/TestCaseEvaluator.java
@@ -0,0 +1,75 @@
+package jcgp.backend.modules.fitness.testcase;
+
+import java.util.ArrayList;
+
+import jcgp.backend.modules.fitness.FitnessFunction;
+import jcgp.backend.population.Population;
+import jcgp.backend.resources.Resources;
+
+/**
+ *
+ * This fitness function module implements a simple test case evaluator.
+ *
+ * A TestCase object is a
+ *
+ *
+ * @author Eduardo Pedroni
+ *
+ */
+public abstract class TestCaseEvaluator implements FitnessFunction {
+
+ public static class TestCase<T> {
+
+ private T[] inputs;
+ private T[] outputs;
+
+ public TestCase(T[] inputs, T[] outputs) {
+ this.inputs = inputs;
+ this.outputs = outputs;
+ }
+
+ public T getInput(int index) {
+ return inputs[index];
+ }
+
+ public T getOutput(int index) {
+ return outputs[index];
+ }
+
+ public T[] getInputs() {
+ return inputs;
+ }
+
+ public T[] getOutputs() {
+ return outputs;
+ }
+ }
+
+ protected ArrayList<TestCase> testCases;
+
+ @Override
+ public void evaluate(Population population, Resources resources) {
+ // for every chromosome in the population
+ for (int i = 0; i < resources.getInt("popSize"); i++) {
+ // assume an initial fitness of 0
+ int fitness = 0;
+ // for each test case
+ for (int t = 0; t < testCases.size(); t++) {
+ population.getChromosome(i).setInputs(testCases.get(t).getInputs());
+ // check each output
+ for (int o = 0; o < resources.getInt("outputs"); o++) {
+ if (population.getChromosome(i).getOutput(o).calculate() == testCases.get(t).getOutput(o)) {
+ fitness++;
+ }
+ }
+ }
+ // assign the resulting fitness to the respective individual
+ population.getChromosome(i).setFitness(fitness);
+ }
+ }
+
+ public int getMaxFitness() {
+ return 0;
+ }
+}
+
diff --git a/src/jcgp/backend/modules/mutator/Mutator.java b/src/jcgp/backend/modules/mutator/Mutator.java
index fd7cd27..ffdd35c 100644
--- a/src/jcgp/backend/modules/mutator/Mutator.java
+++ b/src/jcgp/backend/modules/mutator/Mutator.java
@@ -1,8 +1,8 @@
package jcgp.backend.modules.mutator;
-import jcgp.JCGP.Resources;
import jcgp.backend.modules.Module;
import jcgp.backend.population.Chromosome;
+import jcgp.backend.resources.Resources;
public interface Mutator extends Module {
diff --git a/src/jcgp/backend/modules/mutator/PointMutator.java b/src/jcgp/backend/modules/mutator/PointMutator.java
index cdac8bb..54d5f3d 100644
--- a/src/jcgp/backend/modules/mutator/PointMutator.java
+++ b/src/jcgp/backend/modules/mutator/PointMutator.java
@@ -1,33 +1,39 @@
package jcgp.backend.modules.mutator;
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.backend.resources.Resources;
+import jcgp.backend.resources.parameters.DoubleParameter;
+import jcgp.backend.resources.parameters.Parameter;
+import jcgp.backend.resources.parameters.ParameterStatus;
public class PointMutator implements Mutator {
private DoubleParameter mutationRate;
- private ModuleStatus status = ModuleStatus.READY;
-
- public PointMutator() {
- mutationRate = new DoubleParameter(0.5, "Percent mutation", false, false) {
+ public PointMutator(final Resources resources) {
+ mutationRate = new DoubleParameter(50, "Percent mutation", false, false) {
@Override
public void validate(double newValue) {
- // TODO this
+ if (newValue <= 0 || newValue > 100) {
+ status = ParameterStatus.INVALID;
+ status.setDetails("Mutation rate must be > 0 and <= 100");
+ } else if ((int) ((newValue / 100) * resources.getDouble("nodes")) <= 0) {
+ status = ParameterStatus.WARNING;
+ status.setDetails("With mutation rate " + mutationRate.get() + ", 0 genes will be mutated.");
+ } else {
+ status = ParameterStatus.VALID;
+ }
}
};
}
@Override
public void mutate(Chromosome chromosome, Resources resources) {
- int mutations = (int) Math.ceil(((mutationRate.get()) * ((((resources.getDouble("nodes")) + (resources.getDouble("outputs")))) / (double) 100)));
+ int mutations = (int) ((mutationRate.get()) * ((((resources.getDouble("nodes")) + (resources.getDouble("outputs")))) / 100));
for (int i = 0; i < mutations; i++) {
MutableElement m = chromosome.getRandomMutableElement();
@@ -55,18 +61,4 @@ public class PointMutator implements Mutator {
return "Point mutation";
}
- @Override
- public ModuleStatus getStatus(Resources resources) {
- if (mutationRate.get() <= 0 || mutationRate.get() > 100) {
- status = ModuleStatus.ERROR;
- status.setDetails("Mutation rate must be > 0 and <= 100");
- } else if ((int) ((mutationRate.get() / 100) * resources.getDouble("nodes")) > 0) {
- status = ModuleStatus.WARNING;
- status.setDetails("With mutation rate " + mutationRate.get() + ", no mutations will occur.");
- } else {
- status = ModuleStatus.READY;
- status.setDetails("");
- }
- return status;
- }
}
diff --git a/src/jcgp/backend/population/Chromosome.java b/src/jcgp/backend/population/Chromosome.java
index c7493b9..d438375 100644
--- a/src/jcgp/backend/population/Chromosome.java
+++ b/src/jcgp/backend/population/Chromosome.java
@@ -2,8 +2,8 @@ package jcgp.backend.population;
import java.util.ArrayList;
-import jcgp.JCGP.Resources;
import jcgp.backend.exceptions.ParameterMismatchException;
+import jcgp.backend.resources.Resources;
public class Chromosome {
diff --git a/src/jcgp/backend/population/Node.java b/src/jcgp/backend/population/Node.java
index f1d37a1..6960ded 100644
--- a/src/jcgp/backend/population/Node.java
+++ b/src/jcgp/backend/population/Node.java
@@ -37,7 +37,7 @@ public class Node extends Gene implements MutableElement, Connection {
public void initialise(Function newFunction, Connection ... newConnections) throws InsufficientConnectionsException {
function = newFunction;
- if (newConnections.length == function.getArity()) {
+ if (newConnections.length == chromosome.getResources().getInt("arity")) {
connections = newConnections;
} else {
throw new InsufficientConnectionsException();
diff --git a/src/jcgp/backend/population/Population.java b/src/jcgp/backend/population/Population.java
index 7b62d27..d2e6058 100644
--- a/src/jcgp/backend/population/Population.java
+++ b/src/jcgp/backend/population/Population.java
@@ -1,7 +1,6 @@
package jcgp.backend.population;
-import jcgp.JCGP.Resources;
-
+import jcgp.backend.resources.Resources;
public class Population {
@@ -56,7 +55,6 @@ public class Population {
return chromosomes[resources.getRandomInt(chromosomes.length)];
}
-
/**
* Copy a chromosome into a different position.
* After this returns, the target chromosome has
@@ -75,4 +73,6 @@ public class Population {
}
+
+
}
diff --git a/src/jcgp/gui/console/Console.java b/src/jcgp/backend/resources/Console.java
index 63c7f5b..6bbd5ba 100644
--- a/src/jcgp/gui/console/Console.java
+++ b/src/jcgp/backend/resources/Console.java
@@ -1,4 +1,4 @@
-package jcgp.gui.console;
+package jcgp.backend.resources;
public interface Console {
diff --git a/src/jcgp/backend/resources/ModifiableResources.java b/src/jcgp/backend/resources/ModifiableResources.java
new file mode 100644
index 0000000..3e6b55e
--- /dev/null
+++ b/src/jcgp/backend/resources/ModifiableResources.java
@@ -0,0 +1,42 @@
+package jcgp.backend.resources;
+
+import jcgp.backend.resources.parameters.BooleanParameter;
+import jcgp.backend.resources.parameters.DoubleParameter;
+import jcgp.backend.resources.parameters.IntegerParameter;
+
+/**
+ *
+ * This subclass of Resources allows modifications to be made.
+ * A read-only cast of this class is passed to modules for safety,
+ * and only classes with access to a JCGP instance may modify
+ * the resources.
+ *
+ * @author eddy
+ *
+ */
+public class ModifiableResources extends Resources {
+
+ public ModifiableResources() {
+ super();
+ }
+
+ 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 void setFunctionSet(int index) {
+ functionSet = functionSets[index];
+ set("arity", functionSet.getMaxArity());
+ }
+
+ public void setConsole(Console console) {
+ this.console = console;
+ }
+
+}
diff --git a/src/jcgp/backend/resources/Resources.java b/src/jcgp/backend/resources/Resources.java
new file mode 100644
index 0000000..c1c3e4c
--- /dev/null
+++ b/src/jcgp/backend/resources/Resources.java
@@ -0,0 +1,310 @@
+package jcgp.backend.resources;
+
+import java.util.HashMap;
+import java.util.Random;
+
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import jcgp.backend.function.BitwiseLogic;
+import jcgp.backend.function.BooleanLogic;
+import jcgp.backend.function.Function;
+import jcgp.backend.function.FunctionSet;
+import jcgp.backend.function.IntegerArithmetic;
+import jcgp.backend.resources.parameters.BooleanParameter;
+import jcgp.backend.resources.parameters.DoubleParameter;
+import jcgp.backend.resources.parameters.IntegerParameter;
+import jcgp.backend.resources.parameters.Parameter;
+import jcgp.backend.resources.parameters.ParameterStatus;
+
+/**
+ *
+ * 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 class Resources {
+ protected HashMap<String, Parameter> parameters = new HashMap<String, Parameter>();
+
+ protected Random numberGenerator = new Random();
+
+ // function sets
+ protected FunctionSet[] functionSets = new FunctionSet[] {
+ new IntegerArithmetic(),
+ new BitwiseLogic(),
+ new BooleanLogic() };
+ protected FunctionSet functionSet = functionSets[0];
+
+ // GUI console
+ protected Console console;
+
+ public Resources() {
+ createBaseParameters();
+ }
+
+ 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 ((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 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(((IntegerParameter) parameters.get("rows")).valueProperty().multiply(((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(functionSet.getMaxArity(), "Max arity", true, false) {
+ @Override
+ public void validate(int newValue) {
+ // blank
+ }
+ });
+
+ IntegerParameter seed = new IntegerParameter(1234, "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());
+ }
+ });
+ numberGenerator.setSeed(seed.get());
+ 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;
+ }
+ }
+ });
+ }
+
+ /*
+ * 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);
+ }
+
+ /**
+ * @return the functionSets
+ */
+ public FunctionSet[] getFunctionSets() {
+ return functionSets;
+ }
+
+ /**
+ * @return the functionSet
+ */
+ public FunctionSet getFunctionSet() {
+ return functionSet;
+ }
+
+// /*
+// * Test cases
+// */
+// public TestCase getTestCase(int index) {
+// return testCases[index];
+// }
+//
+// public int getTestCaseCount() {
+// return testCases.length;
+// }
+
+ /*
+ * Console functionality
+ */
+ 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);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/jcgp/backend/parameters/BooleanParameter.java b/src/jcgp/backend/resources/parameters/BooleanParameter.java
index 43825be..cd17649 100644
--- a/src/jcgp/backend/parameters/BooleanParameter.java
+++ b/src/jcgp/backend/resources/parameters/BooleanParameter.java
@@ -1,4 +1,4 @@
-package jcgp.backend.parameters;
+package jcgp.backend.resources.parameters;
import javafx.beans.property.SimpleBooleanProperty;
@@ -35,6 +35,7 @@ public abstract class BooleanParameter extends Parameter {
public abstract void validate(boolean newValue);
+ @Override
public SimpleBooleanProperty valueProperty() {
return value;
}
diff --git a/src/jcgp/backend/parameters/DoubleParameter.java b/src/jcgp/backend/resources/parameters/DoubleParameter.java
index 53551f5..8464c83 100644
--- a/src/jcgp/backend/parameters/DoubleParameter.java
+++ b/src/jcgp/backend/resources/parameters/DoubleParameter.java
@@ -1,4 +1,4 @@
-package jcgp.backend.parameters;
+package jcgp.backend.resources.parameters;
import javafx.beans.property.SimpleDoubleProperty;
@@ -26,6 +26,7 @@ public abstract class DoubleParameter extends Parameter {
}
}
+ @Override
public SimpleDoubleProperty valueProperty() {
return value;
}
diff --git a/src/jcgp/backend/parameters/IntegerParameter.java b/src/jcgp/backend/resources/parameters/IntegerParameter.java
index 68095d9..2a7b2a7 100644
--- a/src/jcgp/backend/parameters/IntegerParameter.java
+++ b/src/jcgp/backend/resources/parameters/IntegerParameter.java
@@ -1,4 +1,4 @@
-package jcgp.backend.parameters;
+package jcgp.backend.resources.parameters;
import javafx.beans.property.SimpleIntegerProperty;
@@ -27,6 +27,7 @@ public abstract class IntegerParameter extends Parameter {
}
}
+ @Override
public SimpleIntegerProperty valueProperty() {
return value;
}
diff --git a/src/jcgp/backend/parameters/Parameter.java b/src/jcgp/backend/resources/parameters/Parameter.java
index ddd5d5b..7e12ff8 100644
--- a/src/jcgp/backend/parameters/Parameter.java
+++ b/src/jcgp/backend/resources/parameters/Parameter.java
@@ -1,4 +1,4 @@
-package jcgp.backend.parameters;
+package jcgp.backend.resources.parameters;
import javafx.beans.property.Property;
diff --git a/src/jcgp/backend/parameters/ParameterStatus.java b/src/jcgp/backend/resources/parameters/ParameterStatus.java
index 86abe33..11da4c2 100644
--- a/src/jcgp/backend/parameters/ParameterStatus.java
+++ b/src/jcgp/backend/resources/parameters/ParameterStatus.java
@@ -1,4 +1,4 @@
-package jcgp.backend.parameters;
+package jcgp.backend.resources.parameters;
public enum ParameterStatus {
INVALID, WARNING, WARNING_RESET, VALID;
diff --git a/src/jcgp/backend/tests/ChromosomeTests.java b/src/jcgp/backend/tests/ChromosomeTests.java
index 1cd067e..a16ba75 100644
--- a/src/jcgp/backend/tests/ChromosomeTests.java
+++ b/src/jcgp/backend/tests/ChromosomeTests.java
@@ -2,13 +2,13 @@ package jcgp.backend.tests;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import jcgp.JCGP.Resources;
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 jcgp.backend.resources.ModifiableResources;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -40,11 +40,11 @@ import org.junit.Test;
public class ChromosomeTests {
private Chromosome chromosome;
- private static Resources resources;
+ private static ModifiableResources resources;
@BeforeClass
public static void setUpBeforeClass() {
- resources = new Resources();
+ resources = new ModifiableResources();
}
@Before
diff --git a/src/jcgp/backend/tests/NodeTests.java b/src/jcgp/backend/tests/NodeTests.java
index 7121e81..2294816 100644
--- a/src/jcgp/backend/tests/NodeTests.java
+++ b/src/jcgp/backend/tests/NodeTests.java
@@ -1,12 +1,13 @@
package jcgp.backend.tests;
import static org.junit.Assert.assertTrue;
-import jcgp.JCGP.Resources;
-import jcgp.backend.function.Arithmetic;
+import jcgp.backend.exceptions.InvalidArgumentsException;
import jcgp.backend.function.Function;
+import jcgp.backend.function.IntegerArithmetic;
import jcgp.backend.population.Chromosome;
import jcgp.backend.population.Connection;
import jcgp.backend.population.Node;
+import jcgp.backend.resources.Resources;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -48,7 +49,7 @@ public class NodeTests {
public void setUp() throws Exception {
node = new Node(chromosome, 0, 0, resources.getInt("arity"));
// make node with anonymous addition function and hard-coded value connections
- node.initialise(new Arithmetic.Addition(),
+ node.initialise(new IntegerArithmetic.Addition(),
new Connection[]{new Connection() {
@Override
@@ -126,7 +127,7 @@ public class NodeTests {
((int) node.getValue()) == arg1 + arg2);
// put in a different function, check the output has changed appropriately
- node.setFunction(new Arithmetic.Subtraction());
+ node.setFunction(new IntegerArithmetic.Subtraction());
assertTrue("Node did not return expected value (difference of arguments).", ((Integer) node.getValue()) == arg1 - arg2);
@@ -166,7 +167,28 @@ public class NodeTests {
}
};
- node.initialise(null, conn0, conn1);
+
+ Function function = new Function() {
+ @Override
+ public Object run(Connection... connections)
+ throws InvalidArgumentsException {
+ // blank
+ return null;
+ }
+
+ @Override
+ public int getArity() {
+ return 2;
+ }
+
+ @Override
+ public String getName() {
+ // blank
+ return null;
+ }
+ };
+
+ node.initialise(function, conn0, conn1);
assertTrue("Connection 0 is incorrect.", node.getConnection(0) == conn0);
assertTrue("Connection 1 is incorrect.", node.getConnection(1) == conn1);
diff --git a/src/jcgp/backend/tests/OutputTests.java b/src/jcgp/backend/tests/OutputTests.java
index 7ff8a4a..b2bc7ec 100644
--- a/src/jcgp/backend/tests/OutputTests.java
+++ b/src/jcgp/backend/tests/OutputTests.java
@@ -1,10 +1,10 @@
package jcgp.backend.tests;
import static org.junit.Assert.assertTrue;
-import jcgp.JCGP.Resources;
import jcgp.backend.population.Chromosome;
import jcgp.backend.population.Connection;
import jcgp.backend.population.Output;
+import jcgp.backend.resources.Resources;
import org.junit.Before;
import org.junit.BeforeClass;
diff --git a/src/jcgp/backend/tests/PopulationTests.java b/src/jcgp/backend/tests/PopulationTests.java
index 51b5168..31df8b9 100644
--- a/src/jcgp/backend/tests/PopulationTests.java
+++ b/src/jcgp/backend/tests/PopulationTests.java
@@ -1,9 +1,9 @@
package jcgp.backend.tests;
import static org.junit.Assert.assertTrue;
-import jcgp.JCGP.Resources;
import jcgp.backend.population.Chromosome;
import jcgp.backend.population.Population;
+import jcgp.backend.resources.Resources;
import org.junit.Before;
import org.junit.BeforeClass;
diff --git a/src/jcgp/gui/GUI.java b/src/jcgp/gui/GUI.java
index f7aa25d..8f28884 100644
--- a/src/jcgp/gui/GUI.java
+++ b/src/jcgp/gui/GUI.java
@@ -5,14 +5,16 @@ import javafx.application.Platform;
import javafx.concurrent.Service;
import javafx.concurrent.Task;
import javafx.scene.Scene;
-import javafx.scene.control.Tab;
-import javafx.scene.control.TabPane;
-import javafx.scene.control.TabPane.TabClosingPolicy;
import javafx.scene.layout.BorderPane;
+import javafx.scene.layout.Pane;
import javafx.stage.Stage;
import jcgp.JCGP;
-import jcgp.JCGP.Resources;
+import jcgp.backend.resources.Resources;
import jcgp.gui.console.GUIConsole;
+import jcgp.gui.dragresize.HorizontalDragResize;
+import jcgp.gui.dragresize.VerticalDragResize;
+import jcgp.gui.population.FunctionSelector;
+import jcgp.gui.population.PopulationPane;
import jcgp.gui.settings.SettingsPane;
public class GUI extends Application {
@@ -28,10 +30,6 @@ public class GUI extends Application {
public static final String GOOD_SELECTION_COLOUR = "#38C25B";
public static final String NEUTRAL_SELECTION_COLOUR = "#FFEF73";
public static final String BAD_SELECTION_COLOUR = "#FF5C5C";
-
- public static final String INVALID_PARAMETER_STYLE = "-fx-border-color: C9C9C9; -fx-border-radius: 2; -fx-padding: 0; -fx-background-color: " + BAD_SELECTION_COLOUR;
- public static final String WARNING_PARAMETER_STYLE = "-fx-border-color: C9C9C9; -fx-border-radius: 2; -fx-padding: 0; -fx-background-color: " + NEUTRAL_SELECTION_COLOUR;
- public static final String VALID_PARAMETER_STYLE = "-fx-border-color: C9C9C9; -fx-border-radius: 2; -fx-padding: 0; -fx-background-color: " + NEUTRAL_COLOUR;
/* Sizes and distances */
public static final double RESIZE_MARGIN = 5.0;
@@ -41,17 +39,16 @@ public class GUI extends Application {
public static final double WRAP_WIDTH = 90;
- private static JCGP cgp;
- public static Resources resources;
+ public static final JCGP jcgp = new JCGP();
+ public static final Resources resources = jcgp.getResources();
- private BorderPane leftPane;
- private BorderPane window;
+ public static final FunctionSelector functionSelector = new FunctionSelector(resources.getFunctionSet());
- private ChromosomePane[] chromosomes;
- private TabPane chromosomeTabs;
+ private PopulationPane populationPane;
private GUIConsole console = new GUIConsole();
- private SettingsPane settings;
+
+ private SettingsPane settingsPane;
private boolean evolving = false;
@@ -63,14 +60,14 @@ public class GUI extends Application {
Task<Void> t = new Task<Void>() {
@Override
protected Void call() throws Exception {
- while (!isCancelled() && !cgp.isFinished()) {
+ while (!isCancelled() && !jcgp.isFinished()) {
synchronized (printLock) {
Platform.runLater(consoleFlush);
- cgp.nextGeneration();
+ jcgp.nextGeneration();
printLock.wait();
}
}
- if (cgp.isFinished()) {
+ if (jcgp.isFinished()) {
Platform.runLater(new Runnable() {
@Override
public void run() {
@@ -96,84 +93,55 @@ public class GUI extends Application {
};
public static void main(String[] args) {
- cgp = new JCGP();
- resources = cgp.getResources();
+// jcgp = new JCGP();
+// resources = jcgp.getResources();
+//
+// functionSelector =
launch();
}
@Override
public void start(Stage primaryStage) throws Exception {
- resources.setConsole(console);
+ jcgp.setConsole(console);
/*
* Instantiate the various GUI elements here.
*
*
*/
+ BorderPane leftFrame = new BorderPane();
- leftPane = new BorderPane();
+ populationPane = new PopulationPane(jcgp);
- chromosomeTabs = new TabPane();
- chromosomeTabs.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE);
- makeChromosomeTabPane();
+ settingsPane = new SettingsPane(jcgp, this);
- settings = new SettingsPane(cgp, this);
+ HorizontalDragResize.makeDragResizable(settingsPane);
+ VerticalDragResize.makeDragResizable(console);
- leftPane.setCenter(chromosomeTabs);
- leftPane.setBottom(console);
+ leftFrame.setCenter(populationPane);
+ leftFrame.setBottom(console);
- window = new BorderPane();
+ BorderPane experimentLayer = new BorderPane();
- window.setCenter(leftPane);
- window.setRight(settings);
+ experimentLayer.setCenter(leftFrame);
+ experimentLayer.setRight(settingsPane);
primaryStage.setTitle("JCGP");
- primaryStage.setScene(new Scene(window));
+ Pane sceneParent = new Pane();
+ experimentLayer.prefHeightProperty().bind(sceneParent.heightProperty());
+ experimentLayer.prefWidthProperty().bind(sceneParent.widthProperty());
+ sceneParent.getChildren().addAll(experimentLayer, functionSelector);
+
+ primaryStage.setScene(new Scene(sceneParent));
+ primaryStage.setMinWidth(800);
+ primaryStage.setMinHeight(600);
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);
- }
- }
-
- 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 runPause() {
- if (!cgp.isFinished() && settings.areParametersValid()) {
+ if (!jcgp.isFinished() && settingsPane.areParametersValid()) {
if (!evolving) {
runningMode(true);
cgpService.restart();
@@ -185,55 +153,49 @@ public class GUI extends Application {
}
public void step() {
- if (!evolving && !cgp.isFinished() && settings.areParametersValid()) {
- if (settings.isResetRequired()) {
+ if (!evolving && !jcgp.isFinished() && settingsPane.areParametersValid()) {
+ if (settingsPane.isResetRequired()) {
reset();
}
- unlockOutputs();
- Task<Void> task = new Task<Void>() {
- @Override
- protected Void call() throws Exception {
- cgp.nextGeneration();
- Platform.runLater(consoleFlush);
- return null;
- }
- };
- Thread t = new Thread(task);
- t.start();
- try {
- t.join();
- } catch (InterruptedException e) {
- // nothing
- } finally {
- updateNodeGrids();
- relockOutputs();
- }
+ populationPane.unlockOutputs();
+
+ jcgp.nextGeneration();
+ console.flush();
+
+ populationPane.updateGenes();
+ populationPane.relockOutputs();
+
}
}
public void reset() {
- if (!evolving && settings.areParametersValid()) {
- settings.applyParameters();
- cgp.reset();
- makeChromosomeTabPane();
- settings.revalidateParameters();
+ if (!evolving && settingsPane.areParametersValid()) {
+ settingsPane.applyParameters();
+ jcgp.reset();
+ populationPane.remakeTabs(jcgp.getPopulation(), jcgp.getResources());
+ settingsPane.revalidateParameters();
+ console.flush();
}
}
private void runningMode(boolean value) {
- chromosomeTabs.setDisable(value);
- settings.disableSettings(value);
+ populationPane.setDisable(value);
+ settingsPane.runningMode(value);
+
if (value) {
- unlockOutputs();
- settings.getRunButton().setText("Pause");
- if (settings.isResetRequired()) {
+ populationPane.unlockOutputs();
+ if (settingsPane.isResetRequired()) {
reset();
}
} else {
- updateNodeGrids();
- relockOutputs();
- settings.getRunButton().setText("Run");
+ populationPane.updateGenes();
+ populationPane.relockOutputs();
}
evolving = value;
}
+
+ public static void updateFunctionSelector() {
+ functionSelector.remakeFunctions(resources.getFunctionSet());
+ }
+
}
diff --git a/src/jcgp/gui/console/GUIConsole.java b/src/jcgp/gui/console/GUIConsole.java
index d8625f5..694f1a5 100644
--- a/src/jcgp/gui/console/GUIConsole.java
+++ b/src/jcgp/gui/console/GUIConsole.java
@@ -1,15 +1,12 @@
package jcgp.gui.console;
-import javafx.event.EventHandler;
-import javafx.scene.Cursor;
import javafx.scene.control.TextArea;
-import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
+import jcgp.backend.resources.Console;
import jcgp.gui.GUI;
public class GUIConsole extends AnchorPane implements Console {
- private boolean dragging;
private TextArea textArea = new TextArea("Welcome to JCGP!");
private StringBuffer printBuffer = new StringBuffer();
@@ -18,8 +15,6 @@ public class GUIConsole extends AnchorPane implements Console {
super();
textArea.setEditable(false);
- setResizeListeners();
-
AnchorPane.setTopAnchor(textArea, GUI.RESIZE_MARGIN);
AnchorPane.setBottomAnchor(textArea, 0.0);
AnchorPane.setRightAnchor(textArea, 0.0);
@@ -32,62 +27,6 @@ public class GUIConsole extends AnchorPane implements Console {
}
- /**
- *
- */
- private void setResizeListeners() {
- setOnMousePressed(new EventHandler<MouseEvent>() {
- @Override
- public void handle(MouseEvent event) {
- // ignore clicks outside of the draggable margin
- if(isInDraggableZone(event)) {
- dragging = true;
- }
- }
- });
- setOnMouseDragged(new EventHandler<MouseEvent>() {
- @Override
- public void handle(MouseEvent event) {
- if(dragging) {
- double newHeight = getHeight() - event.getY();
- if (newHeight >= getMinHeight()) {
- setPrefHeight(newHeight);
- } else {
- setPrefHeight(getMinHeight());
- }
- }
- }
- });
- setOnMouseMoved(new EventHandler<MouseEvent>() {
- @Override
- public void handle(MouseEvent event) {
- if(isInDraggableZone(event) || dragging) {
- setCursor(Cursor.V_RESIZE);
- }
- else {
- setCursor(Cursor.DEFAULT);
- }
- }
- });
- setOnMouseReleased(new EventHandler<MouseEvent>() {
- @Override
- public void handle(MouseEvent event) {
- dragging = false;
- setCursor(Cursor.DEFAULT);
- }
- });
- textArea.setOnMouseEntered(new EventHandler<MouseEvent>() {
- @Override
- public void handle(MouseEvent event) {
- setCursor(Cursor.DEFAULT);
- }
- });
- }
-
- private boolean isInDraggableZone(MouseEvent event) {
- return event.getY() < (GUI.RESIZE_MARGIN);
- }
-
@Override
public void println(String s) {
printBuffer.append("\n" + s);
diff --git a/src/jcgp/gui/dragresize/HorizontalDragResize.java b/src/jcgp/gui/dragresize/HorizontalDragResize.java
new file mode 100644
index 0000000..d580878
--- /dev/null
+++ b/src/jcgp/gui/dragresize/HorizontalDragResize.java
@@ -0,0 +1,90 @@
+package jcgp.gui.dragresize;
+
+import javafx.event.EventHandler;
+import javafx.scene.Cursor;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.Region;
+import jcgp.gui.GUI;
+
+/**
+ *
+ * http://andrewtill.blogspot.co.uk/2012/12/dragging-to-resize-javafx-region.html
+ *
+ * @author eddy
+ *
+ */
+public class HorizontalDragResize {
+
+ private boolean dragging = false;
+ private final Region region;
+
+ private HorizontalDragResize(Region region) {
+ this.region = region;
+ }
+
+ public static void makeDragResizable(final Region region) {
+ final HorizontalDragResize dr = new HorizontalDragResize(region);
+
+ region.setOnMousePressed(new EventHandler<MouseEvent>() {
+ @Override
+ public void handle(MouseEvent event) {
+ dr.mousePressed(event);
+ }
+ });
+ region.setOnMouseDragged(new EventHandler<MouseEvent>() {
+ @Override
+ public void handle(MouseEvent event) {
+ dr.mouseDragged(event);
+ }
+ });
+ region.setOnMouseMoved(new EventHandler<MouseEvent>() {
+ @Override
+ public void handle(MouseEvent event) {
+ dr.mouseMoved(event);
+ }
+ });
+ region.setOnMouseReleased(new EventHandler<MouseEvent>() {
+ @Override
+ public void handle(MouseEvent event) {
+ dr.mouseReleased();
+ }
+ });
+
+ }
+
+ private void mousePressed(MouseEvent event) {
+ if(isInDraggableZone(event)) {
+ dragging = true;
+ }
+ }
+
+ private void mouseDragged(MouseEvent event) {
+ if(dragging) {
+ double newWidth = region.getWidth() - event.getX();
+ if (newWidth >= region.getMinWidth()) {
+ region.setPrefWidth(newWidth);
+ } else {
+ region.setPrefWidth(region.getMinWidth());
+ }
+ }
+ }
+
+ private void mouseMoved(MouseEvent event) {
+ if(isInDraggableZone(event) || dragging) {
+ region.setCursor(Cursor.H_RESIZE);
+ }
+ else {
+ region.setCursor(Cursor.DEFAULT);
+ }
+ }
+
+ private void mouseReleased() {
+ dragging = false;
+ region.setCursor(Cursor.DEFAULT);
+ }
+
+ private boolean isInDraggableZone(MouseEvent event) {
+ return event.getX() < (GUI.RESIZE_MARGIN);
+ }
+
+}
diff --git a/src/jcgp/gui/dragresize/VerticalDragResize.java b/src/jcgp/gui/dragresize/VerticalDragResize.java
new file mode 100644
index 0000000..32a7526
--- /dev/null
+++ b/src/jcgp/gui/dragresize/VerticalDragResize.java
@@ -0,0 +1,90 @@
+package jcgp.gui.dragresize;
+
+import javafx.event.EventHandler;
+import javafx.scene.Cursor;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.Region;
+import jcgp.gui.GUI;
+
+/**
+ *
+ * http://andrewtill.blogspot.co.uk/2012/12/dragging-to-resize-javafx-region.html
+ *
+ * @author eddy
+ *
+ */
+public class VerticalDragResize {
+
+ private boolean dragging = false;
+ private final Region region;
+
+ private VerticalDragResize(Region region) {
+ this.region = region;
+ }
+
+ public static void makeDragResizable(final Region region) {
+ final VerticalDragResize dr = new VerticalDragResize(region);
+
+ region.setOnMousePressed(new EventHandler<MouseEvent>() {
+ @Override
+ public void handle(MouseEvent event) {
+ dr.mousePressed(event);
+ }
+ });
+ region.setOnMouseDragged(new EventHandler<MouseEvent>() {
+ @Override
+ public void handle(MouseEvent event) {
+ dr.mouseDragged(event);
+ }
+ });
+ region.setOnMouseMoved(new EventHandler<MouseEvent>() {
+ @Override
+ public void handle(MouseEvent event) {
+ dr.mouseMoved(event);
+ }
+ });
+ region.setOnMouseReleased(new EventHandler<MouseEvent>() {
+ @Override
+ public void handle(MouseEvent event) {
+ dr.mouseReleased();
+ }
+ });
+
+ }
+
+ private void mousePressed(MouseEvent event) {
+ if(isInDraggableZone(event)) {
+ dragging = true;
+ }
+ }
+
+ private void mouseDragged(MouseEvent event) {
+ if(dragging) {
+ double newHeight = region.getHeight() - event.getY();
+ if (newHeight >= region.getMinHeight()) {
+ region.setPrefHeight(newHeight);
+ } else {
+ region.setPrefHeight(region.getMinHeight());
+ }
+ }
+ }
+
+ private void mouseMoved(MouseEvent event) {
+ if(isInDraggableZone(event) || dragging) {
+ region.setCursor(Cursor.V_RESIZE);
+ }
+ else {
+ region.setCursor(Cursor.DEFAULT);
+ }
+ }
+
+ private void mouseReleased() {
+ dragging = false;
+ region.setCursor(Cursor.DEFAULT);
+ }
+
+ private boolean isInDraggableZone(MouseEvent event) {
+ return event.getY() < (GUI.RESIZE_MARGIN);
+ }
+
+}
diff --git a/src/jcgp/gui/ChromosomePane.java b/src/jcgp/gui/population/ChromosomePane.java
index b1f4bf0..cba58d2 100644
--- a/src/jcgp/gui/ChromosomePane.java
+++ b/src/jcgp/gui/population/ChromosomePane.java
@@ -1,19 +1,15 @@
-package jcgp.gui;
+package jcgp.gui.population;
import java.util.ArrayList;
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.backend.resources.Resources;
public class ChromosomePane extends ScrollPane {
@@ -27,13 +23,13 @@ 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>();
-
+
content = new Pane();
content.setId("content pane for genes");
@@ -96,8 +92,7 @@ public class ChromosomePane extends ScrollPane {
} else {
// something bad happened!
throw new ClassCastException();
- }
-
+ }
}
public boolean isTarget() {
@@ -108,7 +103,7 @@ public class ChromosomePane extends ScrollPane {
target = newValue;
}
- public void update() {
+ public void updateGenes() {
for (int r = 0; r < guiNodes.length; r++) {
for (int c = 0; c < guiNodes[r].length; c++) {
guiNodes[r][c].updateLines();
@@ -119,7 +114,7 @@ public class ChromosomePane extends ScrollPane {
guiOutputs[i].updateLines();
}
}
-
+
public void unlockOutputs() {
relock.clear();
for (int i = 0; i < guiOutputs.length; i++) {
diff --git a/src/jcgp/gui/population/FunctionSelector.java b/src/jcgp/gui/population/FunctionSelector.java
new file mode 100644
index 0000000..0a9606f
--- /dev/null
+++ b/src/jcgp/gui/population/FunctionSelector.java
@@ -0,0 +1,73 @@
+package jcgp.gui.population;
+
+import javafx.event.EventHandler;
+import javafx.scene.control.Label;
+import javafx.scene.input.MouseEvent;
+import javafx.scene.layout.VBox;
+import jcgp.backend.function.FunctionSet;
+import jcgp.gui.GUI;
+
+public class FunctionSelector extends VBox {
+
+ private GUINode target;
+
+ public FunctionSelector(FunctionSet functionSet) {
+ setFillWidth(true);
+ setVisible(false);
+ setStyle("-fx-border-color: #A0A0A0; -fx-border-width: 1 1 0 1");
+
+ remakeFunctions(functionSet);
+
+ addEventFilter(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>() {
+ @Override
+ public void handle(MouseEvent event) {
+ dismiss();
+ }
+ });
+ }
+
+ public void remakeFunctions(final FunctionSet fs) {
+ getChildren().clear();
+
+ for (int i = 0; i < fs.getAllowedFunctionCount(); i++) {
+ final int index = i;
+ Label l = new Label(fs.getAllowedFunction(i).getName());
+ l.setMaxWidth(Double.MAX_VALUE);
+ l.setStyle("-fx-background-color: #FFFFFF; -fx-border-color: #A0A0A0; -fx-border-width: 0 0 1 0; -fx-padding: 2");
+
+ l.addEventFilter(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() {
+ @Override
+ public void handle(MouseEvent event) {
+ ((Label) event.getSource()).setStyle("-fx-background-color: " + GUI.SOFT_HIGHLIGHT_COLOUR + "; -fx-border-color: #B0B0B0; -fx-border-width: 0 0 1 0; -fx-padding: 2");
+ }
+ });
+ l.addEventFilter(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>() {
+ @Override
+ public void handle(MouseEvent event) {
+ ((Label) event.getSource()).setStyle("-fx-background-color: #FFFFFF; -fx-border-color: #A0A0A0; -fx-border-width: 0 0 1 0; -fx-padding: 2");
+ }
+ });
+ l.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
+ @Override
+ public void handle(MouseEvent event) {
+ target.getGene().setFunction(fs.getAllowedFunction(index));
+ target.updateFunction();
+ dismiss();
+ }
+ });
+
+ getChildren().add(l);
+ }
+ }
+
+ public void relocateAndShow(MouseEvent event, GUINode node) {
+ relocate(event.getSceneX() - 5, event.getSceneY() - 5);
+ target = node;
+ setVisible(true);
+ }
+
+ private void dismiss() {
+ setVisible(false);
+ }
+
+}
diff --git a/src/jcgp/gui/population/GUIGene.java b/src/jcgp/gui/population/GUIGene.java
index 26be2a5..6e9d098 100644
--- a/src/jcgp/gui/population/GUIGene.java
+++ b/src/jcgp/gui/population/GUIGene.java
@@ -1,12 +1,14 @@
package jcgp.gui.population;
-import javafx.beans.property.SimpleObjectProperty;
+import javafx.geometry.VPos;
import javafx.scene.Group;
+import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
+import javafx.scene.text.Font;
import javafx.scene.text.Text;
+import javafx.scene.text.TextAlignment;
import jcgp.backend.population.Connection;
import jcgp.backend.population.Gene;
-import jcgp.gui.ChromosomePane;
enum GUIGeneState {
NEUTRAL,
@@ -30,27 +32,34 @@ public abstract class GUIGene extends Group {
public static final double NODE_TEXT = NODE_RADIUS / 2.5;
- protected Text text;
- protected Circle mainCircle;
+ protected Text text = new Text();
+ protected Circle mainCircle = new Circle(NODE_RADIUS, Paint.valueOf("white"));
- protected SimpleObjectProperty<GUIGeneState> stateProperty = new SimpleObjectProperty<GUIGeneState>(GUIGeneState.NEUTRAL);
+ private GUIGeneState state = GUIGeneState.NEUTRAL;
protected ChromosomePane parent;
protected int locked = 0;
-
- public SimpleObjectProperty<GUIGeneState> stateProperty() {
- return stateProperty;
+
+ public GUIGene() {
+ text.setFont(Font.font("Arial", 12));
+ text.setTextOrigin(VPos.CENTER);
+ text.setTextAlignment(TextAlignment.CENTER);
+ text.setWrappingWidth(NODE_RADIUS * 2);
+ text.setX(-NODE_RADIUS);
+ text.setVisible(true);
+
+ mainCircle.setStroke(Paint.valueOf("black"));
}
public void setState(GUIGeneState newState) {
- stateProperty.set(newState);
- }
-
- public void showText(boolean value) {
- text.setVisible(value);
+ state = newState;
}
+ public GUIGeneState getState() {
+ return state;
+ }
+
public boolean isLocked() {
return locked > 0;
}
@@ -63,6 +72,11 @@ public abstract class GUIGene extends Group {
public abstract void addLocks(int value);
+ /**
+ * test
+ *
+ * @param value
+ */
public abstract void removeLocks(int value);
public abstract void updateLines();
diff --git a/src/jcgp/gui/population/GUIInput.java b/src/jcgp/gui/population/GUIInput.java
index f47186c..b4eccaa 100644
--- a/src/jcgp/gui/population/GUIInput.java
+++ b/src/jcgp/gui/population/GUIInput.java
@@ -1,20 +1,13 @@
package jcgp.gui.population;
-import javafx.beans.value.ChangeListener;
-import javafx.beans.value.ObservableValue;
import javafx.event.EventHandler;
-import javafx.geometry.VPos;
import javafx.scene.input.MouseDragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
-import javafx.scene.text.Font;
-import javafx.scene.text.Text;
-import javafx.scene.text.TextAlignment;
import jcgp.backend.population.Connection;
import jcgp.backend.population.Input;
import jcgp.backend.population.Output;
-import jcgp.gui.ChromosomePane;
import jcgp.gui.GUI;
public class GUIInput extends GUIGene {
@@ -22,23 +15,16 @@ public class GUIInput extends GUIGene {
private Input input;
public GUIInput(ChromosomePane parentRef, final Input input) {
-
+ super();
+
this.parent = parentRef;
this.input = input;
relocate(NODE_RADIUS,
(input.getIndex() * (2 * NODE_RADIUS + SPACING)) + NODE_RADIUS);
- mainCircle = new Circle(NODE_RADIUS, Paint.valueOf("white"));
- mainCircle.setStroke(Paint.valueOf("black"));
-
- text = new Text("I: " + input.getIndex());
- text.setFont(Font.font("Arial", 12));
- text.setTextOrigin(VPos.CENTER);
- text.setTextAlignment(TextAlignment.CENTER);
- text.setWrappingWidth(NODE_RADIUS * 2);
- text.setX(-NODE_RADIUS);
- text.setVisible(true);
+ text.setText("I: " + input.getIndex());
+
Circle outputSocket = new Circle(NODE_RADIUS, 0, SOCKET_RADIUS, Paint.valueOf("white"));
outputSocket.setId(String.valueOf(0));
@@ -59,7 +45,7 @@ public class GUIInput extends GUIGene {
if (event.getGestureSource() instanceof GUINode) {
Connection source = ((GUINode) event.getGestureSource()).getChangingConnection();
if (input == source) {
- stateProperty.set(GUIGeneState.NO_CHANGE_TARGET);
+ setState(GUIGeneState.NO_CHANGE_TARGET);
return;
}
} else if (event.getGestureSource() instanceof GUIOutput) {
@@ -68,7 +54,7 @@ public class GUIInput extends GUIGene {
((GUIGene) event.getSource()).setState(GUIGeneState.NO_CHANGE_TARGET);
}
}
- stateProperty.set(GUIGeneState.TARGET);
+ setState(GUIGeneState.TARGET);
}
});
@@ -79,10 +65,10 @@ public class GUIInput extends GUIGene {
// this happens even if we are the source of the drag
parent.setTarget(false);
if (event.isPrimaryButtonDown()) {
- if (stateProperty.get() == GUIGeneState.NO_CHANGE_TARGET) {
- stateProperty.set(GUIGeneState.INDIRECT_HOVER);
+ if (getState() == GUIGeneState.NO_CHANGE_TARGET) {
+ setState(GUIGeneState.INDIRECT_HOVER);
} else {
- stateProperty.set(GUIGeneState.NEUTRAL);
+ setState(GUIGeneState.NEUTRAL);
((GUIGene) event.getGestureSource()).setConnections(GUIGeneState.INDIRECT_HOVER);
}
}
@@ -115,7 +101,7 @@ public class GUIInput extends GUIGene {
}
source.updateLines();
- stateProperty.set(GUIGeneState.HOVER);
+ setState(GUIGeneState.HOVER);
}
});
@@ -123,8 +109,8 @@ public class GUIInput extends GUIGene {
@Override
public void handle(MouseEvent event) {
// cursor has entered this node without dragging, or it is dragging and this is the source
- if (stateProperty.get() == GUIGeneState.NEUTRAL) {
- stateProperty.set(GUIGeneState.HOVER);
+ if (getState() == GUIGeneState.NEUTRAL) {
+ setState(GUIGeneState.HOVER);
}
}
});
@@ -133,62 +119,61 @@ public class GUIInput extends GUIGene {
@Override
public void handle(MouseEvent event) {
// cursor has left this node without dragging, or it is dragging and this is the source
- if (stateProperty.get() == GUIGeneState.HOVER) {
- stateProperty.set(GUIGeneState.NEUTRAL);
+ if (getState() == GUIGeneState.HOVER) {
+ setState(GUIGeneState.NEUTRAL);
setConnections(GUIGeneState.NEUTRAL);
}
}
});
+ }
+
+ @Override
+ public void setState(GUIGeneState newState) {
+ super.setState(newState);
- stateProperty.addListener(new ChangeListener<GUIGeneState>() {
- @Override
- public void changed(ObservableValue<? extends GUIGeneState> observable, GUIGeneState oldValue, GUIGeneState newValue) {
-
- switch (newValue) {
- case ACTIVE_HOVER:
- if (locked > 0) {
- stateProperty().set(GUIGeneState.LOCKED_HOVER);
- } else {
- mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
- }
- break;
- case FORBIDDEN_TARGET:
- mainCircle.setFill(Paint.valueOf(GUI.BAD_SELECTION_COLOUR));
- break;
- case LOCKED_HOVER:
- mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
- break;
- case HOVER:
- mainCircle.setFill(Paint.valueOf(GUI.MEDIUM_HIGHLIGHT_COLOUR));
- break;
- case INDIRECT_HOVER:
- mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
- break;
- case NEUTRAL:
- if (locked > 0) {
- stateProperty.set(GUIGeneState.HOVER);
- } else {
- mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_COLOUR));
- }
- break;
- case NO_CHANGE_TARGET:
- parent.setTarget(true);
- mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_SELECTION_COLOUR));
- break;
- case SOURCE:
- mainCircle.setFill(Paint.valueOf(GUI.MEDIUM_HIGHLIGHT_COLOUR));
- break;
- case TARGET:
- parent.setTarget(true);
- mainCircle.setFill(Paint.valueOf(GUI.GOOD_SELECTION_COLOUR));
- break;
- default:
- break;
-
- }
+ switch (newState) {
+ case ACTIVE_HOVER:
+ if (locked > 0) {
+ setState(GUIGeneState.LOCKED_HOVER);
+ } else {
+ mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
}
- });
-
+ break;
+ case FORBIDDEN_TARGET:
+ mainCircle.setFill(Paint.valueOf(GUI.BAD_SELECTION_COLOUR));
+ break;
+ case LOCKED_HOVER:
+ mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
+ break;
+ case HOVER:
+ mainCircle.setFill(Paint.valueOf(GUI.MEDIUM_HIGHLIGHT_COLOUR));
+ break;
+ case INDIRECT_HOVER:
+ mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
+ break;
+ case NEUTRAL:
+ if (locked > 0) {
+ setState(GUIGeneState.HOVER);
+ } else {
+ mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_COLOUR));
+ }
+ break;
+ case NO_CHANGE_TARGET:
+ parent.setTarget(true);
+ mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_SELECTION_COLOUR));
+ break;
+ case SOURCE:
+ mainCircle.setFill(Paint.valueOf(GUI.MEDIUM_HIGHLIGHT_COLOUR));
+ break;
+ case TARGET:
+ parent.setTarget(true);
+ mainCircle.setFill(Paint.valueOf(GUI.GOOD_SELECTION_COLOUR));
+ break;
+ default:
+ break;
+
+ }
+
}
@Override
@@ -208,13 +193,13 @@ public class GUIInput extends GUIGene {
@Override
public void resetState() {
- stateProperty.set(GUIGeneState.NEUTRAL);
+ setState(GUIGeneState.NEUTRAL);
}
@Override
void setLocked(boolean value) {
locked += value ? 1 : -1;
- stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
+ setState(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
}
@Override
@@ -230,7 +215,7 @@ public class GUIInput extends GUIGene {
@Override
public void addLocks(int value) {
locked += value;
- stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
+ setState(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
}
@Override
@@ -241,7 +226,7 @@ public class GUIInput extends GUIGene {
@Override
public void removeLocks(int value) {
locked -= value;
- stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.NEUTRAL);
+ setState(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.NEUTRAL);
}
@Override
diff --git a/src/jcgp/gui/population/GUINode.java b/src/jcgp/gui/population/GUINode.java
index 450647f..98ba738 100644
--- a/src/jcgp/gui/population/GUINode.java
+++ b/src/jcgp/gui/population/GUINode.java
@@ -1,22 +1,15 @@
package jcgp.gui.population;
-import javafx.beans.value.ChangeListener;
-import javafx.beans.value.ObservableValue;
import javafx.event.EventHandler;
-import javafx.geometry.VPos;
import javafx.scene.control.Label;
import javafx.scene.input.MouseDragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
-import javafx.scene.text.Font;
-import javafx.scene.text.Text;
-import javafx.scene.text.TextAlignment;
import jcgp.backend.population.Connection;
import jcgp.backend.population.Input;
import jcgp.backend.population.Node;
-import jcgp.gui.ChromosomePane;
import jcgp.gui.GUI;
public class GUINode extends GUIGene {
@@ -26,7 +19,8 @@ public class GUINode extends GUIGene {
private int connectionIndex = 0;
public GUINode(ChromosomePane parentRef, final Node node, Line[] connectionLines) {
-
+ super();
+
// store references
this.parent = parentRef;
this.node = node;
@@ -46,21 +40,12 @@ public class GUINode extends GUIGene {
Circle output = new Circle(NODE_RADIUS, 0, SOCKET_RADIUS, Paint.valueOf("white"));
output.setStroke(Paint.valueOf("black"));
- mainCircle = new Circle(NODE_RADIUS, Paint.valueOf("white"));
- mainCircle.setStroke(Paint.valueOf("black"));
-
- text = new Text(node.getFunction().getName());
- text.setFont(Font.font("Arial", NODE_TEXT));
- text.setTextOrigin(VPos.CENTER);
- text.setTextAlignment(TextAlignment.CENTER);
- text.setWrappingWidth(NODE_RADIUS * 2);
- text.setX(-NODE_RADIUS);
- text.setVisible(true);
+ text.setText(node.getFunction().getName());
Circle[] sockets = new Circle[GUI.resources.getInt("arity")];
double angle, xPos, yPos;
for (int l = 0; l < sockets.length; l++) {
- angle = ((((double) (l + 1)) / ((GUI.resources.getDouble("arity") + 1))) * THETA) - (THETA / 2);
+ angle = (((l + 1) / ((GUI.resources.getDouble("arity") + 1))) * THETA) - (THETA / 2);
xPos = -Math.cos(angle) * NODE_RADIUS;
yPos = Math.sin(angle) * NODE_RADIUS;
@@ -75,7 +60,7 @@ public class GUINode extends GUIGene {
* Mouse event handlers on sockets
*
*/
- s.addEventFilter(MouseDragEvent.DRAG_DETECTED, new EventHandler<MouseEvent>() {
+ s.addEventFilter(MouseEvent.DRAG_DETECTED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
// the mouse has been dragged out of the socket, this means a full drag is in progress
@@ -101,16 +86,16 @@ public class GUINode extends GUIGene {
}
});
- s.addEventFilter(MouseDragEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
+ s.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
// mouse was pressed on the socket
- stateProperty.set(GUIGeneState.SOURCE);
+ setState(GUIGeneState.SOURCE);
connectionIndex = index;
}
});
- s.addEventFilter(MouseDragEvent.MOUSE_DRAGGED, new EventHandler<MouseEvent>() {
+ s.addEventFilter(MouseEvent.MOUSE_DRAGGED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (!parent.isTarget()) {
@@ -120,14 +105,14 @@ public class GUINode extends GUIGene {
}
});
- s.addEventFilter(MouseDragEvent.MOUSE_RELEASED, new EventHandler<MouseEvent>() {
+ s.addEventFilter(MouseEvent.MOUSE_RELEASED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (event.isStillSincePress()) {
// mouse was released before dragging out of the socket
updateLine(index);
- stateProperty.set(GUIGeneState.HOVER);
- } else if (stateProperty.get() == GUIGeneState.SOURCE) {
+ setState(GUIGeneState.HOVER);
+ } else if (getState() == GUIGeneState.SOURCE) {
// no connection has been made, fallback
resetState();
updateLines();
@@ -139,6 +124,14 @@ public class GUINode extends GUIGene {
/*
* Mouse event handlers on whole gene
*/
+
+ addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
+ @Override
+ public void handle(MouseEvent event) {
+ GUI.functionSelector.relocateAndShow(event, (GUINode) event.getSource());
+ }
+ });
+
addEventFilter(MouseDragEvent.MOUSE_DRAG_ENTERED, new EventHandler<MouseDragEvent>() {
@Override
public void handle(MouseDragEvent event) {
@@ -149,12 +142,12 @@ public class GUINode extends GUIGene {
Connection source = ((GUIGene) event.getGestureSource()).getChangingConnection();
if (node == source) {
- stateProperty.set(GUIGeneState.NO_CHANGE_TARGET);
+ setState(GUIGeneState.NO_CHANGE_TARGET);
} else {
- stateProperty.set(GUIGeneState.TARGET);
+ setState(GUIGeneState.TARGET);
}
} else {
- stateProperty.set(GUIGeneState.FORBIDDEN_TARGET);
+ setState(GUIGeneState.FORBIDDEN_TARGET);
}
}
});
@@ -167,12 +160,12 @@ public class GUINode extends GUIGene {
parent.setTarget(false);
if (event.isPrimaryButtonDown()) {
if (event.getGestureSource() == event.getSource()) {
- stateProperty.set(GUIGeneState.SOURCE);
+ setState(GUIGeneState.SOURCE);
} else {
- if (stateProperty.get() == GUIGeneState.NO_CHANGE_TARGET) {
- stateProperty.set(GUIGeneState.INDIRECT_HOVER);
+ if (getState() == GUIGeneState.NO_CHANGE_TARGET) {
+ setState(GUIGeneState.INDIRECT_HOVER);
} else {
- stateProperty.set(GUIGeneState.NEUTRAL);
+ setState(GUIGeneState.NEUTRAL);
((GUIGene) event.getGestureSource()).setConnections(GUIGeneState.INDIRECT_HOVER);
}
}
@@ -210,7 +203,7 @@ public class GUINode extends GUIGene {
}
source.updateLines();
- stateProperty.set(GUIGeneState.HOVER);
+ setState(GUIGeneState.HOVER);
}
});
@@ -219,8 +212,8 @@ public class GUINode extends GUIGene {
@Override
public void handle(MouseEvent event) {
// cursor has entered this node without dragging, or it is dragging and this is the source
- if (stateProperty.get() == GUIGeneState.NEUTRAL) {
- stateProperty.set(GUIGeneState.HOVER);
+ if (getState() == GUIGeneState.NEUTRAL) {
+ setState(GUIGeneState.HOVER);
} else if (locked > 0) {
setConnections(GUIGeneState.LOCKED_HOVER);
}
@@ -231,11 +224,11 @@ public class GUINode extends GUIGene {
@Override
public void handle(MouseEvent event) {
// cursor has left this node without dragging, or it is dragging and this is the source
- if (stateProperty.get() == GUIGeneState.HOVER && locked <= 0) {
- stateProperty.set(GUIGeneState.NEUTRAL);
+ if (getState() == GUIGeneState.HOVER && locked <= 0) {
+ setState(GUIGeneState.NEUTRAL);
setConnections(GUIGeneState.NEUTRAL);
} else if (locked > 0) {
- if (stateProperty.get() == GUIGeneState.SOURCE || stateProperty.get() == GUIGeneState.FORBIDDEN_TARGET) {
+ if (getState() == GUIGeneState.SOURCE || getState() == GUIGeneState.FORBIDDEN_TARGET) {
setConnections(GUIGeneState.INDIRECT_HOVER);
} else {
setConnections(GUIGeneState.HOVER);
@@ -249,85 +242,72 @@ public class GUINode extends GUIGene {
getChildren().addAll(sockets);
getChildren().addAll(output, connectionNumber);
- stateProperty.addListener(new ChangeListener<GUIGeneState>() {
- @Override
- public void changed(ObservableValue<? extends GUIGeneState> observable, GUIGeneState oldValue, GUIGeneState newValue) {
+ }
- switch (newValue) {
- case ACTIVE_HOVER:
- if (locked > 0) {
- stateProperty().set(GUIGeneState.LOCKED_HOVER);
- } else {
- mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
- showLines(true);
- }
- setConnections(GUIGeneState.ACTIVE_HOVER);
- break;
- case LOCKED_HOVER:
- mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
- break;
- case FORBIDDEN_TARGET:
- mainCircle.setFill(Paint.valueOf(GUI.BAD_SELECTION_COLOUR));
- break;
- case HOVER:
- mainCircle.setFill(Paint.valueOf(GUI.MEDIUM_HIGHLIGHT_COLOUR));
- showLines(true);
- if (locked <= 0) {
- setConnections(GUIGeneState.INDIRECT_HOVER);
- } else {
- setConnections(GUIGeneState.HOVER);
- }
- break;
- case INDIRECT_HOVER:
- mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
- break;
- case NEUTRAL:
- if (locked > 0) {
- stateProperty.set(GUIGeneState.HOVER);
- } else {
- mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_COLOUR));
- showLines(false);
- if (oldValue == GUIGeneState.ACTIVE_HOVER) {
- setConnections(GUIGeneState.NEUTRAL);
- }
- }
- break;
- case NO_CHANGE_TARGET:
- parent.setTarget(true);
- mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_SELECTION_COLOUR));
- break;
- case SOURCE:
- mainCircle.setFill(Paint.valueOf(GUI.HARD_HIGHLIGHT_COLOUR));
- break;
- case TARGET:
- parent.setTarget(true);
- mainCircle.setFill(Paint.valueOf(GUI.GOOD_SELECTION_COLOUR));
- break;
- default:
- break;
+ @Override
+ public void setState(GUIGeneState newState) {
+ switch (newState) {
+ case ACTIVE_HOVER:
+ if (locked > 0) {
+ setState(GUIGeneState.LOCKED_HOVER);
+ } else {
+ mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
+ showLines(true);
+ }
+ setConnections(GUIGeneState.ACTIVE_HOVER);
+ break;
+ case LOCKED_HOVER:
+ mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
+ break;
+ case FORBIDDEN_TARGET:
+ mainCircle.setFill(Paint.valueOf(GUI.BAD_SELECTION_COLOUR));
+ break;
+ case HOVER:
+ mainCircle.setFill(Paint.valueOf(GUI.MEDIUM_HIGHLIGHT_COLOUR));
+ showLines(true);
+ if (locked <= 0) {
+ setConnections(GUIGeneState.INDIRECT_HOVER);
+ } else {
+ setConnections(GUIGeneState.HOVER);
+ }
+ break;
+ case INDIRECT_HOVER:
+ mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
+ break;
+ case NEUTRAL:
+ if (locked > 0) {
+ setState(GUIGeneState.HOVER);
+ } else {
+ mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_COLOUR));
+ showLines(false);
+ if (getState() == GUIGeneState.ACTIVE_HOVER) {
+ setConnections(GUIGeneState.NEUTRAL);
}
}
- });
-
-// for (int c = 0; c < lines.length; c++) {
-// final int i = c;
-// node.connections().get(c).addListener(new ChangeListener<Connection>() {
-// @Override
-// public void changed(ObservableValue<? extends Connection> observable,
-// Connection oldValue, Connection newValue) {
-// updateLine(i);
-// }
-// });
-// }
+ break;
+ case NO_CHANGE_TARGET:
+ parent.setTarget(true);
+ mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_SELECTION_COLOUR));
+ break;
+ case SOURCE:
+ mainCircle.setFill(Paint.valueOf(GUI.HARD_HIGHLIGHT_COLOUR));
+ break;
+ case TARGET:
+ parent.setTarget(true);
+ mainCircle.setFill(Paint.valueOf(GUI.GOOD_SELECTION_COLOUR));
+ break;
+ default:
+ break;
+ }
+ super.setState(newState);
}
-
+
@Override
public Connection getChangingConnection() {
return node.getConnection(connectionIndex);
}
-
private boolean isAllowed(GUIGene source, GUIGene target) {
if (source instanceof GUINode) {
// if the source is a node, all inputs and some nodes are valid
@@ -381,6 +361,7 @@ public class GUINode extends GUIGene {
/**
* Updates the end of all lines to match the associated connections.
*/
+ @Override
public void updateLines() {
for (int c = 0; c < lines.length; c++) {
updateLine(c);
@@ -420,9 +401,9 @@ public class GUINode extends GUIGene {
@Override
public void resetState() {
if (locked > 0) {
- stateProperty.set(GUIGeneState.HOVER);
+ setState(GUIGeneState.HOVER);
} else {
- stateProperty.set(GUIGeneState.NEUTRAL);
+ setState(GUIGeneState.NEUTRAL);
setConnections(GUIGeneState.NEUTRAL);
}
@@ -431,7 +412,7 @@ public class GUINode extends GUIGene {
@Override
void setLocked(boolean value) {
locked += value ? 1 : -1;
- stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
+ setState(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
for (int i = 0; i < lines.length; i++) {
parent.getGuiGene(node.getConnection(i)).setLocked(value);
@@ -441,7 +422,7 @@ public class GUINode extends GUIGene {
@Override
public void addLocks(int value) {
locked += value;
- stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
+ setState(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.ACTIVE_HOVER);
for (int i = 0; i < lines.length; i++) {
parent.getGuiGene(node.getConnection(i)).addLocks(value);
@@ -451,7 +432,7 @@ public class GUINode extends GUIGene {
@Override
public void removeLocks(int value) {
locked -= value;
- stateProperty.set(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.NEUTRAL);
+ setState(locked > 0 ? GUIGeneState.HOVER : GUIGeneState.NEUTRAL);
for (int i = 0; i < lines.length; i++) {
parent.getGuiGene(node.getConnection(i)).removeLocks(value);
diff --git a/src/jcgp/gui/population/GUIOutput.java b/src/jcgp/gui/population/GUIOutput.java
index 9c5dfa5..4a12385 100644
--- a/src/jcgp/gui/population/GUIOutput.java
+++ b/src/jcgp/gui/population/GUIOutput.java
@@ -1,23 +1,16 @@
package jcgp.gui.population;
-import javafx.beans.value.ChangeListener;
-import javafx.beans.value.ObservableValue;
import javafx.event.EventHandler;
-import javafx.geometry.VPos;
import javafx.scene.control.Label;
import javafx.scene.input.MouseDragEvent;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
-import javafx.scene.text.Font;
-import javafx.scene.text.Text;
-import javafx.scene.text.TextAlignment;
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.gui.GUI;
public class GUIOutput extends GUIGene {
@@ -27,7 +20,8 @@ public class GUIOutput extends GUIGene {
private Output output;
public GUIOutput(ChromosomePane parentRef, final Output output, Line line) {
-
+ super();
+
this.parent = parentRef;
this.output = output;
this.sourceLine = line;
@@ -38,16 +32,7 @@ public class GUIOutput extends GUIGene {
// set the line ends correctly
updateLines();
- mainCircle = new Circle(NODE_RADIUS, Paint.valueOf("white"));
- mainCircle.setStroke(Paint.valueOf("black"));
-
- text = new Text("O: " + output.getIndex());
- text.setFont(Font.font("Arial", 12));
- text.setTextOrigin(VPos.CENTER);
- text.setTextAlignment(TextAlignment.CENTER);
- text.setWrappingWidth(NODE_RADIUS * 2);
- text.setX(-NODE_RADIUS);
- text.setVisible(true);
+ text.setText("O: " + output.getIndex());
Circle socket = new Circle(-NODE_RADIUS, 0, SOCKET_RADIUS, Paint.valueOf("white"));
socket.setId(String.valueOf(0));
@@ -62,7 +47,7 @@ public class GUIOutput extends GUIGene {
* Mouse event handlers on sockets
*
*/
- socket.addEventFilter(MouseDragEvent.DRAG_DETECTED, new EventHandler<MouseEvent>() {
+ socket.addEventFilter(MouseEvent.DRAG_DETECTED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
// the mouse has been dragged out of the socket, this means a full drag is in progress
@@ -86,15 +71,15 @@ public class GUIOutput extends GUIGene {
}
});
- socket.addEventFilter(MouseDragEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
+ socket.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
// mouse was pressed on the socket
- stateProperty.set(GUIGeneState.SOURCE);
+ setState(GUIGeneState.SOURCE);
}
});
- socket.addEventFilter(MouseDragEvent.MOUSE_DRAGGED, new EventHandler<MouseEvent>() {
+ socket.addEventFilter(MouseEvent.MOUSE_DRAGGED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (!parent.isTarget()) {
@@ -105,14 +90,14 @@ public class GUIOutput extends GUIGene {
}
});
- socket.addEventFilter(MouseDragEvent.MOUSE_RELEASED, new EventHandler<MouseEvent>() {
+ socket.addEventFilter(MouseEvent.MOUSE_RELEASED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
if (event.isStillSincePress()) {
// mouse was released before dragging out of the socket
updateLines();
- stateProperty.set(GUIGeneState.HOVER);
- } else if (stateProperty.get() == GUIGeneState.SOURCE) {
+ setState(GUIGeneState.HOVER);
+ } else if (getState() == GUIGeneState.SOURCE) {
// no connection has been made, fallback
resetState();
updateLines();
@@ -129,7 +114,7 @@ public class GUIOutput extends GUIGene {
@Override
public void handle(MouseDragEvent event) {
// the drag has entered this node, react appropriately
- stateProperty.set(GUIGeneState.FORBIDDEN_TARGET);
+ setState(GUIGeneState.FORBIDDEN_TARGET);
}
});
@@ -140,9 +125,9 @@ public class GUIOutput extends GUIGene {
// this happens even if we are the source of the drag
if (event.isPrimaryButtonDown()) {
if (event.getGestureSource() == event.getSource()) {
- stateProperty.set(GUIGeneState.SOURCE);
+ setState(GUIGeneState.SOURCE);
} else {
- stateProperty.set(isLocked() ? GUIGeneState.HOVER : GUIGeneState.NEUTRAL);
+ setState(isLocked() ? GUIGeneState.HOVER : GUIGeneState.NEUTRAL);
}
}
}
@@ -164,7 +149,7 @@ public class GUIOutput extends GUIGene {
}
source.updateLines();
- stateProperty.set(GUIGeneState.HOVER);
+ setState(GUIGeneState.HOVER);
}
});
@@ -173,8 +158,8 @@ public class GUIOutput extends GUIGene {
@Override
public void handle(MouseEvent event) {
// cursor has entered this node without dragging, or it is dragging and this is the source
- if (stateProperty.get() == GUIGeneState.NEUTRAL) {
- stateProperty.set(GUIGeneState.HOVER);
+ if (getState() == GUIGeneState.NEUTRAL) {
+ setState(GUIGeneState.HOVER);
}
}
});
@@ -190,8 +175,8 @@ public class GUIOutput extends GUIGene {
@Override
public void handle(MouseEvent event) {
// cursor has left this node without dragging, or it is dragging and this is the source
- if (stateProperty.get() == GUIGeneState.HOVER && !isLocked()) {
- stateProperty.set(GUIGeneState.NEUTRAL);
+ if (getState() == GUIGeneState.HOVER && !isLocked()) {
+ setState(GUIGeneState.NEUTRAL);
setConnections(GUIGeneState.NEUTRAL);
}
}
@@ -199,52 +184,49 @@ public class GUIOutput extends GUIGene {
getChildren().addAll(mainCircle, text, socket, connectionLabel);
+
+ }
- stateProperty.addListener(new ChangeListener<GUIGeneState>() {
- @Override
- public void changed(ObservableValue<? extends GUIGeneState> observable, GUIGeneState oldValue, GUIGeneState newValue) {
-
-
- switch (newValue) {
- case ACTIVE_HOVER:
- break;
- case FORBIDDEN_TARGET:
- mainCircle.setFill(Paint.valueOf(GUI.BAD_SELECTION_COLOUR));
- break;
- case HOVER:
- mainCircle.setFill(Paint.valueOf(GUI.MEDIUM_HIGHLIGHT_COLOUR));
- sourceLine.setVisible(true);
- if (!isLocked()) {
- setConnections(GUIGeneState.ACTIVE_HOVER);
- }
- break;
- case INDIRECT_HOVER:
- mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
- break;
- case NEUTRAL:
- mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_COLOUR));
- sourceLine.setVisible(false);
- break;
- case NO_CHANGE_TARGET:
- mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_SELECTION_COLOUR));
- break;
- case SOURCE:
- mainCircle.setFill(Paint.valueOf(GUI.HARD_HIGHLIGHT_COLOUR));
- setConnections(GUIGeneState.NEUTRAL);
- setConnections(GUIGeneState.INDIRECT_HOVER);
- break;
- case TARGET:
- mainCircle.setFill(Paint.valueOf(GUI.GOOD_SELECTION_COLOUR));
- break;
- default:
- break;
-
- }
+ @Override
+ public void setState(GUIGeneState newState) {
+ super.setState(newState);
+
+ switch (newState) {
+ case ACTIVE_HOVER:
+ break;
+ case FORBIDDEN_TARGET:
+ mainCircle.setFill(Paint.valueOf(GUI.BAD_SELECTION_COLOUR));
+ break;
+ case HOVER:
+ mainCircle.setFill(Paint.valueOf(GUI.MEDIUM_HIGHLIGHT_COLOUR));
+ sourceLine.setVisible(true);
+ if (!isLocked()) {
+ setConnections(GUIGeneState.ACTIVE_HOVER);
}
- });
-
+ break;
+ case INDIRECT_HOVER:
+ mainCircle.setFill(Paint.valueOf(GUI.SOFT_HIGHLIGHT_COLOUR));
+ break;
+ case NEUTRAL:
+ mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_COLOUR));
+ sourceLine.setVisible(false);
+ break;
+ case NO_CHANGE_TARGET:
+ mainCircle.setFill(Paint.valueOf(GUI.NEUTRAL_SELECTION_COLOUR));
+ break;
+ case SOURCE:
+ mainCircle.setFill(Paint.valueOf(GUI.HARD_HIGHLIGHT_COLOUR));
+ setConnections(GUIGeneState.NEUTRAL);
+ setConnections(GUIGeneState.INDIRECT_HOVER);
+ break;
+ case TARGET:
+ mainCircle.setFill(Paint.valueOf(GUI.GOOD_SELECTION_COLOUR));
+ break;
+ default:
+ break;
+ }
}
-
+
@Override
public void updateLines() {
if (output.getSource() instanceof Node) {
@@ -272,10 +254,10 @@ public class GUIOutput extends GUIGene {
@Override
public void resetState() {
if (locked > 0) {
- stateProperty.set(GUIGeneState.HOVER);
+ setState(GUIGeneState.HOVER);
setConnections(GUIGeneState.HOVER);
} else {
- stateProperty.set(GUIGeneState.NEUTRAL);
+ setState(GUIGeneState.NEUTRAL);
setConnections(GUIGeneState.NEUTRAL);
}
}
@@ -318,14 +300,14 @@ public class GUIOutput extends GUIGene {
public void unlock() {
if (isLocked()) {
setLocked(false);
- stateProperty.set(GUIGeneState.NEUTRAL);
+ setState(GUIGeneState.NEUTRAL);
setConnections(GUIGeneState.NEUTRAL);
}
}
public void lock() {
if (!isLocked()) {
- stateProperty.set(GUIGeneState.HOVER);
+ setState(GUIGeneState.HOVER);
setLocked(true);
}
}
diff --git a/src/jcgp/gui/population/PopulationPane.java b/src/jcgp/gui/population/PopulationPane.java
new file mode 100644
index 0000000..3a83a86
--- /dev/null
+++ b/src/jcgp/gui/population/PopulationPane.java
@@ -0,0 +1,49 @@
+package jcgp.gui.population;
+
+import javafx.scene.control.Tab;
+import javafx.scene.control.TabPane;
+import jcgp.JCGP;
+import jcgp.backend.population.Population;
+import jcgp.backend.resources.Resources;
+
+public class PopulationPane extends TabPane {
+
+ public PopulationPane(JCGP jcgp) {
+ super();
+
+ setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE);
+
+ remakeTabs(jcgp.getPopulation(), jcgp.getResources());
+ }
+
+ public void remakeTabs(Population population, Resources resources) {
+ getTabs().clear();
+
+ Tab tab;
+ ChromosomePane cp;
+ for (int i = 0; i < resources.getInt("popSize"); i++) {
+ cp = new ChromosomePane(population.getChromosome(i), resources);
+ tab = new Tab("Chr " + i);
+ tab.setContent(cp);
+ getTabs().add(tab);
+ }
+ }
+
+ public void updateGenes() {
+ for (int i = 0; i < getChildrenUnmodifiable().size(); i++) {
+ ((ChromosomePane) getTabs().get(i).getContent()).updateGenes();
+ }
+ }
+
+ public void unlockOutputs() {
+ for (int i = 0; i < getChildrenUnmodifiable().size(); i++) {
+ ((ChromosomePane) getTabs().get(i).getContent()).unlockOutputs();
+ }
+ }
+
+ public void relockOutputs() {
+ for (int i = 0; i < getChildrenUnmodifiable().size(); i++) {
+ ((ChromosomePane) getTabs().get(i).getContent()).relockOutputs();
+ }
+ }
+}
diff --git a/src/jcgp/gui/settings/SettingsPane.java b/src/jcgp/gui/settings/SettingsPane.java
index cb066b7..8c707d3 100644
--- a/src/jcgp/gui/settings/SettingsPane.java
+++ b/src/jcgp/gui/settings/SettingsPane.java
@@ -5,12 +5,10 @@ import java.util.ArrayList;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
-import javafx.scene.Cursor;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ScrollPane;
-import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
@@ -23,26 +21,21 @@ 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.backend.resources.parameters.Parameter;
import jcgp.gui.GUI;
-import jcgp.gui.settings.parameters.*;
+import jcgp.gui.settings.parameters.GUIParameter;
public class SettingsPane extends AnchorPane {
private VBox mainContainer;
- private VBox bpPane, eaPane, mutatorPane, ffPane, nfPane;
+ private VBox baseParameterPane, eaPane, mutatorPane, ffPane, nfPane;
- private Button runPause;
+ private Button runPause = new Button("Run"), step = new Button("Step"), reset = new Button("Reset");
private ArrayList<GUIParameter> parameters = new ArrayList<GUIParameter>();
- private boolean dragging = false;
-
public SettingsPane(JCGP cgp, GUI gui) {
super();
-
- setResizeListeners();
mainContainer = new VBox(8);
mainContainer.setPadding(new Insets(5, GUI.RESIZE_MARGIN, 0, 2));
@@ -50,15 +43,13 @@ public class SettingsPane extends AnchorPane {
setMinWidth(GUI.SETTINGS_WIDTH);
setPrefWidth(GUI.SETTINGS_WIDTH);
- initialiseBaseParameters(cgp, gui);
+ initialiseBaseParameters(cgp);
initialiseEAParameters(cgp);
initialiseMutatorParameters(cgp);
- initialiseFitnessFunctionParameters(cgp);
-
- initialiseNodeFunctionParameters(cgp);
+ initialiseProblemTypeParameters(cgp, gui);
createControls(cgp, gui);
@@ -75,35 +66,39 @@ public class SettingsPane extends AnchorPane {
getChildren().add(scroll);
}
- private void initialiseBaseParameters(JCGP cgp, GUI gui) {
- bpPane = new VBox(2);
+ private void initialiseBaseParameters(JCGP cgp) {
+ baseParameterPane = new VBox(2);
Text header = new Text("Base Parameters");
header.setFont(Font.font("Arial", 14));
header.setUnderline(true);
- bpPane.getChildren().add(header);
-
- parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("rows"), this));
- parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("columns"), this));
- parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("inputs"), this));
- parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("outputs"), this));
- parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("levelsBack"), this));
-
- parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("popSize"), this));
- parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("generations"), this));
- parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("runs"), this));
-
- parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("currentGen"), this));
- parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("currentRun"), this));
-
- parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("maxFitness"), this));
- parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("seed"), this));
- parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("report"), this));
-
- bpPane.getChildren().addAll(parameters);
-
- mainContainer.getChildren().add(bpPane);
+ baseParameterPane.getChildren().add(header);
+
+ parameters.add(GUIParameter.create(cgp.getResources().getParameter("rows"), this));
+ parameters.add(GUIParameter.create(cgp.getResources().getParameter("columns"), this));
+ parameters.add(GUIParameter.create(cgp.getResources().getParameter("inputs"), this));
+ parameters.add(GUIParameter.create(cgp.getResources().getParameter("outputs"), this));
+ parameters.add(GUIParameter.create(cgp.getResources().getParameter("levelsBack"), this));
+
+ GUIParameter gp = GUIParameter.create(cgp.getResources().getParameter("popSize"), this);
+ gp.setPadding(new Insets(0, 0, 10, 0));
+ parameters.add(gp);
+
+ parameters.add(GUIParameter.create(cgp.getResources().getParameter("currentGen"), this));
+ parameters.add(GUIParameter.create(cgp.getResources().getParameter("generations"), this));
+ parameters.add(GUIParameter.create(cgp.getResources().getParameter("currentRun"), this));
+
+ gp = GUIParameter.create(cgp.getResources().getParameter("runs"), this);
+ gp.setPadding(new Insets(0, 0, 10, 0));
+ parameters.add(gp);
+
+ parameters.add(GUIParameter.create(cgp.getResources().getParameter("seed"), this));
+ parameters.add(GUIParameter.create(cgp.getResources().getParameter("report"), this));
+ parameters.add(GUIParameter.create(cgp.getResources().getParameter("maxFitness"), this));
+
+ baseParameterPane.getChildren().addAll(parameters);
+ mainContainer.getChildren().add(baseParameterPane);
}
private void initialiseEAParameters(final JCGP cgp) {
@@ -172,10 +167,10 @@ public class SettingsPane extends AnchorPane {
mainContainer.getChildren().add(mutatorPane);
}
- private void initialiseFitnessFunctionParameters(final JCGP cgp) {
+ private void initialiseProblemTypeParameters(final JCGP cgp, final GUI gui) {
ffPane= new VBox(2);
- Text header = new Text("Fitness Function");
+ Text header = new Text("Problem type");
header.setFont(Font.font("Arial", 14));
header.setUnderline(true);
@@ -200,36 +195,13 @@ public class SettingsPane extends AnchorPane {
}
});
- ffPane.getChildren().addAll(header, ffCBox, ffParameters);
- mainContainer.getChildren().add(ffPane);
-
- }
-
- private void initialiseNodeFunctionParameters(JCGP cgp) {
- nfPane = new VBox(2);
-
- Text header = new Text("Node Functions");
- header.setFont(Font.font("Arial", 14));
- header.setUnderline(true);
-
- final ComboBox<FunctionSet> nfCBox = new ComboBox<FunctionSet>();
- nfCBox.getItems().addAll(cgp.getResources().getFunctionSets());
- nfCBox.getSelectionModel().select(cgp.getResources().getFunctionSet());
- nfCBox.prefWidthProperty().bind(mainContainer.widthProperty());
-
final VBox nfParameters = new VBox();
nfParameters.setSpacing(2);
- refreshFunctions(cgp.getResources().getFunctionSet(), nfParameters);
+ refreshFunctions(cgp.getResources().getFunctionSet(), nfParameters, gui);
- nfCBox.setOnAction(new EventHandler<ActionEvent>() {
- @Override
- public void handle(ActionEvent event) {
- refreshFunctions(nfCBox.getSelectionModel().getSelectedItem(), nfParameters);
- }
- });
+ ffPane.getChildren().addAll(header, ffCBox, ffParameters, nfParameters);
+ mainContainer.getChildren().add(ffPane);
- nfPane.getChildren().addAll(header, nfCBox, nfParameters);
- mainContainer.getChildren().add(nfPane);
}
private void createControls(final JCGP cgp, final GUI gui) {
@@ -237,7 +209,6 @@ public class SettingsPane extends AnchorPane {
controls.setFillWidth(true);
final HBox flowButtons = new HBox(2);
- runPause = new Button("Run");
runPause.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
@@ -245,7 +216,7 @@ public class SettingsPane extends AnchorPane {
}
});
- Button step = new Button("Step");
+ step = new Button("Step");
step.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
@@ -253,7 +224,7 @@ public class SettingsPane extends AnchorPane {
}
});
- Button reset = new Button("Reset");
+ reset = new Button("Reset");
reset.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
@@ -265,10 +236,8 @@ public class SettingsPane extends AnchorPane {
HBox.setHgrow(runPause, Priority.ALWAYS);
runPause.setMaxWidth(Double.MAX_VALUE);
-
HBox.setHgrow(step, Priority.ALWAYS);
step.setMaxWidth(Double.MAX_VALUE);
-
HBox.setHgrow(reset, Priority.ALWAYS);
reset.setMaxWidth(Double.MAX_VALUE);
@@ -293,7 +262,7 @@ public class SettingsPane extends AnchorPane {
revalidateParameters();
}
- private void refreshFunctions(final FunctionSet fs, VBox vb) {
+ private void refreshFunctions(final FunctionSet fs, VBox vb, final GUI gui) {
vb.getChildren().clear();
CheckBox cb;
for (int i = 0; i < fs.getTotalFunctionCount(); i++) {
@@ -309,69 +278,30 @@ public class SettingsPane extends AnchorPane {
} else {
fs.disableFunction(index);
}
+ GUI.updateFunctionSelector();
}
});
vb.getChildren().add(cb);
+
+ GUI.updateFunctionSelector();
}
}
- private void setResizeListeners() {
- setOnMousePressed(new EventHandler<MouseEvent>() {
- @Override
- public void handle(MouseEvent event) {
- if(isInDraggableZone(event)) {
- dragging = true;
- }
- }
- });
- setOnMouseDragged(new EventHandler<MouseEvent>() {
- @Override
- public void handle(MouseEvent event) {
- if(dragging) {
- double newWidth = getWidth() - event.getX();
- if (newWidth >= getMinWidth()) {
- setPrefWidth(newWidth);
- } else {
- setPrefWidth(getMinWidth());
- }
- }
- }
- });
- setOnMouseMoved(new EventHandler<MouseEvent>() {
- @Override
- public void handle(MouseEvent event) {
- if(isInDraggableZone(event) || dragging) {
- setCursor(Cursor.H_RESIZE);
- }
- else {
- setCursor(Cursor.DEFAULT);
- }
- }
- });
- setOnMouseReleased(new EventHandler<MouseEvent>() {
- @Override
- public void handle(MouseEvent event) {
- dragging = false;
- setCursor(Cursor.DEFAULT);
- }
- });
- }
-
- private boolean isInDraggableZone(MouseEvent event) {
- return event.getX() < (GUI.RESIZE_MARGIN);
- }
+
- public void disableSettings(boolean value) {
- bpPane.setDisable(value);
+ public void runningMode(boolean value) {
+ baseParameterPane.setDisable(value);
eaPane.setDisable(value);
mutatorPane.setDisable(value);
ffPane.setDisable(value);
nfPane.setDisable(value);
+ step.setDisable(value);
+ reset.setDisable(value);
+
+ runPause.setText(value ? "Pause" : "Run");
}
/**
- * 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.
*/
@@ -394,8 +324,12 @@ public class SettingsPane extends AnchorPane {
}
public void revalidateParameters() {
+ runPause.setDisable(false);
for (GUIParameter parameter : parameters) {
parameter.validate();
+ if (parameter.requiresReset()) {
+ runPause.setDisable(true);
+ }
}
}
@@ -404,10 +338,4 @@ public class SettingsPane extends AnchorPane {
parameter.applyValue();
}
}
-
- public Button getRunButton() {
- return runPause;
- }
-
-
}
diff --git a/src/jcgp/gui/settings/parameters/GUIBooleanParameter.java b/src/jcgp/gui/settings/parameters/GUIBooleanParameter.java
index fc66e7d..4339562 100644
--- a/src/jcgp/gui/settings/parameters/GUIBooleanParameter.java
+++ b/src/jcgp/gui/settings/parameters/GUIBooleanParameter.java
@@ -3,9 +3,8 @@ package jcgp.gui.settings.parameters;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.control.CheckBox;
-import jcgp.backend.parameters.BooleanParameter;
-import jcgp.backend.parameters.ParameterStatus;
-import jcgp.gui.GUI;
+import jcgp.backend.resources.parameters.BooleanParameter;
+import jcgp.backend.resources.parameters.ParameterStatus;
import jcgp.gui.settings.SettingsPane;
public class GUIBooleanParameter extends GUIParameter {
@@ -65,15 +64,15 @@ public class GUIBooleanParameter extends GUIParameter {
*/
private void setValidityStyle() {
if (parameter.getStatus() == ParameterStatus.INVALID) {
- valueControl.setStyle(GUI.INVALID_PARAMETER_STYLE);
+ valueControl.setStyle(BASE_CHECKBOX_STYLE + INVALID_PARAMETER_STYLE);
valueControl.setTooltip(tooltip);
tooltip.setText(parameter.getStatus().getDetails());
} else if (parameter.getStatus() == ParameterStatus.WARNING || parameter.getStatus() == ParameterStatus.WARNING_RESET) {
- valueControl.setStyle(GUI.WARNING_PARAMETER_STYLE);
+ valueControl.setStyle(BASE_CHECKBOX_STYLE + WARNING_PARAMETER_STYLE);
valueControl.setTooltip(tooltip);
tooltip.setText(parameter.getStatus().getDetails());
} else {
- valueControl.setStyle(GUI.VALID_PARAMETER_STYLE);
+ valueControl.setStyle(BASE_CHECKBOX_STYLE + VALID_PARAMETER_STYLE);
valueControl.setTooltip(null);
}
}
diff --git a/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java b/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java
index 190f4b7..eecff2d 100644
--- a/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java
+++ b/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java
@@ -8,9 +8,8 @@ import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Priority;
import javafx.scene.text.Text;
-import jcgp.backend.parameters.DoubleParameter;
-import jcgp.backend.parameters.ParameterStatus;
-import jcgp.gui.GUI;
+import jcgp.backend.resources.parameters.DoubleParameter;
+import jcgp.backend.resources.parameters.ParameterStatus;
import jcgp.gui.settings.SettingsPane;
public class GUIDoubleParameter extends GUIParameter {
@@ -26,13 +25,14 @@ public class GUIDoubleParameter extends GUIParameter {
name = new Text(parameter.getName());
valueControl = new TextField(String.valueOf(parameter.get()));
- valueControl.setStyle(GUI.VALID_PARAMETER_STYLE);
+ valueControl.setStyle(VALID_PARAMETER_STYLE);
((TextField) valueControl).setAlignment(Pos.CENTER_RIGHT);
setHgrow(valueControl, Priority.ALWAYS);
+ setHgrow(name, Priority.ALWAYS);
- name.setWrappingWidth(GUI.WRAP_WIDTH);
+ name.wrappingWidthProperty().bind(widthProperty().divide(2));
((TextField) valueControl).setEditable(!parameter.isMonitor());
@@ -41,6 +41,7 @@ public class GUIDoubleParameter extends GUIParameter {
makeLightBinding();
} else {
valueControl.addEventFilter(KeyEvent.KEY_TYPED, new EventHandler<KeyEvent>() {
+ @Override
public void handle( KeyEvent t ) {
char ch = t.getCharacter().toCharArray()[t.getCharacter().toCharArray().length - 1];
if (!((ch >= '0' && ch <= '9') || (ch == '.' && !((TextField) valueControl).getText().contains(".")))) {
@@ -101,15 +102,15 @@ public class GUIDoubleParameter extends GUIParameter {
private void setValidityStyle() {
if (parameter.getStatus() == ParameterStatus.INVALID) {
- valueControl.setStyle(GUI.INVALID_PARAMETER_STYLE);
+ valueControl.setStyle(BASE_TEXT_STYLE + INVALID_PARAMETER_STYLE);
valueControl.setTooltip(tooltip);
tooltip.setText(parameter.getStatus().getDetails());
} else if (parameter.getStatus() == ParameterStatus.WARNING || parameter.getStatus() == ParameterStatus.WARNING_RESET) {
- valueControl.setStyle(GUI.WARNING_PARAMETER_STYLE);
+ valueControl.setStyle(BASE_TEXT_STYLE + WARNING_PARAMETER_STYLE);
valueControl.setTooltip(tooltip);
tooltip.setText(parameter.getStatus().getDetails());
} else {
- valueControl.setStyle(GUI.VALID_PARAMETER_STYLE);
+ valueControl.setStyle(BASE_TEXT_STYLE + VALID_PARAMETER_STYLE);
valueControl.setTooltip(null);
}
}
diff --git a/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java b/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java
index a2040d7..9c84c6a 100644
--- a/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java
+++ b/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java
@@ -8,9 +8,8 @@ import javafx.scene.control.TextField;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Priority;
import javafx.scene.text.Text;
-import jcgp.backend.parameters.IntegerParameter;
-import jcgp.backend.parameters.ParameterStatus;
-import jcgp.gui.GUI;
+import jcgp.backend.resources.parameters.IntegerParameter;
+import jcgp.backend.resources.parameters.ParameterStatus;
import jcgp.gui.settings.SettingsPane;
public class GUIIntegerParameter extends GUIParameter {
@@ -26,13 +25,14 @@ public class GUIIntegerParameter extends GUIParameter {
name = new Text(parameter.getName());
valueControl = new TextField(String.valueOf(parameter.get()));
- valueControl.setStyle(GUI.VALID_PARAMETER_STYLE);
+ valueControl.setStyle(VALID_PARAMETER_STYLE);
((TextField) valueControl).setAlignment(Pos.CENTER_RIGHT);
setHgrow(valueControl, Priority.ALWAYS);
+ setHgrow(name, Priority.ALWAYS);
- name.setWrappingWidth(GUI.WRAP_WIDTH);
+ name.wrappingWidthProperty().bind(widthProperty().divide(2));
((TextField) valueControl).setEditable(!parameter.isMonitor());
@@ -41,6 +41,7 @@ public class GUIIntegerParameter extends GUIParameter {
makeLightBinding();
} else {
valueControl.addEventFilter(KeyEvent.KEY_TYPED, new EventHandler<KeyEvent>() {
+ @Override
public void handle( KeyEvent t ) {
char ch = t.getCharacter().toCharArray()[t.getCharacter().toCharArray().length - 1];
if (!(ch >= '0' && ch <= '9')) {
@@ -101,15 +102,15 @@ public class GUIIntegerParameter extends GUIParameter {
private void setValidityStyle() {
if (parameter.getStatus() == ParameterStatus.INVALID) {
- valueControl.setStyle(GUI.INVALID_PARAMETER_STYLE);
+ valueControl.setStyle(BASE_TEXT_STYLE + INVALID_PARAMETER_STYLE);
valueControl.setTooltip(tooltip);
tooltip.setText(parameter.getStatus().getDetails());
} else if (parameter.getStatus() == ParameterStatus.WARNING || parameter.getStatus() == ParameterStatus.WARNING_RESET) {
- valueControl.setStyle(GUI.WARNING_PARAMETER_STYLE);
+ valueControl.setStyle(BASE_TEXT_STYLE + WARNING_PARAMETER_STYLE);
valueControl.setTooltip(tooltip);
tooltip.setText(parameter.getStatus().getDetails());
} else {
- valueControl.setStyle(GUI.VALID_PARAMETER_STYLE);
+ valueControl.setStyle(BASE_TEXT_STYLE + VALID_PARAMETER_STYLE);
valueControl.setTooltip(null);
}
}
diff --git a/src/jcgp/gui/settings/parameters/GUIParameter.java b/src/jcgp/gui/settings/parameters/GUIParameter.java
index da2fe86..6bfdf30 100644
--- a/src/jcgp/gui/settings/parameters/GUIParameter.java
+++ b/src/jcgp/gui/settings/parameters/GUIParameter.java
@@ -10,14 +10,22 @@ import javafx.scene.control.Control;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.HBox;
import javafx.scene.text.Text;
-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.resources.parameters.BooleanParameter;
+import jcgp.backend.resources.parameters.DoubleParameter;
+import jcgp.backend.resources.parameters.IntegerParameter;
+import jcgp.backend.resources.parameters.Parameter;
+import jcgp.backend.resources.parameters.ParameterStatus;
+import jcgp.gui.GUI;
import jcgp.gui.settings.SettingsPane;
public abstract class GUIParameter extends HBox {
+
+ public static final String BASE_TEXT_STYLE = "-fx-border-color: #C9C9C9; -fx-border-radius: 2; -fx-padding: 0; ";
+ public static final String BASE_CHECKBOX_STYLE = "-fx-padding: 0; ";
+
+ public static final String INVALID_PARAMETER_STYLE = "-fx-background-color: " + GUI.BAD_SELECTION_COLOUR;
+ public static final String WARNING_PARAMETER_STYLE = "-fx-background-color: " + GUI.NEUTRAL_SELECTION_COLOUR;
+ public static final String VALID_PARAMETER_STYLE = "-fx-background-color: " + GUI.NEUTRAL_COLOUR;
protected Parameter parameter;
protected Text name;