diff options
Diffstat (limited to 'src/jcgp/backend/resources')
8 files changed, 535 insertions, 0 deletions
diff --git a/src/jcgp/backend/resources/Console.java b/src/jcgp/backend/resources/Console.java new file mode 100644 index 0000000..6bbd5ba --- /dev/null +++ b/src/jcgp/backend/resources/Console.java @@ -0,0 +1,11 @@ +package jcgp.backend.resources; + +public interface Console { + + public void println(String s); + + public void print(String s); + + public void flush(); + +} 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/resources/parameters/BooleanParameter.java b/src/jcgp/backend/resources/parameters/BooleanParameter.java new file mode 100644 index 0000000..cd17649 --- /dev/null +++ b/src/jcgp/backend/resources/parameters/BooleanParameter.java @@ -0,0 +1,42 @@ +package jcgp.backend.resources.parameters; + +import javafx.beans.property.SimpleBooleanProperty; + +public abstract class BooleanParameter extends Parameter { + + private SimpleBooleanProperty value; + + public BooleanParameter(boolean value, String name, boolean monitor, boolean critical) { + super(name, monitor, critical); + this.value = new SimpleBooleanProperty(value); + } + + /** + * Simple BooleanParameter constructor, + * + * + * @param value + * @param name + */ + public BooleanParameter(boolean value, String name) { + super(name, false, false); + this.value = new SimpleBooleanProperty(value); + } + + public boolean get() { + return value.get(); + } + + public void set(boolean newValue) { + if (!value.isBound()) { + value.set(newValue); + } + } + + public abstract void validate(boolean newValue); + + @Override + public SimpleBooleanProperty valueProperty() { + return value; + } +} diff --git a/src/jcgp/backend/resources/parameters/DoubleParameter.java b/src/jcgp/backend/resources/parameters/DoubleParameter.java new file mode 100644 index 0000000..8464c83 --- /dev/null +++ b/src/jcgp/backend/resources/parameters/DoubleParameter.java @@ -0,0 +1,36 @@ +package jcgp.backend.resources.parameters; + +import javafx.beans.property.SimpleDoubleProperty; + +public abstract class DoubleParameter extends Parameter { + + protected SimpleDoubleProperty value; + + public DoubleParameter(double value, String name, boolean monitor, boolean critical) { + super(name, monitor, critical); + this.value = new SimpleDoubleProperty(value); + } + + public DoubleParameter(double value, String name) { + super(name, false, false); + this.value = new SimpleDoubleProperty(value); + } + + public double get() { + return value.get(); + } + + public void set(double newValue) { + if (!value.isBound()) { + value.set(newValue); + } + } + + @Override + public SimpleDoubleProperty valueProperty() { + return value; + } + + public abstract void validate(double newValue); + +} diff --git a/src/jcgp/backend/resources/parameters/IntegerParameter.java b/src/jcgp/backend/resources/parameters/IntegerParameter.java new file mode 100644 index 0000000..2a7b2a7 --- /dev/null +++ b/src/jcgp/backend/resources/parameters/IntegerParameter.java @@ -0,0 +1,37 @@ +package jcgp.backend.resources.parameters; + +import javafx.beans.property.SimpleIntegerProperty; + +public abstract class IntegerParameter extends Parameter { + + private SimpleIntegerProperty value; + + public IntegerParameter(int value, String name, boolean monitor, boolean critical) { + super(name, monitor, critical); + this.value = new SimpleIntegerProperty(value); + } + + public IntegerParameter(int value, String name) { + super(name, false, false); + this.value = new SimpleIntegerProperty(value); + } + + public int get() { + return value.get(); + } + + public void set(int newValue) { + if (!value.isBound()) { + validate(newValue); + value.set(newValue); + } + } + + @Override + public SimpleIntegerProperty valueProperty() { + return value; + } + + public abstract void validate(int newValue); + +} diff --git a/src/jcgp/backend/resources/parameters/Parameter.java b/src/jcgp/backend/resources/parameters/Parameter.java new file mode 100644 index 0000000..7e12ff8 --- /dev/null +++ b/src/jcgp/backend/resources/parameters/Parameter.java @@ -0,0 +1,41 @@ +package jcgp.backend.resources.parameters; + +import javafx.beans.property.Property; + +public abstract class Parameter { + + protected boolean monitor, critical, reset = false; + + protected ParameterStatus status = ParameterStatus.VALID; + + protected String name; + + public Parameter(String name, boolean monitor, boolean critical) { + this.name = name; + this.monitor = monitor; + this.critical = critical; + } + + public boolean isMonitor() { + return monitor; + } + + public boolean isCritical() { + return critical; + } + + public boolean requiresReset() { + return critical || reset; + } + + public String getName() { + return name; + } + + public ParameterStatus getStatus() { + return status; + } + + public abstract Property<?> valueProperty(); + +} diff --git a/src/jcgp/backend/resources/parameters/ParameterStatus.java b/src/jcgp/backend/resources/parameters/ParameterStatus.java new file mode 100644 index 0000000..11da4c2 --- /dev/null +++ b/src/jcgp/backend/resources/parameters/ParameterStatus.java @@ -0,0 +1,16 @@ +package jcgp.backend.resources.parameters; + +public enum ParameterStatus { + INVALID, WARNING, WARNING_RESET, VALID; + + private String details; + + public void setDetails(String details) { + this.details = details; + } + + public String getDetails() { + return details; + } + +} |