diff options
Diffstat (limited to 'src')
32 files changed, 399 insertions, 857 deletions
diff --git a/src/jcgp/GUI.java b/src/jcgp/GUI.java index a893494..98545db 100644 --- a/src/jcgp/GUI.java +++ b/src/jcgp/GUI.java @@ -1,10 +1,8 @@ package jcgp; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintStream; - import javafx.application.Application; +import javafx.concurrent.Service; +import javafx.concurrent.Task; import javafx.scene.Scene; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; @@ -12,9 +10,9 @@ import javafx.scene.control.TabPane.TabClosingPolicy; import javafx.scene.layout.BorderPane; import javafx.stage.Stage; import jcgp.JCGP.Resources; +import jcgp.gui.ChromosomePane; import jcgp.gui.GUIConsole; -import jcgp.gui.SettingsPane; -import jcgp.gui.population.ChromosomePane; +import jcgp.gui.settings.SettingsPane; public class GUI extends Application { @@ -35,10 +33,9 @@ public class GUI extends Application { /* Sizes and distances */ - public static final double RESIZE_MARGIN = 5.0; - public static final double SETTINGS_WIDTH = 190; + public static final double SETTINGS_WIDTH = 200; public static final double CONSOLE_HEIGHT = 100; public static final double WRAP_WIDTH = 90; @@ -52,18 +49,14 @@ public class GUI extends Application { private ChromosomePane[] chromosomes; private TabPane mainPane; - private static GUIConsole console = new GUIConsole(); + private GUIConsole console = new GUIConsole(); private SettingsPane settings; - public static final PrintStream out = new PrintStream(new OutputStream() { - @Override - public void write(int b) throws IOException { - console.getTextArea().appendText(String.valueOf((char) b)); - } - }); - + private Service<Object> cgpService; + + private static boolean evolving = false; + public static void main(String[] args) { - cgp = new JCGP(); resources = cgp.getResources(); @@ -73,6 +66,28 @@ public class GUI extends Application { @Override public void start(Stage primaryStage) throws Exception { + + cgpService = new Service<Object> () { + + @Override + protected Task<Object> createTask() { + Task<Object> t = new Task<Object>() { + @Override + protected Object call() throws Exception { + while (true) { + if (isCancelled()) { + return null; + } else { + cgp.nextGeneration(); + } + } + } + }; + + return t; + } + }; + /* * Instantiate the various GUI elements here. * @@ -81,16 +96,16 @@ public class GUI extends Application { mainPane = new TabPane(); mainPane.setTabClosingPolicy(TabClosingPolicy.UNAVAILABLE); - chromosomes = new ChromosomePane[(int) cgp.getResources().get("popSize")]; + 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)); + chromosomes[i] = new ChromosomePane(cgp.getPopulation().getChromosome(i), resources); tab = new Tab("Chr " + i); tab.setContent(chromosomes[i]); mainPane.getTabs().add(tab); } - settings = new SettingsPane(cgp); + settings = new SettingsPane(cgp, this); //mainPane.setPrefHeight(500); @@ -102,7 +117,7 @@ public class GUI extends Application { window.setCenter(leftPane); window.setRight(settings); - + //primaryStage.setMinHeight(600); //primaryStage.setMinWidth(800); @@ -111,5 +126,51 @@ public class GUI extends Application { primaryStage.setScene(new Scene(window)); primaryStage.show(); } + + public void updateNodeGrids() { + for (int i = 0; i < chromosomes.length; i++) { + chromosomes[i].update(); + } + } + + public void playPause() { + if (!evolving) { + setEvolving(true); + cgpService.restart(); + } else { + cgpService.cancel(); + setEvolving(false); + } + } + + public void step() { + if (!evolving) { + Thread t = new Thread(new Task<Object>() { + @Override + protected Object call() throws Exception { + cgp.nextGeneration(); + setEvolving(false); + return null; + } + }); + setEvolving(true); + t.start(); + } + } + + private void setEvolving(boolean value) { + evolving = value; + settings.toggleSettings(value); + if (value) { + settings.bindParameters(); + } else { + updateNodeGrids(); + settings.unbindParameters(); + } + } + + public boolean isEvolving() { + return evolving; + } } diff --git a/src/jcgp/JCGP.java b/src/jcgp/JCGP.java index dc121c9..1742b6a 100644 --- a/src/jcgp/JCGP.java +++ b/src/jcgp/JCGP.java @@ -2,28 +2,33 @@ package jcgp; import java.util.HashMap; import java.util.Iterator; -import java.util.Map; import java.util.Map.Entry; import java.util.Random; -import javafx.beans.property.Property; +import javafx.beans.property.SimpleIntegerProperty; import jcgp.function.Arithmetic; import jcgp.function.BitwiseLogic; import jcgp.function.BooleanLogic; import jcgp.function.Function; import jcgp.function.FunctionSet; import jcgp.modules.ea.EvolutionaryAlgorithm; -import jcgp.modules.ea.StandardEA; +import jcgp.modules.ea.MuPlusLambda; +import jcgp.modules.ea.TournamentSelection; import jcgp.modules.fitness.FitnessFunction; import jcgp.modules.fitness.TestCase; import jcgp.modules.fitness.TestCaseEvaluator; import jcgp.modules.mutator.Mutator; import jcgp.modules.mutator.PointMutator; import jcgp.parameters.BooleanParameter; +import jcgp.parameters.DoubleParameter; import jcgp.parameters.IntegerParameter; import jcgp.parameters.Parameter; import jcgp.population.Population; +/** + * @author Eduardo Pedroni + * + */ public class JCGP { /** @@ -49,52 +54,57 @@ public class JCGP { public Resources() { createCoreParameters(); - numberGenerator = new Random((int) get("seed")); - + numberGenerator = new Random(getInt("seed")); set("arity", functionSet.getMaxArity()); } - public Object get(String key) { - return parameters.get(key).getValue(); - } - public int getInt(String key) { - return (int) parameters.get(key).getValue(); + 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) { - return (double) parameters.get(key).getValue(); + 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) { - return (boolean) parameters.get(key).getValue(); + 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) { - parameters.get(key).setValue(value); - } - - public Property<?> getProperty(String key) { - return parameters.get(key).valueProperty(); + 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 void setManagedParameter(String key, boolean value) { - parameters.get(key).setManaged(value); - } - - public void setHiddenParameter(String key, boolean value) { - parameters.get(key).setHidden(value); - } - public boolean contains(String key) { return parameters.containsKey(key); } - private void createCoreParameters() { + private void createCoreParameters() { parameters.put("rows", new IntegerParameter(8, "Rows")); parameters.put("columns", new IntegerParameter(9, "Columns")); parameters.put("inputs", new IntegerParameter(3, "Inputs")); @@ -102,28 +112,23 @@ public class JCGP { parameters.put("popSize", new IntegerParameter(5, "Population")); parameters.put("levelsBack", new IntegerParameter(2, "Levels back")); - parameters.put("nodes", new IntegerParameter(72, "Nodes", true, true)); - + IntegerParameter nodes = new IntegerParameter(1, "Nodes", false, true); + nodes.valueProperty().bind(((SimpleIntegerProperty) ((IntegerParameter) parameters.get("rows")).valueProperty()).multiply((SimpleIntegerProperty) ((IntegerParameter) parameters.get("columns")).valueProperty())); + parameters.put("nodes", nodes); + parameters.put("generations", new IntegerParameter(1000000, "Generations")); - parameters.put("currentGen", new IntegerParameter(0, "Generation", true, false)); + parameters.put("currentGen", new IntegerParameter(1, "Generation", false, false)); + parameters.put("runs", new IntegerParameter(5, "Runs")); + parameters.put("currentRun", new IntegerParameter(1, "Run", false, false)); parameters.put("arity", new IntegerParameter(0, "Max arity", true, true)); - parameters.put("seed", new IntegerParameter(123, "Seed")); - parameters.put("debug", new BooleanParameter(false, "Debug")); + parameters.put("verbose", new BooleanParameter(false, "Verbose")); parameters.put("report", new IntegerParameter(1, "Report")); } - // TODO fix this up - private void resetParameters(EvolutionaryAlgorithm ea, Mutator mu, FitnessFunction ff) { - Iterator<Entry<String, Parameter>> it = parameters.entrySet().iterator(); - while (it.hasNext()) { - ((Parameter) ((Map.Entry<String, Parameter>) it.next()).getValue()).reset(); - } - } - /** * * @@ -152,11 +157,11 @@ public class JCGP { * FunctionSet functions */ public Function getRandomFunction() { - return functionSet.getFunction(numberGenerator.nextInt(functionSet.getAllowedFunctionCount())); + return functionSet.getAllowedFunction(numberGenerator.nextInt(functionSet.getAllowedFunctionCount())); } public Function getFunction(int index) { - return functionSet.getFunction(index); + return functionSet.getAllowedFunction(index); } public void setFunctionSet(int index) { @@ -205,27 +210,36 @@ public class JCGP { // mutators private Mutator[] mutators = new Mutator[] { new PointMutator() }; - private Mutator mutator = mutators[0]; + private Mutator mutator; // evolutionary algorithms private EvolutionaryAlgorithm[] evolutionaryAlgorithms = new EvolutionaryAlgorithm[] { - new StandardEA() }; - private EvolutionaryAlgorithm evolutionaryAlgorithm = evolutionaryAlgorithms[0]; + new MuPlusLambda(), + new TournamentSelection()}; + private EvolutionaryAlgorithm evolutionaryAlgorithm; // fitness evaluators private FitnessFunction[] fitnessFunctions = new FitnessFunction[] { new TestCaseEvaluator() }; - private FitnessFunction fitnessFunction = fitnessFunctions[0]; - - // the population of chromosomes - private Population population = new Population(resources); - + private FitnessFunction fitnessFunction; + /* + * the population of chromosomes + */ + private Population population; + public JCGP() { + population = new Population(resources); + + evolutionaryAlgorithm = evolutionaryAlgorithms[0]; + + mutator = mutators[0]; + + fitnessFunction = fitnessFunctions[0]; + resources.setTestCases(new TestCase(new Integer[]{1, 2, 3}, new Integer[]{4, 5, 6}), new TestCase(new Integer[]{1, 12, 4}, new Integer[]{6, 21, 2})); - // for (int i = 0; i < (int) resources.get("generations"); i++) { // // resources.set("currentGen", ((int) resources.get("currentGen")) + 1); @@ -301,4 +315,48 @@ public class JCGP { return fitnessFunction; } + + /** + * @param mutator the mutator to set + */ + public void setMutator(int index) { + this.mutator = mutators[index]; + } + + + /** + * @param evolutionaryAlgorithm the evolutionaryAlgorithm to set + */ + public void setEvolutionaryAlgorithm(int index) { + this.evolutionaryAlgorithm = evolutionaryAlgorithms[index]; + } + + + /** + * @param fitnessFunction the fitnessFunction to set + */ + public void setFitnessFunction(int index) { + this.fitnessFunction = fitnessFunctions[index]; + } + + public void nextGeneration() { + resources.set("currentGen", resources.getInt("currentGen") + 1); + + fitnessFunction.evaluate(population, resources); + evolutionaryAlgorithm.evolve(population, mutator, resources); + + if (evolutionaryAlgorithm.getFittestChromosome().getFitness() >= 6) { + System.out.println("solution found"); + evolutionaryAlgorithm.getFittestChromosome().printNodes(); + } else { + System.out.println("Generation: " + resources.getInt("currentGen") + ", fitness: " + evolutionaryAlgorithm.getFittestChromosome().getFitness()); + } + } + + public void start() { + while (resources.getInt("currentGen") <= resources.getInt("generations")) { + nextGeneration(); + } + // TODO print something? + } } diff --git a/src/jcgp/function/Arithmetic.java b/src/jcgp/function/Arithmetic.java index 7ec1366..b61ee65 100644 --- a/src/jcgp/function/Arithmetic.java +++ b/src/jcgp/function/Arithmetic.java @@ -9,7 +9,6 @@ import jcgp.population.Connection; public class Arithmetic extends FunctionSet { public Arithmetic() { - maxArity = 2; name = "Arithmetic"; functionList = new Function[]{ new Addition(), diff --git a/src/jcgp/function/BitwiseLogic.java b/src/jcgp/function/BitwiseLogic.java index 033534d..7ced8e8 100644 --- a/src/jcgp/function/BitwiseLogic.java +++ b/src/jcgp/function/BitwiseLogic.java @@ -9,7 +9,6 @@ import jcgp.population.Connection; public class BitwiseLogic extends FunctionSet { public BitwiseLogic() { - maxArity = 2; name = "32-bit Logic"; functionList = new Function[]{ new And(), diff --git a/src/jcgp/function/BooleanLogic.java b/src/jcgp/function/BooleanLogic.java index d31b798..7e441f2 100644 --- a/src/jcgp/function/BooleanLogic.java +++ b/src/jcgp/function/BooleanLogic.java @@ -9,7 +9,6 @@ import jcgp.population.Connection; public class BooleanLogic extends FunctionSet { public BooleanLogic() { - maxArity = 2; name = "1-bit Logic"; functionList = new Function[]{ new And(), diff --git a/src/jcgp/function/FunctionSet.java b/src/jcgp/function/FunctionSet.java index 49ff7e7..fef8f88 100644 --- a/src/jcgp/function/FunctionSet.java +++ b/src/jcgp/function/FunctionSet.java @@ -12,7 +12,6 @@ import java.util.Iterator; public abstract class FunctionSet { protected Function[] functionList; protected ArrayList<Function> allowedFunctions; - protected int maxArity; protected String name; public int getAllowedFunctionCount() { @@ -23,12 +22,22 @@ public abstract class FunctionSet { return functionList.length; } - public Function getFunction(int index) { + public Function getAllowedFunction(int index) { return allowedFunctions.get(index); } + public Function getFunction(int index) { + return functionList[index]; + } + public int getMaxArity(){ - return maxArity; + int arity = 0; + for (Function function : allowedFunctions) { + if (function.getArity() > arity) { + arity = function.getArity(); + } + } + return arity; } public String getName() { @@ -58,4 +67,8 @@ public abstract class FunctionSet { public String toString() { return name; } + + public boolean isEnabled(Function f) { + return allowedFunctions.contains(f); + } }
\ No newline at end of file diff --git a/src/jcgp/gui/GUIConsole.java b/src/jcgp/gui/GUIConsole.java index a14a23b..15ef2f6 100644 --- a/src/jcgp/gui/GUIConsole.java +++ b/src/jcgp/gui/GUIConsole.java @@ -1,5 +1,10 @@ package jcgp.gui; +import java.io.IOException; +import java.io.OutputStream; +import java.io.PrintStream; + +import javafx.application.Platform; import javafx.event.EventHandler; import javafx.scene.Cursor; import javafx.scene.control.TextArea; @@ -17,7 +22,12 @@ public class GUIConsole extends AnchorPane { textArea.setEditable(false); textArea.setWrapText(true); - //setStyle("-fx-border-width: 5 0 0 0; -fx-border-color: #D1D1D1"); +// System.setOut(new PrintStream(new OutputStream() { +// @Override +// public void write(final int b) throws IOException { +// textArea.appendText(String.valueOf((char) b)); +// } +// })); setResizeListeners(); diff --git a/src/jcgp/gui/SettingsPane.java b/src/jcgp/gui/SettingsPane.java deleted file mode 100644 index 594147f..0000000 --- a/src/jcgp/gui/SettingsPane.java +++ /dev/null @@ -1,266 +0,0 @@ -package jcgp.gui; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; - -import javafx.event.ActionEvent; -import javafx.event.EventHandler; -import javafx.geometry.Insets; -import javafx.scene.Cursor; -import javafx.scene.control.CheckBox; -import javafx.scene.control.ComboBox; -import javafx.scene.input.MouseEvent; -import javafx.scene.layout.AnchorPane; -import javafx.scene.layout.VBox; -import javafx.scene.text.Font; -import javafx.scene.text.Text; -import jcgp.GUI; -import jcgp.JCGP; -import jcgp.function.FunctionSet; -import jcgp.gui.settings.GUIBooleanParameter; -import jcgp.gui.settings.GUIDoubleParameter; -import jcgp.gui.settings.GUIIntegerParameter; -import jcgp.gui.settings.GUIParameter; -import jcgp.modules.ea.EvolutionaryAlgorithm; -import jcgp.modules.fitness.FitnessFunction; -import jcgp.modules.mutator.Mutator; -import jcgp.parameters.BooleanParameter; -import jcgp.parameters.DoubleParameter; -import jcgp.parameters.IntegerParameter; -import jcgp.parameters.Parameter; - -public class SettingsPane extends AnchorPane { - - private VBox mainContainer, eas, mutators, ffs; - private boolean dragging = false; - - public SettingsPane(JCGP cgp) { - super(); - setResizeListeners(); - - //setStyle("-fx-border-width: 0 0 0 5; -fx-border-color: #D1D1D1"); - - mainContainer = new VBox(); - - AnchorPane.setTopAnchor(mainContainer, 0.0); - AnchorPane.setBottomAnchor(mainContainer, 0.0); - AnchorPane.setRightAnchor(mainContainer, 0.0); - AnchorPane.setLeftAnchor(mainContainer, GUI.RESIZE_MARGIN); - mainContainer.setPadding(new Insets(5, 0, 0, 0)); - mainContainer.setSpacing(6); - - setMinWidth(GUI.SETTINGS_WIDTH); - setPrefWidth(GUI.SETTINGS_WIDTH); - - makeBaseParameters(cgp); - makeEAParameters(cgp); - mainContainer.getChildren().add(eas); - - makeMutatorParameters(cgp); - mainContainer.getChildren().add(mutators); - - makeFitnessFunctionParameters(cgp); - mainContainer.getChildren().add(ffs); - - makeNodeFunctionParameters(cgp); - - getChildren().add(mainContainer); - } - - private void makeBaseParameters(JCGP cgp) { - VBox vb = new VBox(); - vb.setSpacing(2); - - Text header = new Text("Base Parameters"); - header.setFont(Font.font("Arial", 14)); - header.setUnderline(true); - - vb.getChildren().add(header); - - ArrayList<GUIParameter> gp = new ArrayList<GUIParameter>(); - - gp.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("rows"))); - gp.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("columns"))); - gp.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("inputs"))); - gp.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("outputs"))); - gp.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("levelsBack"))); - - gp.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("popSize"))); - gp.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("generations"))); - gp.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("runs"))); - - gp.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("seed"))); - gp.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("report"))); - gp.add(new GUIBooleanParameter((BooleanParameter) cgp.getResources().getParameter("debug"))); - - vb.getChildren().addAll(gp); - - mainContainer.getChildren().add(vb); - } - - private void makeEAParameters(JCGP cgp) { - eas = new VBox(); - eas.setSpacing(2); - - Text header = new Text("EA"); - header.setFont(Font.font("Arial", 14)); - header.setUnderline(true); - - eas.getChildren().add(header); - - ComboBox<EvolutionaryAlgorithm> eab = new ComboBox<EvolutionaryAlgorithm>(); - eab.getItems().addAll(cgp.getEvolutionaryAlgorithms()); - eab.getSelectionModel().select(cgp.getEvolutionaryAlgorithm()); - eab.prefWidthProperty().bind(mainContainer.widthProperty()); - eas.getChildren().add(eab); - - addParameters(cgp.getEvolutionaryAlgorithm().getLocalParameters().entrySet().iterator(), eas); - } - - private void makeMutatorParameters(JCGP cgp) { - mutators = new VBox(); - mutators.setSpacing(2); - - Text header = new Text("Mutator"); - header.setFont(Font.font("Arial", 14)); - header.setUnderline(true); - - mutators.getChildren().add(header); - - ComboBox<Mutator> mb = new ComboBox<Mutator>(); - mb.getItems().addAll(cgp.getMutators()); - mb.getSelectionModel().select(cgp.getMutator()); - mb.prefWidthProperty().bind(mainContainer.widthProperty()); - mutators.getChildren().add(mb); - - addParameters(cgp.getMutator().getLocalParameters().entrySet().iterator(), mutators); - } - - private void makeFitnessFunctionParameters(JCGP cgp) { - ffs = new VBox(); - ffs.setSpacing(2); - - Text header = new Text("Fitness Function"); - header.setFont(Font.font("Arial", 14)); - header.setUnderline(true); - - ffs.getChildren().add(header); - - ComboBox<FitnessFunction> ff = new ComboBox<FitnessFunction>(); - ff.getItems().addAll(cgp.getFitnessFunctions()); - ff.getSelectionModel().select(cgp.getFitnessFunction()); - ff.prefWidthProperty().bind(mainContainer.widthProperty()); - ffs.getChildren().add(ff); - - addParameters(cgp.getFitnessFunction().getLocalParameters().entrySet().iterator(), ffs); - } - - private void makeNodeFunctionParameters(JCGP cgp) { - VBox vb = new VBox(); - vb.setSpacing(2); - - Text header = new Text("Node Functions"); - header.setFont(Font.font("Arial", 14)); - header.setUnderline(true); - - vb.getChildren().add(header); - - ComboBox<FunctionSet> nf = new ComboBox<FunctionSet>(); - nf.getItems().addAll(cgp.getResources().getFunctionSets()); - nf.getSelectionModel().select(cgp.getResources().getFunctionSet()); - nf.prefWidthProperty().bind(mainContainer.widthProperty()); - vb.getChildren().add(nf); - - // TODO make this function re-usable - addFunctions(cgp.getResources().getFunctionSet(), vb); - - mainContainer.getChildren().add(vb); - } - - /** - * @param cgp - * @param vb - */ - private void addParameters(Iterator<Entry<String, Parameter>> it, VBox vb) { - while (it.hasNext()) { - Parameter parameter = ((Map.Entry<String, Parameter>) it.next()).getValue(); - if (parameter instanceof IntegerParameter) { - vb.getChildren().add(new GUIIntegerParameter((IntegerParameter) parameter)); - } else if (parameter instanceof DoubleParameter) { - vb.getChildren().add(new GUIDoubleParameter((DoubleParameter) parameter)); - } else if (parameter instanceof BooleanParameter) { - vb.getChildren().add(new GUIBooleanParameter((BooleanParameter) parameter)); - } - } - } - - private void addFunctions(final FunctionSet fs, VBox vb) { - CheckBox cb; - for (int i = 0; i < fs.getTotalFunctionCount(); i++) { - cb = new CheckBox(fs.getFunction(i).getName()); - cb.setId(String.valueOf(i)); - cb.setSelected(true); - final int index = i; - cb.setOnAction(new EventHandler<ActionEvent>() { - @Override - public void handle(ActionEvent event) { - if (((CheckBox) event.getSource()).isSelected()) { - fs.enableFunction(index); - } else { - fs.disableFunction(index); - } - } - }); - vb.getChildren().add(cb); - } - } - - 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); - } - -} diff --git a/src/jcgp/gui/population/ChromosomePane.java b/src/jcgp/gui/population/ChromosomePane.java deleted file mode 100644 index 7fa8a54..0000000 --- a/src/jcgp/gui/population/ChromosomePane.java +++ /dev/null @@ -1,106 +0,0 @@ -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.GUI; -import jcgp.population.Chromosome; -import jcgp.population.Connection; -import jcgp.population.Input; -import jcgp.population.Node; - - -public class ChromosomePane extends ScrollPane { - - private GUINode[][] guiNodes; - private GUIInput[] guiInputs; - private GUIOutput[] guiOutputs; - - private Pane content; - - private ArrayList<Line> connectionLines; - - private boolean target = false; - - public ChromosomePane(Chromosome chromosome) { - super(); - connectionLines = new ArrayList<Line>(); - - //setMouseTransparent(true); - - content = new Pane(); - content.setId("content pane for genes"); - - // generate the GUIGenes - // inputs - guiInputs = new GUIInput[(int) GUI.resources.get("inputs")]; - for (int i = 0; i < guiInputs.length; i++) { - // make the GUI elements - guiInputs[i] = new GUIInput(this, chromosome.getInput(i)); - content.getChildren().addAll(guiInputs[i]); - } - // nodes - guiNodes = new GUINode[(int) GUI.resources.get("rows")][(int) GUI.resources.get("columns")]; - double angle, xPos, yPos; - for (int r = 0; r < guiNodes.length; r++) { - for (int c = 0; c < guiNodes[r].length; c++) { - // make the connection lines - Line lines[] = new Line[(int) GUI.resources.get("arity")]; - for (int l = 0; l < lines.length; l++) { - angle = ((((double) (l + 1)) / ((double) (lines.length + 1))) * GUIGene.THETA) - (GUIGene.THETA / 2); - xPos = (-Math.cos(angle) * GUIGene.NODE_RADIUS) + (((c + 1) * (2 * GUIGene.NODE_RADIUS + GUIGene.SPACING)) + GUIGene.NODE_RADIUS); - yPos = (Math.sin(angle) * GUIGene.NODE_RADIUS) + ((r * (2 * GUIGene.NODE_RADIUS + GUIGene.SPACING)) + GUIGene.NODE_RADIUS); - - lines[l] = new Line(xPos, yPos, xPos, yPos); - lines[l].setMouseTransparent(true); - lines[l].setVisible(false); - connectionLines.add(lines[l]); - } - // make the GUI elements - guiNodes[r][c] = new GUINode(this, chromosome.getNode(r, c), lines); - } - content.getChildren().addAll(guiNodes[r]); - } - - // outputs - guiOutputs = new GUIOutput[(int) GUI.resources.get("outputs")]; - for (int i = 0; i < guiOutputs.length; i++) { - xPos = (((int) GUI.resources.get("columns") + 1) * (2 * GUIGene.NODE_RADIUS + GUIGene.SPACING)); - yPos = (chromosome.getOutput(i).getIndex() * (2 * GUIGene.NODE_RADIUS + GUIGene.SPACING)) + GUIGene.NODE_RADIUS; - // make the line - Line line = new Line(xPos, yPos, xPos, yPos); - line.setMouseTransparent(true); - line.setVisible(false); - connectionLines.add(line); - // make the GUI elements - guiOutputs[i] = new GUIOutput(this, chromosome.getOutput(i), line); - content.getChildren().addAll(guiOutputs[i]); - } - - content.getChildren().addAll(connectionLines); - setPrefWidth(620); - setContent(content); - } - - public GUIGene getGuiGene(Connection gene) { - if (gene instanceof Input) { - return guiInputs[((Input) gene).getIndex()]; - } else if (gene instanceof Node) { - return guiNodes[((Node) gene).getRow()][((Node) gene).getColumn()]; - } else { - // something bad happened! - throw new ClassCastException(); - } - - } - - public boolean isTarget() { - return target; - } - - public void setTarget(boolean newValue) { - target = newValue; - } -} diff --git a/src/jcgp/gui/population/GUIGene.java b/src/jcgp/gui/population/GUIGene.java index 3addca7..a37eb19 100644 --- a/src/jcgp/gui/population/GUIGene.java +++ b/src/jcgp/gui/population/GUIGene.java @@ -4,6 +4,7 @@ import javafx.beans.property.SimpleObjectProperty; import javafx.scene.Group; import javafx.scene.shape.Circle; import javafx.scene.text.Text; +import jcgp.gui.ChromosomePane; import jcgp.population.Connection; import jcgp.population.Gene; diff --git a/src/jcgp/gui/population/GUIInput.java b/src/jcgp/gui/population/GUIInput.java index 84e8a2a..30ce4ac 100644 --- a/src/jcgp/gui/population/GUIInput.java +++ b/src/jcgp/gui/population/GUIInput.java @@ -12,6 +12,7 @@ import javafx.scene.text.Font; import javafx.scene.text.Text; import javafx.scene.text.TextAlignment; import jcgp.GUI; +import jcgp.gui.ChromosomePane; import jcgp.population.Connection; import jcgp.population.Input; import jcgp.population.Output; diff --git a/src/jcgp/gui/population/GUINode.java b/src/jcgp/gui/population/GUINode.java index eeacb9e..6fc84da 100644 --- a/src/jcgp/gui/population/GUINode.java +++ b/src/jcgp/gui/population/GUINode.java @@ -14,6 +14,7 @@ import javafx.scene.text.Font; import javafx.scene.text.Text; import javafx.scene.text.TextAlignment; import jcgp.GUI; +import jcgp.gui.ChromosomePane; import jcgp.population.Connection; import jcgp.population.Input; import jcgp.population.Node; @@ -56,10 +57,10 @@ public class GUINode extends GUIGene { text.setX(-NODE_RADIUS); text.setVisible(true); - Circle[] sockets = new Circle[(int) GUI.resources.get("arity")]; + Circle[] sockets = new Circle[GUI.resources.getInt("arity")]; double angle, xPos, yPos; for (int l = 0; l < sockets.length; l++) { - angle = ((((double) (l + 1)) / ((double) ((int) GUI.resources.get("arity") + 1))) * THETA) - (THETA / 2); + angle = ((((double) (l + 1)) / ((GUI.resources.getDouble("arity") + 1))) * THETA) - (THETA / 2); xPos = -Math.cos(angle) * NODE_RADIUS; yPos = Math.sin(angle) * NODE_RADIUS; @@ -335,7 +336,7 @@ public class GUINode extends GUIGene { } else if (target instanceof GUINode) { // target and source are nodes, let's look at levels back Node t = ((GUINode) target).getGene(), s = ((GUINode) source).getGene(); - if (s.getColumn() - t.getColumn() > 0 && s.getColumn() - t.getColumn() <= (int) GUI.resources.get("levelsBack")) { + if (s.getColumn() - t.getColumn() > 0 && s.getColumn() - t.getColumn() <= GUI.resources.getInt("levelsBack")) { return true; } return false; @@ -462,4 +463,8 @@ public class GUINode extends GUIGene { lines[connectionIndex].setEndX(gene.getLayoutX() + NODE_RADIUS); lines[connectionIndex].setEndY(gene.getLayoutY()); } + + public void updateFunction() { + text.setText(node.getFunction().getName()); + } } diff --git a/src/jcgp/gui/population/GUIOutput.java b/src/jcgp/gui/population/GUIOutput.java index 57042eb..16d95f0 100644 --- a/src/jcgp/gui/population/GUIOutput.java +++ b/src/jcgp/gui/population/GUIOutput.java @@ -14,6 +14,7 @@ import javafx.scene.text.Font; import javafx.scene.text.Text; import javafx.scene.text.TextAlignment; import jcgp.GUI; +import jcgp.gui.ChromosomePane; import jcgp.population.Connection; import jcgp.population.Input; import jcgp.population.Node; @@ -31,7 +32,7 @@ public class GUIOutput extends GUIGene { this.output = output; this.sourceLine = line; - relocate((((int) GUI.resources.get("columns") + 1) * (2 * NODE_RADIUS + SPACING)) + NODE_RADIUS, + relocate(((GUI.resources.getInt("columns") + 1) * (2 * NODE_RADIUS + SPACING)) + NODE_RADIUS, (output.getIndex() * (2 * NODE_RADIUS + SPACING)) + NODE_RADIUS); // set the line ends correctly @@ -242,14 +243,6 @@ public class GUIOutput extends GUIGene { } }); - output.sourceProperty().addListener(new ChangeListener<Connection>() { - @Override - public void changed(ObservableValue<? extends Connection> observable, - Connection oldValue, Connection newValue) { - updateLines(); - } - }); - } @Override diff --git a/src/jcgp/gui/settings/GUIBooleanParameter.java b/src/jcgp/gui/settings/GUIBooleanParameter.java deleted file mode 100644 index 7b20c3b..0000000 --- a/src/jcgp/gui/settings/GUIBooleanParameter.java +++ /dev/null @@ -1,24 +0,0 @@ -package jcgp.gui.settings; - -import javafx.geometry.Pos; -import javafx.scene.control.CheckBox; -import jcgp.parameters.BooleanParameter; - -public class GUIBooleanParameter extends GUIParameter { - - public GUIBooleanParameter(BooleanParameter parameter) { - setAlignment(Pos.CENTER_LEFT); - setSpacing(5); - - this.parameter = parameter; - - value = new CheckBox(parameter.getName()); - ((CheckBox) value).setSelected(parameter.getValue()); - - value.setDisable(parameter.isManaged()); - - getChildren().add(value); - - } - -} diff --git a/src/jcgp/gui/settings/GUIDoubleParameter.java b/src/jcgp/gui/settings/GUIDoubleParameter.java deleted file mode 100644 index d61899b..0000000 --- a/src/jcgp/gui/settings/GUIDoubleParameter.java +++ /dev/null @@ -1,33 +0,0 @@ -package jcgp.gui.settings; - -import javafx.geometry.Pos; -import javafx.scene.control.TextField; -import javafx.scene.layout.Priority; -import javafx.scene.text.Text; -import jcgp.GUI; -import jcgp.parameters.DoubleParameter; - -public class GUIDoubleParameter extends GUIParameter { - - public GUIDoubleParameter(DoubleParameter parameter) { - setAlignment(Pos.CENTER_LEFT); - setSpacing(5); - - this.parameter = parameter; - - name = new Text(parameter.getName()); - value = new TextField(String.valueOf(parameter.getValue())); - - ((TextField) value).setAlignment(Pos.CENTER_RIGHT); - - setHgrow(value, Priority.ALWAYS); - - name.setWrappingWidth(GUI.WRAP_WIDTH); - - value.setDisable(parameter.isManaged()); - - getChildren().addAll(name, value); - - } - -} diff --git a/src/jcgp/gui/settings/GUIIntegerParameter.java b/src/jcgp/gui/settings/GUIIntegerParameter.java deleted file mode 100644 index b7a23a4..0000000 --- a/src/jcgp/gui/settings/GUIIntegerParameter.java +++ /dev/null @@ -1,31 +0,0 @@ -package jcgp.gui.settings; - -import javafx.geometry.Pos; -import javafx.scene.control.TextField; -import javafx.scene.layout.Priority; -import javafx.scene.text.Text; -import jcgp.GUI; -import jcgp.parameters.IntegerParameter; - -public class GUIIntegerParameter extends GUIParameter { - - public GUIIntegerParameter(IntegerParameter parameter) { - setAlignment(Pos.CENTER_LEFT); - setSpacing(5); - - this.parameter = parameter; - - name = new Text(parameter.getName()); - value = new TextField(String.valueOf(parameter.getValue())); - - ((TextField) value).setAlignment(Pos.CENTER_RIGHT); - - setHgrow(value, Priority.ALWAYS); - - name.setWrappingWidth(GUI.WRAP_WIDTH); - - value.setDisable(parameter.isManaged()); - - getChildren().addAll(name, value); - } -} diff --git a/src/jcgp/gui/settings/GUIParameter.java b/src/jcgp/gui/settings/GUIParameter.java deleted file mode 100644 index 0547758..0000000 --- a/src/jcgp/gui/settings/GUIParameter.java +++ /dev/null @@ -1,14 +0,0 @@ -package jcgp.gui.settings; - -import javafx.scene.control.Control; -import javafx.scene.layout.HBox; -import javafx.scene.text.Text; -import jcgp.parameters.Parameter; - -public abstract class GUIParameter extends HBox { - - protected Parameter parameter; - protected Text name; - protected Control value; - -} diff --git a/src/jcgp/modules/Module.java b/src/jcgp/modules/Module.java index 7cf0b8d..9e0b267 100644 --- a/src/jcgp/modules/Module.java +++ b/src/jcgp/modules/Module.java @@ -6,9 +6,6 @@ import jcgp.JCGP.Resources; import jcgp.parameters.Parameter; public interface Module { - - public void activate(Resources parameters); - public HashMap<String, Parameter> getLocalParameters(); - + public ModuleStatus getStatus(Resources resources); } diff --git a/src/jcgp/modules/ea/StandardEA.java b/src/jcgp/modules/ea/StandardEA.java deleted file mode 100644 index 1d27004..0000000 --- a/src/jcgp/modules/ea/StandardEA.java +++ /dev/null @@ -1,79 +0,0 @@ -package jcgp.modules.ea; - -import java.util.HashMap; - -import jcgp.JCGP.Resources; -import jcgp.modules.mutator.Mutator; -import jcgp.parameters.IntegerParameter; -import jcgp.parameters.Parameter; -import jcgp.population.Chromosome; -import jcgp.population.Population; - -/** - * (μ + λ) EA. - * - * - * @author Eduardo Pedroni - * - */ -public class StandardEA implements EvolutionaryAlgorithm { - - private Chromosome fittestChromosome; - - private IntegerParameter parents, offspring; - private HashMap<String, Parameter> localParameters; - - public StandardEA() { - parents = new IntegerParameter(1, "Parents"); - offspring = new IntegerParameter(4, "Offspring"); - - localParameters = new HashMap<String, Parameter>(); - - localParameters.put("mu", parents); - localParameters.put("lambda", offspring); - } - - @Override - public void evolve(Population population, Mutator mutator, Resources parameters) { - // select fittest chromosome - int fittest = 0; - - for (int i = 1; i < (int) parameters.get("popSize"); i++) { - if (population.getChromosome(i).getFitness() >= population.getChromosome(fittest).getFitness()) { - fittest = i; - } - } - fittestChromosome = population.getChromosome(fittest); - population.setBestIndividual(fittest); - // create copies of fittest chromosome, mutate them - Chromosome fc = population.getChromosome(fittest); - for (int i = 0; i < (int) parameters.get("popSize"); i++) { - if (i != fittest) { - population.getChromosome(i).copyConnections(fc); - mutator.mutate(population.getChromosome(i), parameters); - } - } - } - - @Override - public Chromosome getFittestChromosome() { - return fittestChromosome; - } - - @Override - public void activate(Resources parameters) { - parameters.getParameter("popSize").setManaged(true); - } - - @Override - public HashMap<String, Parameter> getLocalParameters() { - return localParameters; - } - - @Override - public String toString() { - return "(μ + λ)"; - } - - -} diff --git a/src/jcgp/modules/fitness/TestCaseEvaluator.java b/src/jcgp/modules/fitness/TestCaseEvaluator.java index 77b282c..d8c1255 100644 --- a/src/jcgp/modules/fitness/TestCaseEvaluator.java +++ b/src/jcgp/modules/fitness/TestCaseEvaluator.java @@ -3,6 +3,7 @@ package jcgp.modules.fitness; import java.util.HashMap; import jcgp.JCGP.Resources; +import jcgp.modules.ModuleStatus; import jcgp.parameters.Parameter; import jcgp.population.Population; @@ -11,13 +12,13 @@ public class TestCaseEvaluator implements FitnessFunction { @Override public void evaluate(Population population, Resources resources) { // for every chromosome in the population - for (int i = 0; i < (int) resources.get("popSize"); i++) { + 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 < (int) resources.get("outputs"); o++) { + for (int o = 0; o < resources.getInt("outputs"); o++) { if (population.getChromosome(i).getOutput(o).calculate() == resources.getTestCase(t).getOutput(o)) { fitness++; } @@ -28,17 +29,17 @@ public class TestCaseEvaluator implements FitnessFunction { } @Override - public void activate(Resources parameters) { - // nothing - } - - @Override public HashMap<String, Parameter> getLocalParameters() { - return new HashMap<String, Parameter>(); + return null; } @Override public String toString() { return "Test case"; } + + @Override + public ModuleStatus getStatus(Resources resources) { + return null; + } } diff --git a/src/jcgp/modules/mutator/PointMutator.java b/src/jcgp/modules/mutator/PointMutator.java index e9be153..2298368 100644 --- a/src/jcgp/modules/mutator/PointMutator.java +++ b/src/jcgp/modules/mutator/PointMutator.java @@ -2,6 +2,7 @@ package jcgp.modules.mutator; import java.util.HashMap; +import jcgp.modules.ModuleStatus; import jcgp.parameters.DoubleParameter; import jcgp.parameters.Parameter; import jcgp.JCGP.Resources; @@ -12,9 +13,11 @@ import jcgp.population.Output; public class PointMutator implements Mutator { - private Parameter mutationRate; + private DoubleParameter mutationRate; private HashMap<String, Parameter> localParameters; + private ModuleStatus status = ModuleStatus.READY; + public PointMutator() { mutationRate = new DoubleParameter(0.5, "Percent mutation"); @@ -24,29 +27,24 @@ public class PointMutator implements Mutator { @Override public void mutate(Chromosome chromosome, Resources resources) { - int mutations = (int) Math.ceil((((double) mutationRate.getValue()) * (((((Integer) resources.get("nodes")).doubleValue() + ((Integer) resources.get("outputs")).doubleValue())) / (double) 100))); + int mutations = (int) Math.ceil(((mutationRate.get()) * ((((resources.getDouble("nodes")) + (resources.getDouble("outputs")))) / (double) 100))); for (int i = 0; i < mutations; i++) { MutableElement m = chromosome.getRandomMutableElement(); if (m instanceof Output) { m.setConnection(0, chromosome.getRandomConnection()); } else if (m instanceof Node) { - int geneType = resources.getRandomInt(1 + ((int) resources.get("arity"))); + int geneType = resources.getRandomInt(1 + resources.getInt("arity")); if (geneType < 1) { ((Node) m).setFunction(resources.getRandomFunction()); } else { - m.setConnection(resources.getRandomInt((int) resources.get("arity")), chromosome.getRandomConnection(((Node) m).getColumn())); + m.setConnection(resources.getRandomInt(resources.getInt("arity")), chromosome.getRandomConnection(((Node) m).getColumn())); } } } } @Override - public void activate(Resources parameters) { - // nothing - } - - @Override public HashMap<String, Parameter> getLocalParameters() { return localParameters; } @@ -56,4 +54,18 @@ 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/parameters/BooleanParameter.java b/src/jcgp/parameters/BooleanParameter.java index 0f339a1..63e9c73 100644 --- a/src/jcgp/parameters/BooleanParameter.java +++ b/src/jcgp/parameters/BooleanParameter.java @@ -3,30 +3,30 @@ package jcgp.parameters; import javafx.beans.property.SimpleBooleanProperty; public class BooleanParameter extends Parameter { - - public BooleanParameter(boolean value, String name) { - super(name); + + private SimpleBooleanProperty value; + + public BooleanParameter(boolean value, String name, boolean editable, boolean hidden) { + super(name, editable, hidden); this.value = new SimpleBooleanProperty(value); } - public BooleanParameter(boolean value, String name, boolean managed, boolean hidden) { - super(name, managed, hidden); + public BooleanParameter(boolean value, String name) { + super(name, true, false); this.value = new SimpleBooleanProperty(value); } - @Override - public Boolean getValue() { - return ((SimpleBooleanProperty) this.value).get(); + public boolean get() { + return value.get(); } - @Override - public SimpleBooleanProperty valueProperty() { - return (SimpleBooleanProperty) value; - } - - @Override - public void setValue(Object value) { - ((SimpleBooleanProperty) this.value).set((boolean) value); + public void set(boolean newValue) { + if (!value.isBound()) { + value.set(newValue); + } } + public SimpleBooleanProperty valueProperty() { + return value; + } } diff --git a/src/jcgp/parameters/DoubleParameter.java b/src/jcgp/parameters/DoubleParameter.java index ade99cc..d555452 100644 --- a/src/jcgp/parameters/DoubleParameter.java +++ b/src/jcgp/parameters/DoubleParameter.java @@ -3,31 +3,31 @@ package jcgp.parameters; import javafx.beans.property.SimpleDoubleProperty; public class DoubleParameter extends Parameter { - - public DoubleParameter(double value, String name) { - super(name); + + protected SimpleDoubleProperty value; + + public DoubleParameter(double value, String name, boolean editable, boolean hidden) { + super(name, editable, hidden); this.value = new SimpleDoubleProperty(value); } - public DoubleParameter(double value, String name, boolean managed, boolean hidden) { - super(name, managed, hidden); + public DoubleParameter(double value, String name) { + super(name, true, false); this.value = new SimpleDoubleProperty(value); } + + public double get() { + return value.get(); + } - @Override - public Double getValue() { - return ((SimpleDoubleProperty) value).get(); + public void set(double newValue) { + if (!value.isBound()) { + value.set(newValue); + } } - @Override public SimpleDoubleProperty valueProperty() { - return (SimpleDoubleProperty) value; - } - - @Override - public void setValue(Object value) { - ((SimpleDoubleProperty) this.value).set((double) value); - + return value; } } diff --git a/src/jcgp/parameters/IntegerParameter.java b/src/jcgp/parameters/IntegerParameter.java index cc60179..c743e97 100644 --- a/src/jcgp/parameters/IntegerParameter.java +++ b/src/jcgp/parameters/IntegerParameter.java @@ -4,29 +4,30 @@ import javafx.beans.property.SimpleIntegerProperty; public class IntegerParameter extends Parameter { - public IntegerParameter(int value, String name) { - super(name); + protected SimpleIntegerProperty value; + + public IntegerParameter(int value, String name, boolean editable, boolean hidden) { + super(name, editable, hidden); this.value = new SimpleIntegerProperty(value); } - public IntegerParameter(int value, String name, boolean managed, boolean hidden) { - super(name, managed, hidden); + public IntegerParameter(int value, String name) { + super(name, true, false); this.value = new SimpleIntegerProperty(value); } + + public int get() { + return value.get(); + } - @Override - public Integer getValue() { - return ((SimpleIntegerProperty) this.value).get(); + public void set(int newValue) { + if (!value.isBound()) { + value.set(newValue); + } } - @Override public SimpleIntegerProperty valueProperty() { - return (SimpleIntegerProperty) value; - } - - @Override - public void setValue(Object value) { - ((SimpleIntegerProperty) this.value).set((int) value); + return value; } } diff --git a/src/jcgp/parameters/Parameter.java b/src/jcgp/parameters/Parameter.java index fcff9fd..42c70e4 100644 --- a/src/jcgp/parameters/Parameter.java +++ b/src/jcgp/parameters/Parameter.java @@ -1,58 +1,26 @@ package jcgp.parameters; -import javafx.beans.property.Property; public abstract class Parameter { - protected boolean managed = false; - protected boolean hidden = false; - - protected boolean originalManaged = false; - protected boolean originalHidden = false; - - protected Property<?> value; + protected boolean hidden = false, editable = true; protected String name; - public Parameter(String name, boolean managed, boolean hidden) { - this.name = name; - this.managed = originalManaged = managed; - this.hidden = originalHidden = hidden; - } - - public Parameter(String name) { + public Parameter(String name, boolean editable, boolean hidden) { this.name = name; - } - - public void setManaged(boolean value) { - managed = value; - } - - public boolean isManaged() { - return managed; - } - - public void setHidden(boolean value) { - hidden = value; + this.hidden = hidden; + this.editable = editable; } public boolean isHidden() { return hidden; } - public String getName() { - return name; + public boolean isEditable() { + return editable; } - public abstract Object getValue(); - - public abstract void setValue(Object value); - - public Property<?> valueProperty() { - return value; - } - - public void reset() { - hidden = originalHidden; - managed = originalManaged; + public String getName() { + return name; } } diff --git a/src/jcgp/population/Chromosome.java b/src/jcgp/population/Chromosome.java index 6f50025..297d298 100644 --- a/src/jcgp/population/Chromosome.java +++ b/src/jcgp/population/Chromosome.java @@ -55,22 +55,22 @@ public class Chromosome { * */ private void instantiateElements() { - inputs = new Input[((int) resources.get("inputs"))]; - for (int i = 0; i < ((int) resources.get("inputs")); i++) { + inputs = new Input[(resources.getInt("inputs"))]; + for (int i = 0; i < (resources.getInt("inputs")); i++) { inputs[i] = new Input(i); } - int arity = (int) resources.get("arity"); + int arity = resources.getInt("arity"); // rows first - nodes = new Node[((int) resources.get("rows"))][((int) resources.get("columns"))]; - for (int r = 0; r < ((int) resources.get("rows")); r++) { - for (int c = 0; c < ((int) resources.get("columns")); c++) { + nodes = new Node[(resources.getInt("rows"))][(resources.getInt("columns"))]; + for (int r = 0; r < (resources.getInt("rows")); r++) { + for (int c = 0; c < (resources.getInt("columns")); c++) { nodes[r][c] = new Node(this, r, c, arity); } } - outputs = new Output[((int) resources.get("outputs"))]; - for (int o = 0; o < ((int) resources.get("outputs")); o++) { + outputs = new Output[(resources.getInt("outputs"))]; + for (int o = 0; o < (resources.getInt("outputs")); o++) { outputs[o] = new Output(this, o); } } @@ -80,7 +80,7 @@ public class Chromosome { */ private void initialiseConnections() { - int arity = (int) resources.get("arity"); + int arity = resources.getInt("arity"); // initialise nodes - [rows][columns] for (int r = 0; r < nodes.length; r++) { @@ -103,7 +103,7 @@ public class Chromosome { * @param clone */ public void copyConnections(Chromosome clone) { - int arity = (int) resources.get("arity"); + int arity = resources.getInt("arity"); // copy nodes - [rows][columns] for (int r = 0; r < nodes.length; r++) { @@ -186,7 +186,7 @@ public class Chromosome { */ public MutableElement getRandomMutableElement() { // choose output or node - int index = resources.getRandomInt(outputs.length + ((int) resources.get("rows")) * ((int) resources.get("columns"))); + int index = resources.getRandomInt(outputs.length + (resources.getInt("rows")) * (resources.getInt("columns"))); if (index < outputs.length) { // outputs @@ -194,7 +194,7 @@ public class Chromosome { } else { // node index -= outputs.length; - return nodes[index / ((int) resources.get("columns"))][index % ((int) resources.get("columns"))]; + return nodes[index / (resources.getInt("columns"))][index % (resources.getInt("columns"))]; } } @@ -208,7 +208,7 @@ public class Chromosome { */ public Connection getRandomConnection(int column) { // work out the allowed range obeying levels back - int allowedColumns = ((column >= ((int) resources.get("levelsBack"))) ? ((int) resources.get("levelsBack")) : column); + int allowedColumns = ((column >= (resources.getInt("levelsBack"))) ? (resources.getInt("levelsBack")) : column); int offset = ((column - allowedColumns) * nodes.length) - inputs.length; // choose input or allowed node @@ -235,15 +235,14 @@ public class Chromosome { */ public Connection getRandomConnection() { // choose output or node - int index = resources.getRandomInt(inputs.length + ((int) resources.get("columns")) * ((int) resources.get("rows"))); - + int index = resources.getRandomInt(inputs.length + (resources.getInt("columns")) * (resources.getInt("rows"))); if (index < inputs.length) { // outputs return inputs[index]; } else { // node index -= inputs.length; - return nodes[index / ((int) resources.get("columns"))][index % ((int) resources.get("columns"))]; + return nodes[index / (resources.getInt("columns"))][index % (resources.getInt("columns"))]; } } @@ -278,15 +277,15 @@ public class Chromosome { } public boolean compareTo(Chromosome chromosome) { - for (int r = 0; r < ((int) resources.get("rows")); r++) { - for (int c = 0; c < ((int) resources.get("columns")); c++) { + for (int r = 0; r < (resources.getInt("rows")); r++) { + for (int c = 0; c < (resources.getInt("columns")); c++) { if (!(nodes[r][c].copyOf(chromosome.getNode(r, c)))) { return false; } } } - for (int o = 0; o < ((int) resources.get("outputs")); o++) { + for (int o = 0; o < (resources.getInt("outputs")); o++) { if (!(outputs[o].copyOf(chromosome.getOutput(o)))) { return false; } @@ -311,11 +310,11 @@ public class Chromosome { } public void printNodes() { - int arity = (int) resources.get("arity"); + int arity = resources.getInt("arity"); - for (int r = 0; r < ((int) resources.get("rows")); r++) { + for (int r = 0; r < (resources.getInt("rows")); r++) { System.out.print("r: " + r + "\t"); - for (int c = 0; c < ((int) resources.get("columns")); c++) { + for (int c = 0; c < (resources.getInt("columns")); c++) { System.out.print("N: (" + r + ", " + c + ") "); for (int i = 0; i < arity; i++) { System.out.print("C" + i + ": (" + nodes[r][c].getConnection(i).getDescription() + ") "); @@ -325,7 +324,7 @@ public class Chromosome { System.out.print("\n"); } - for (int o = 0; o < ((int) resources.get("outputs")); o++) { + for (int o = 0; o < (resources.getInt("outputs")); o++) { System.out.print("o: " + o + " (" + outputs[o].getSource().getDescription() + ")\t"); } } diff --git a/src/jcgp/population/Node.java b/src/jcgp/population/Node.java index d7013d3..141a32a 100644 --- a/src/jcgp/population/Node.java +++ b/src/jcgp/population/Node.java @@ -1,58 +1,46 @@ package jcgp.population; import java.util.ArrayList; +import java.util.Arrays; -import javafx.beans.property.SimpleObjectProperty; import jcgp.exceptions.InsufficientConnectionsException; import jcgp.function.Function; public class Node extends Gene implements MutableElement, Connection { - private SimpleObjectProperty<Function> function; - private ArrayList<SimpleObjectProperty<Connection>> connections; + private Function function; + private Connection[] connections; private int column, row; private Chromosome chromosome; public Node(Chromosome chromosome, int row, int column, int arity) { - this.function = new SimpleObjectProperty<Function>(); this.chromosome = chromosome; this.column = column; this.row = row; - this.connections = new ArrayList<SimpleObjectProperty<Connection>>(arity); - for (int c = 0; c < arity; c++) { - connections.add(new SimpleObjectProperty<Connection>()); - } } @Override public Object getValue() { //System.out.print("Calculating node: (" + row + ", " + column + ") > "); - Connection[] list = new Connection[function.get().getArity()]; - for (int i = 0; i < list.length; i++) { - list[i] = connections.get(i).get(); - } - - return function.get().run(list); + return function.run(Arrays.copyOfRange(connections, 0, function.getArity())); } public void setFunction(Function newFunction) { - function.set(newFunction); + function = newFunction; chromosome.recomputeActiveNodes(); } @Override public void setConnection(int index, Connection newConnection) { - connections.get(index).set(newConnection); + connections[index] = newConnection; chromosome.recomputeActiveNodes(); } public void initialise(Function newFunction, Connection ... newConnections) throws InsufficientConnectionsException { - function.set(newFunction); - if (newConnections.length >= connections.size()) { - for (int i = 0; i < connections.size(); i++) { - connections.get(i).set(newConnections[i]); - } + function = newFunction; + if (newConnections.length == function.getArity()) { + connections = newConnections; } else { throw new InsufficientConnectionsException(); } @@ -67,28 +55,20 @@ public class Node extends Gene implements MutableElement, Connection { } public Function getFunction() { - return function.get(); - } - - public SimpleObjectProperty<Function> functionProperty() { return function; } - - public ArrayList<SimpleObjectProperty<Connection>> connections() { - return connections; - } public Connection getConnection(int index) { - return connections.get(index).get(); + return connections[index]; } public void getActive(ArrayList<Node> activeNodes) { if (!activeNodes.contains(this)) { activeNodes.add(this); } - for (int i = 0; i < function.get().getArity(); i++) { - if (connections.get(i).get() instanceof Node) { - ((Node) connections.get(i).get()).getActive(activeNodes); + for (int i = 0; i < function.getArity(); i++) { + if (connections[i] instanceof Node) { + ((Node) connections[i]).getActive(activeNodes); } } @@ -99,17 +79,17 @@ public class Node extends Gene implements MutableElement, Connection { if (this != m) { if (m instanceof Node) { Node n = (Node) m; - if (function.get() == n.getFunction()) { + if (function == n.getFunction()) { if (column == n.getColumn() && row == n.getRow()) { - for (int i = 0; i < connections.size(); i++) { - if (connections.get(i).get() != n.getConnection(i)) { - if (connections.get(i).get() instanceof Input && n.getConnection(i) instanceof Input) { - if (((Input) connections.get(i).get()).getIndex() != ((Input) n.getConnection(i)).getIndex()) { + for (int i = 0; i < connections.length; i++) { + if (connections[i] != n.getConnection(i)) { + if (connections[i] instanceof Input && n.getConnection(i) instanceof Input) { + if (((Input) connections[i]).getIndex() != ((Input) n.getConnection(i)).getIndex()) { return false; } - } else if (connections.get(i).get() instanceof Node && n.getConnection(i) instanceof Node) { - if (((Node) connections.get(i).get()).getRow() != ((Node) n.getConnection(i)).getRow() && - ((Node) connections.get(i).get()).getColumn() != ((Node) n.getConnection(i)).getColumn()) { + } else if (connections[i] instanceof Node && n.getConnection(i) instanceof Node) { + if (((Node) connections[i]).getRow() != ((Node) n.getConnection(i)).getRow() && + ((Node) connections[i]).getColumn() != ((Node) n.getConnection(i)).getColumn()) { return false; } } else { diff --git a/src/jcgp/population/Output.java b/src/jcgp/population/Output.java index b7c6128..5cc6dcf 100644 --- a/src/jcgp/population/Output.java +++ b/src/jcgp/population/Output.java @@ -2,18 +2,16 @@ package jcgp.population; import java.util.ArrayList; -import javafx.beans.property.SimpleObjectProperty; - public class Output extends Gene implements MutableElement { - private SimpleObjectProperty<Connection> source; + private Connection source; private Chromosome chromosome; private int index; public Output(Chromosome chromosome, int index) { this.chromosome = chromosome; this.index = index; - this.source = new SimpleObjectProperty<Connection>(); + //this.source = new SimpleObjectProperty<Connection>(); } public Object calculate() { @@ -23,7 +21,7 @@ public class Output extends Gene implements MutableElement { @Override public void setConnection(int index, Connection newConnection) { - source.set(newConnection); + source = newConnection; chromosome.recomputeActiveNodes(); } @@ -32,16 +30,16 @@ public class Output extends Gene implements MutableElement { } public Connection getSource() { - return source.get(); - } - - public SimpleObjectProperty<Connection> sourceProperty() { return source; } + +// public SimpleObjectProperty<Connection> sourceProperty() { +// return source; +// } public void getActiveNodes(ArrayList<Node> activeNodes) { - if (source.get() instanceof Node) { - ((Node) source.get()).getActive(activeNodes); + if (source instanceof Node) { + ((Node) source).getActive(activeNodes); } } @@ -51,14 +49,14 @@ public class Output extends Gene implements MutableElement { if (m instanceof Output) { Output o = (Output) m; if (index == o.getIndex()) { - if (source.get() != o.getSource()) { - if (source.get() instanceof Input && o.getSource() instanceof Input) { - if (((Input) source.get()).getIndex() == ((Input) o.getSource()).getIndex()) { + if (source != o.getSource()) { + if (source instanceof Input && o.getSource() instanceof Input) { + if (((Input) source).getIndex() == ((Input) o.getSource()).getIndex()) { return true; } - } else if (source.get() instanceof Node && o.getSource() instanceof Node) { - if (((Node) source.get()).getRow() == ((Node) o.getSource()).getRow() && - ((Node) source.get()).getColumn() == ((Node) o.getSource()).getColumn()) { + } else if (source instanceof Node && o.getSource() instanceof Node) { + if (((Node) source).getRow() == ((Node) o.getSource()).getRow() && + ((Node) source).getColumn() == ((Node) o.getSource()).getColumn()) { return true; } } diff --git a/src/jcgp/population/Population.java b/src/jcgp/population/Population.java index 586f556..f5e0517 100644 --- a/src/jcgp/population/Population.java +++ b/src/jcgp/population/Population.java @@ -8,15 +8,15 @@ public class Population { private Chromosome[] chromosomes; private int fittest; - public Population(Resources parameters) { - chromosomes = new Chromosome[((int) parameters.get("popSize"))]; + public Population(Resources resources) { + chromosomes = new Chromosome[(resources.getInt("popSize"))]; for (int c = 0; c < chromosomes.length; c++) { - chromosomes[c] = new Chromosome(parameters); + chromosomes[c] = new Chromosome(resources); } } - public Population(Chromosome parent, Resources parameters) { - chromosomes = new Chromosome[((int) parameters.get("popSize"))]; + public Population(Chromosome parent, Resources resources) { + chromosomes = new Chromosome[(resources.getInt("popSize"))]; // make a clone for safety this.chromosomes[0] = new Chromosome(parent); // generate the rest of the individuals diff --git a/src/jcgp/tests/ChromosomeTests.java b/src/jcgp/tests/ChromosomeTests.java index f4ed79c..eb4b5d1 100644 --- a/src/jcgp/tests/ChromosomeTests.java +++ b/src/jcgp/tests/ChromosomeTests.java @@ -62,7 +62,7 @@ public class ChromosomeTests { // compare all elements, one by one // check outputs - for (int o = 0; o < (int) resources.get("outputs"); o++) { + for (int o = 0; o < resources.getInt("outputs"); o++) { // check that no cross-references exist between chromosomes assertTrue("Cloned chromosome contains a reference to a member of the original chromosome.", clone.getOutput(o) != chromosome.getOutput(o) && @@ -80,8 +80,8 @@ public class ChromosomeTests { } } // check nodes, rows first - for (int row = 0; row < (int) resources.get("rows"); row++) { - for (int column = 0; column < (int) resources.get("columns"); column++) { + for (int row = 0; row < resources.getInt("rows"); row++) { + for (int column = 0; column < resources.getInt("columns"); column++) { // check that nodes are not pointers to the same instance assertTrue("Both chromosomes contain a reference to the same node.", clone.getNode(row, column) != chromosome.getNode(row, column)); // check that both nodes reference their own position in the grid correctly @@ -91,7 +91,7 @@ public class ChromosomeTests { assertTrue("Equivalent nodes have different functions.", clone.getNode(row, column).getFunction() == chromosome.getNode(row, column).getFunction()); // compare each connection - for (int connection = 0; connection < (int) resources.get("arity"); connection++) { + for (int connection = 0; connection < resources.getInt("arity"); connection++) { // first look at whether they are actually the same instance assertTrue("Nodes are connected to the same connection instance.", clone.getNode(row, column).getConnection(connection) != chromosome.getNode(row, column).getConnection(connection)); @@ -130,12 +130,12 @@ public class ChromosomeTests { clone.setInputs((Object[]) testInputs); // check that both chromosomes have the same outputs - for (int i = 0; i < (int) resources.get("outputs"); i++) { + for (int i = 0; i < resources.getInt("outputs"); i++) { assertTrue("Incorrect output returned", ((Integer) chromosome.getOutput(i).calculate()) == ((Integer) clone.getOutput(i).calculate())); } // mutate an output in clone, check that the same node in chromosome produces a different output - clone.getOutput(1).setConnection(resources.getRandomInt((int) resources.get("arity")), clone.getInput(2)); + clone.getOutput(1).setConnection(resources.getRandomInt(resources.getInt("arity")), clone.getInput(2)); assertTrue("Mutation affected nodes in both chromosomes.", clone.getOutput(1).calculate() != chromosome.getOutput(1).calculate()); @@ -164,7 +164,7 @@ public class ChromosomeTests { // get random connections with the last column as reference, check that they're all within range int connectionNodes = 0, connectionOutOfRange = 0, connectionInputs = 0, connectionPicks = 100000; - int chosenColumn = (int) resources.get("columns") - 1; + int chosenColumn = resources.getInt("columns") - 1; for (int i = 0; i < connectionPicks; i++) { Connection c = chromosome.getRandomConnection(chosenColumn); if (c instanceof Node) { @@ -180,10 +180,10 @@ public class ChromosomeTests { } } - System.out.println("Out of " + connectionPicks + " connections picked from " + ((chosenColumn >= (int) resources.get("levelsBack")) ? (int) resources.get("levelsBack") : chosenColumn) * (int) resources.get("rows") + - " allowed nodes and " + (int) resources.get("inputs") + " inputs, " + connectionNodes + " were nodes and " + connectionInputs + " were inputs."); + System.out.println("Out of " + connectionPicks + " connections picked from " + ((chosenColumn >= resources.getInt("levelsBack")) ? resources.getInt("levelsBack") : chosenColumn) * resources.getInt("rows") + + " allowed nodes and " + resources.getInt("inputs") + " inputs, " + connectionNodes + " were nodes and " + connectionInputs + " were inputs."); - System.out.println("Node/input ratio: " + ((Integer) (((chosenColumn >= (int) resources.get("levelsBack")) ? (int) resources.get("levelsBack") : chosenColumn) * (Integer) resources.get("rows"))).doubleValue() / ((Integer) resources.get("inputs")).doubleValue() + + System.out.println("Node/input ratio: " + (chosenColumn >= resources.getInt("levelsBack") ? resources.getInt("levelsBack") : chosenColumn) * resources.getDouble("rows") / resources.getDouble("inputs") + ", picked ratio: " + (double) connectionNodes / (double) connectionInputs); System.out.println(connectionOutOfRange + " nodes that disrespected levels back were picked."); @@ -207,10 +207,10 @@ public class ChromosomeTests { fail("Return is neither Node nor Output."); } } - System.out.println("Out of " + mutablePicks + " mutable elements picked from " + (int) resources.get("nodes") + - " nodes and " + (int) resources.get("outputs") + " outputs, " + mutableNodes + " were nodes and " + + System.out.println("Out of " + mutablePicks + " mutable elements picked from " + resources.getInt("nodes") + + " nodes and " + resources.getInt("outputs") + " outputs, " + mutableNodes + " were nodes and " + mutableOutputs + " were outputs."); - System.out.println("Node/output ratio: " + ((Integer) resources.get("nodes")).doubleValue() / ((Integer) resources.get("outputs")).doubleValue() + + System.out.println("Node/output ratio: " + resources.getDouble("nodes") / resources.getDouble("outputs") + ", picked ratio: " + (double) mutableNodes / (double) mutableOutputs + "\n"); } @@ -234,12 +234,12 @@ public class ChromosomeTests { @Test public void setInputTest() { // set input values, check that acquired values are correct - Integer[] testInputs = new Integer[(int) resources.get("inputs")]; - for (int i = 0; i < (int) resources.get("inputs"); i++) { + Integer[] testInputs = new Integer[resources.getInt("inputs")]; + for (int i = 0; i < resources.getInt("inputs"); i++) { testInputs[i] = i * 2 - 3; } chromosome.setInputs((Object[]) testInputs); - for (int i = 0; i < (int) resources.get("inputs"); i++) { + for (int i = 0; i < resources.getInt("inputs"); i++) { assertTrue("Incorrect input returned.", ((Integer) chromosome.getInput(i).getValue()) == i * 2 - 3); } } @@ -250,8 +250,8 @@ public class ChromosomeTests { @Test public void getNodeTest() { // get all nodes one by one, check that they are all correct - for (int r = 0; r < (int) resources.get("rows"); r++) { - for (int c = 0; c < (int) resources.get("columns"); c++) { + for (int r = 0; r < resources.getInt("rows"); r++) { + for (int c = 0; c < resources.getInt("columns"); c++) { assertTrue("Incorrect node returned.", chromosome.getNode(r, c).getColumn() == c && chromosome.getNode(r, c).getRow() == r); } diff --git a/src/jcgp/tests/NodeTests.java b/src/jcgp/tests/NodeTests.java index 7ce5701..d8aa742 100644 --- a/src/jcgp/tests/NodeTests.java +++ b/src/jcgp/tests/NodeTests.java @@ -46,7 +46,7 @@ public class NodeTests { @Before public void setUp() throws Exception { - node = new Node(chromosome, 0, 0, (int) resources.get("arity")); + 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(), new Connection[]{new Connection() { @@ -186,7 +186,7 @@ public class NodeTests { return null; } }; - node.setConnection(resources.getRandomInt((int) resources.get("arity")), conn2); + node.setConnection(resources.getRandomInt(resources.getInt("arity")), conn2); assertTrue("Connection was not found in node.", node.getConnection(0) == conn2 || node.getConnection(1) == conn2); diff --git a/src/jcgp/tests/PopulationTests.java b/src/jcgp/tests/PopulationTests.java index ca737d6..a11becf 100644 --- a/src/jcgp/tests/PopulationTests.java +++ b/src/jcgp/tests/PopulationTests.java @@ -70,7 +70,7 @@ public class PopulationTests { chromosomes++; } - assertTrue("Incorrect number of chromosomes generated.", chromosomes == (int) resources.get("popSize")); + assertTrue("Incorrect number of chromosomes generated.", chromosomes == resources.getInt("popSize")); } @Test |