aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEduardo Pedroni <ep625@york.ac.uk>2014-03-26 21:34:37 +0000
committerEduardo Pedroni <ep625@york.ac.uk>2014-03-26 21:34:37 +0000
commit2bf2d3ac2c578de481ecfd545d58be73c5628996 (patch)
treeec47cfeedaed5bf677cab1bc9e910782369fe127 /src
parentbc4fafb9d3c60993253f7e78c10338c901de653a (diff)
Node grid has been refactored a few times, settings pane is almost complete, console is all done.
Diffstat (limited to 'src')
-rw-r--r--src/jcgp/GUI.java85
-rw-r--r--src/jcgp/JCGP.java109
-rw-r--r--src/jcgp/function/FunctionSet.java23
-rw-r--r--src/jcgp/gui/Console.java13
-rw-r--r--src/jcgp/gui/GUIConsole.java96
-rw-r--r--src/jcgp/gui/SettingsPane.java253
-rw-r--r--src/jcgp/gui/population/ChromosomePane.java21
-rw-r--r--src/jcgp/gui/population/GUIGene.java2
-rw-r--r--src/jcgp/gui/population/GUIInput.java3
-rw-r--r--src/jcgp/gui/population/GUINode.java74
-rw-r--r--src/jcgp/gui/population/GUIOutput.java42
-rw-r--r--src/jcgp/gui/settings/GUIBooleanParameter.java24
-rw-r--r--src/jcgp/gui/settings/GUIDoubleParameter.java33
-rw-r--r--src/jcgp/gui/settings/GUIIntegerParameter.java18
-rw-r--r--src/jcgp/gui/settings/GUIParameter.java5
-rw-r--r--src/jcgp/modules/Module.java5
-rw-r--r--src/jcgp/modules/ea/StandardEA.java16
-rw-r--r--src/jcgp/modules/fitness/TestCaseEvaluator.java12
-rw-r--r--src/jcgp/modules/mutator/PointMutator.java12
19 files changed, 627 insertions, 219 deletions
diff --git a/src/jcgp/GUI.java b/src/jcgp/GUI.java
index 669a4e2..a893494 100644
--- a/src/jcgp/GUI.java
+++ b/src/jcgp/GUI.java
@@ -1,43 +1,66 @@
package jcgp;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
import javafx.application.Application;
-import javafx.event.EventHandler;
-import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Tab;
import javafx.scene.control.TabPane;
import javafx.scene.control.TabPane.TabClosingPolicy;
-import javafx.scene.input.MouseDragEvent;
-import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import jcgp.JCGP.Resources;
-import jcgp.gui.Console;
+import jcgp.gui.GUIConsole;
import jcgp.gui.SettingsPane;
import jcgp.gui.population.ChromosomePane;
-import jcgp.gui.population.GUIGene;
public class GUI extends Application {
+ /* Colours */
+ /** NEUTRAL_COLOUR is the colour elements should be when no interaction is occurring
+ * (no hovering, clicking, dragging or any other form of interaction). */
public static final String NEUTRAL_COLOUR = "#FFFFFF";
public static final String HARD_HIGHLIGHT_COLOUR = "#5496FF";
- public static final String MEDIUM_HIGHLIGHT_COLOUR = "#89AAD6";
+ // 89AAD6
+ public static final String MEDIUM_HIGHLIGHT_COLOUR = "#75BAFF";
public static final String SOFT_HIGHLIGHT_COLOUR = "#C7DFFF";
- public static final String GOOD_SELECTION_COLOUR = "#BDFFC2";
- public static final String NEUTRAL_SELECTION_COLOUR = "#FBFFB8";
- public static final String BAD_SELECTION_COLOUR = "#FF9C9C";
+ // BDFFC2
+ public static final String GOOD_SELECTION_COLOUR = "#38C25B";
+ // FBFFB8
+ public static final String NEUTRAL_SELECTION_COLOUR = "#EDEB72";
+ // FF9C9C
+ public static final String BAD_SELECTION_COLOUR = "#F53D3D";
+
+ /* Sizes and distances */
+
+ public static final double RESIZE_MARGIN = 5.0;
+
+ public static final double SETTINGS_WIDTH = 190;
+ public static final double CONSOLE_HEIGHT = 100;
+
+ public static final double WRAP_WIDTH = 90;
+
private static JCGP cgp;
public static Resources resources;
-
+ private BorderPane leftPane;
private BorderPane window;
private ChromosomePane[] chromosomes;
private TabPane mainPane;
- private static Console console;
+ private static 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));
+ }
+ });
public static void main(String[] args) {
@@ -45,7 +68,6 @@ public class GUI extends Application {
resources = cgp.getResources();
launch();
-
}
@Override
@@ -70,41 +92,24 @@ public class GUI extends Application {
settings = new SettingsPane(cgp);
- mainPane.setPrefHeight(500);
+ //mainPane.setPrefHeight(500);
+
+ leftPane = new BorderPane();
+ leftPane.setCenter(mainPane);
+ leftPane.setBottom(console);
window = new BorderPane();
- window.setCenter(mainPane);
- window.setRight(settings);
- primaryStage.addEventFilter(MouseDragEvent.MOUSE_DRAG_RELEASED, new EventHandler<MouseDragEvent>() {
- @Override
- public void handle(MouseDragEvent event) {
- // preemptively determine whether this event will reach a GUIGene
- // sodding Controls...
- if (event.getTarget() instanceof Node) {
- Node source = ((Node) event.getTarget());
- while (source != null) {
- if (source instanceof GUIGene) {
- return;
- }
- source = source.getParent();
- }
- }
- event.consume();
- ((GUIGene) event.getGestureSource()).resetState();
- ((GUIGene) event.getGestureSource()).updateLines();
+ window.setCenter(leftPane);
+ window.setRight(settings);
- }
- });
+ //primaryStage.setMinHeight(600);
+ //primaryStage.setMinWidth(800);
-
- primaryStage.setMinHeight(600);
- primaryStage.setMinWidth(800);
+ primaryStage.setTitle("JCGP");
primaryStage.setScene(new Scene(window));
primaryStage.show();
-
-
}
}
diff --git a/src/jcgp/JCGP.java b/src/jcgp/JCGP.java
index 21161fa..dc121c9 100644
--- a/src/jcgp/JCGP.java
+++ b/src/jcgp/JCGP.java
@@ -5,7 +5,6 @@ import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
-import java.util.Set;
import javafx.beans.property.Property;
import jcgp.function.Arithmetic;
@@ -34,12 +33,12 @@ public class JCGP {
*
*/
public static class Resources {
- private HashMap<String, Parameter> moduleParameters = new HashMap<String, Parameter>();
- private HashMap<String, Parameter> coreParameters = new HashMap<String, Parameter>();
- private HashMap<String, Parameter> allParameters = new HashMap<String, Parameter>();
+ private HashMap<String, Parameter> parameters = new HashMap<String, Parameter>();
private Random numberGenerator;
+ private TestCase[] testCases;
+
// function sets
private FunctionSet[] functionSets = new FunctionSet[] {
new Arithmetic(),
@@ -47,86 +46,91 @@ public class JCGP {
new BooleanLogic() };
private FunctionSet functionSet = functionSets[0];
- private TestCase[] testCases;
-
public Resources() {
createCoreParameters();
numberGenerator = new Random((int) get("seed"));
- functionSet = functionSets[0];
set("arity", functionSet.getMaxArity());
}
public Object get(String key) {
- return allParameters.get(key).getValue();
+ return parameters.get(key).getValue();
+ }
+
+ public int getInt(String key) {
+ return (int) parameters.get(key).getValue();
+ }
+
+ public double getDouble(String key) {
+ return (double) parameters.get(key).getValue();
+ }
+
+ public boolean getBoolean(String key) {
+ return (boolean) parameters.get(key).getValue();
}
public void set(String key, Object value) {
- allParameters.get(key).setValue(value);
+ parameters.get(key).setValue(value);
}
public Property<?> getProperty(String key) {
- return allParameters.get(key).valueProperty();
+ return parameters.get(key).valueProperty();
+ }
+
+ public Parameter getParameter(String key) {
+ return parameters.get(key);
}
public void setManagedParameter(String key, boolean value) {
- allParameters.get(key).setManaged(value);
+ parameters.get(key).setManaged(value);
}
public void setHiddenParameter(String key, boolean value) {
- allParameters.get(key).setHidden(value);
+ parameters.get(key).setHidden(value);
}
public boolean contains(String key) {
- return allParameters.containsKey(key);
+ return parameters.containsKey(key);
}
private void createCoreParameters() {
- coreParameters.put("rows", new IntegerParameter(9, "Rows"));
- coreParameters.put("columns", new IntegerParameter(10, "Columns"));
- coreParameters.put("inputs", new IntegerParameter(3, "Inputs"));
- coreParameters.put("outputs", new IntegerParameter(3, "Outputs"));
- coreParameters.put("popSize", new IntegerParameter(5, "Population"));
- coreParameters.put("levelsBack", new IntegerParameter(2, "Levels back"));
+ parameters.put("rows", new IntegerParameter(8, "Rows"));
+ parameters.put("columns", new IntegerParameter(9, "Columns"));
+ parameters.put("inputs", new IntegerParameter(3, "Inputs"));
+ parameters.put("outputs", new IntegerParameter(3, "Outputs"));
+ parameters.put("popSize", new IntegerParameter(5, "Population"));
+ parameters.put("levelsBack", new IntegerParameter(2, "Levels back"));
- coreParameters.put("nodes", new IntegerParameter(90, "Nodes", true, true));
+ parameters.put("nodes", new IntegerParameter(72, "Nodes", true, true));
- coreParameters.put("generations", new IntegerParameter(1000000, "Generations"));
- coreParameters.put("currentGen", new IntegerParameter(0, "Generation"));
- coreParameters.put("runs", new IntegerParameter(5, "Runs"));
+ parameters.put("generations", new IntegerParameter(1000000, "Generations"));
+ parameters.put("currentGen", new IntegerParameter(0, "Generation", true, false));
+ parameters.put("runs", new IntegerParameter(5, "Runs"));
- coreParameters.put("arity", new IntegerParameter(0, "Max arity", true, true));
+ parameters.put("arity", new IntegerParameter(0, "Max arity", true, true));
- coreParameters.put("seed", new IntegerParameter(123, "Random seed", true, true));
+ parameters.put("seed", new IntegerParameter(123, "Seed"));
- coreParameters.put("debug", new BooleanParameter(false, "Debug"));
-
- allParameters.putAll(coreParameters);
+ parameters.put("debug", new BooleanParameter(false, "Debug"));
+ 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 = coreParameters.entrySet().iterator();
+ Iterator<Entry<String, Parameter>> it = parameters.entrySet().iterator();
while (it.hasNext()) {
((Parameter) ((Map.Entry<String, Parameter>) it.next()).getValue()).reset();
}
-
- allParameters.clear();
- allParameters.putAll(coreParameters);
- addModuleParameters(ea, mu, ff);
}
- private void addModuleParameters(EvolutionaryAlgorithm ea, Mutator mu, FitnessFunction ff) {
- moduleParameters.clear();
- moduleParameters.putAll(ea.activate(this));
- moduleParameters.putAll(mu.activate(this));
- moduleParameters.putAll(ff.activate(this));
-
- allParameters.putAll(moduleParameters);
- }
-
+ /**
+ *
+ *
+ * @return the iterator for the set of base parameters
+ */
public Iterator<Entry<String, Parameter>> iterator() {
- return allParameters.entrySet().iterator();
+ return parameters.entrySet().iterator();
}
/*
@@ -145,10 +149,10 @@ public class JCGP {
}
/*
- * Function set functions
+ * FunctionSet functions
*/
public Function getRandomFunction() {
- return functionSet.getFunction(numberGenerator.nextInt(functionSet.getFunctionCount()));
+ return functionSet.getFunction(numberGenerator.nextInt(functionSet.getAllowedFunctionCount()));
}
public Function getFunction(int index) {
@@ -159,6 +163,20 @@ public class JCGP {
functionSet = functionSets[index];
}
+ /**
+ * @return the functionSets
+ */
+ public FunctionSet[] getFunctionSets() {
+ return functionSets;
+ }
+
+ /**
+ * @return the functionSet
+ */
+ public FunctionSet getFunctionSet() {
+ return functionSet;
+ }
+
/*
* Test cases
*/
@@ -204,7 +222,6 @@ public class JCGP {
public JCGP() {
- resources.addModuleParameters(evolutionaryAlgorithm, mutator, fitnessFunction);
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}));
diff --git a/src/jcgp/function/FunctionSet.java b/src/jcgp/function/FunctionSet.java
index 07b4ea4..49ff7e7 100644
--- a/src/jcgp/function/FunctionSet.java
+++ b/src/jcgp/function/FunctionSet.java
@@ -3,6 +3,7 @@ package jcgp.function;
import java.util.ArrayList;
import java.util.Iterator;
+
/**
*
* @author Eduardo Pedroni
@@ -14,14 +15,14 @@ public abstract class FunctionSet {
protected int maxArity;
protected String name;
-// public int getTotalFunctionCount() {
-// return functionList.length;
-// }
-
- public int getFunctionCount() {
+ public int getAllowedFunctionCount() {
return allowedFunctions.size();
}
+ public int getTotalFunctionCount() {
+ return functionList.length;
+ }
+
public Function getFunction(int index) {
return allowedFunctions.get(index);
}
@@ -35,14 +36,15 @@ public abstract class FunctionSet {
}
public void disableFunction(int index) {
- for (Iterator<Function> iterator = allowedFunctions.iterator(); iterator.hasNext();) {
- if (index < functionList.length) {
+ if (index < functionList.length) {
+ for (Iterator<Function> iterator = allowedFunctions.iterator(); iterator.hasNext();) {
Function function = (Function) iterator.next();
if (function == functionList[index]) {
iterator.remove();
}
}
-
+ } else {
+ throw new IndexOutOfBoundsException("Function " + index + " does not exist, the set only has " + functionList.length + " functions.");
}
}
@@ -51,4 +53,9 @@ public abstract class FunctionSet {
allowedFunctions.add(functionList[index]);
}
}
+
+ @Override
+ public String toString() {
+ return name;
+ }
} \ No newline at end of file
diff --git a/src/jcgp/gui/Console.java b/src/jcgp/gui/Console.java
deleted file mode 100644
index 9008531..0000000
--- a/src/jcgp/gui/Console.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package jcgp.gui;
-
-import javafx.scene.control.TextArea;
-
-public class Console extends TextArea {
-
- public Console() {
- super();
- setDisable(true);
- setPrefHeight(100);
- }
-
-}
diff --git a/src/jcgp/gui/GUIConsole.java b/src/jcgp/gui/GUIConsole.java
new file mode 100644
index 0000000..a14a23b
--- /dev/null
+++ b/src/jcgp/gui/GUIConsole.java
@@ -0,0 +1,96 @@
+package jcgp.gui;
+
+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.GUI;
+
+public class GUIConsole extends AnchorPane {
+
+ private boolean dragging;
+ private TextArea textArea = new TextArea("Welcome to JCGP!\n");
+
+ public GUIConsole() {
+ super();
+ textArea.setEditable(false);
+ textArea.setWrapText(true);
+
+ //setStyle("-fx-border-width: 5 0 0 0; -fx-border-color: #D1D1D1");
+
+ setResizeListeners();
+
+ AnchorPane.setTopAnchor(textArea, GUI.RESIZE_MARGIN);
+ AnchorPane.setBottomAnchor(textArea, 0.0);
+ AnchorPane.setRightAnchor(textArea, 0.0);
+ AnchorPane.setLeftAnchor(textArea, 0.0);
+
+ setMinHeight(GUI.CONSOLE_HEIGHT);
+ setPrefHeight(GUI.CONSOLE_HEIGHT);
+
+ getChildren().add(textArea);
+
+ }
+
+ /**
+ *
+ */
+ 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);
+ }
+
+ public TextArea getTextArea() {
+ return textArea;
+ }
+
+}
diff --git a/src/jcgp/gui/SettingsPane.java b/src/jcgp/gui/SettingsPane.java
index f7e7767..594147f 100644
--- a/src/jcgp/gui/SettingsPane.java
+++ b/src/jcgp/gui/SettingsPane.java
@@ -1,37 +1,266 @@
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 VBox {
+public class SettingsPane extends AnchorPane {
+ private VBox mainContainer, eas, mutators, ffs;
+ private boolean dragging = false;
+
public SettingsPane(JCGP cgp) {
super();
- setPrefSize(180, 500);
+ setResizeListeners();
- Text parameters = new Text("Parameters");
- getChildren().add(parameters);
+ //setStyle("-fx-border-width: 0 0 0 5; -fx-border-color: #D1D1D1");
- Iterator<Entry<String, Parameter>> it = cgp.getResources().iterator();
- while (it.hasNext()) {
- Parameter p = (Parameter) ((Map.Entry<String, Parameter>) it.next()).getValue();
- if (p instanceof IntegerParameter) {
- GUIIntegerParameter gip = new GUIIntegerParameter((IntegerParameter) p);
- getChildren().add(gip);
- }
- }
+ 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
index 0c7b3d2..7fa8a54 100644
--- a/src/jcgp/gui/population/ChromosomePane.java
+++ b/src/jcgp/gui/population/ChromosomePane.java
@@ -28,6 +28,8 @@ public class ChromosomePane extends ScrollPane {
super();
connectionLines = new ArrayList<Line>();
+ //setMouseTransparent(true);
+
content = new Pane();
content.setId("content pane for genes");
@@ -82,19 +84,6 @@ public class ChromosomePane extends ScrollPane {
setContent(content);
}
-
-// public GUINode getGuiNode(int row, int column) {
-// return guiNodes[row][column];
-// }
-//
-// public GUIInput getGuiInput(int index) {
-// return guiInputs[index];
-// }
-//
-// public GUIOutput getGuiOutput(int index) {
-// return guiOutputs[index];
-// }
-
public GUIGene getGuiGene(Connection gene) {
if (gene instanceof Input) {
return guiInputs[((Input) gene).getIndex()];
@@ -107,11 +96,6 @@ public class ChromosomePane extends ScrollPane {
}
- public Pane getContentPane() {
- return content;
- }
-
-
public boolean isTarget() {
return target;
}
@@ -119,5 +103,4 @@ public class ChromosomePane extends ScrollPane {
public void setTarget(boolean newValue) {
target = newValue;
}
-
}
diff --git a/src/jcgp/gui/population/GUIGene.java b/src/jcgp/gui/population/GUIGene.java
index 1be662e..3addca7 100644
--- a/src/jcgp/gui/population/GUIGene.java
+++ b/src/jcgp/gui/population/GUIGene.java
@@ -27,7 +27,7 @@ public abstract class GUIGene extends Group {
public static final double THETA = Math.PI / 1.4;
public static final double SOCKET_RADIUS = Math.sqrt(NODE_RADIUS) / 1.8;
- public static final double NODE_TEXT = 0;
+ public static final double NODE_TEXT = NODE_RADIUS / 2.5;
protected Text text;
protected Circle mainCircle;
diff --git a/src/jcgp/gui/population/GUIInput.java b/src/jcgp/gui/population/GUIInput.java
index ac1a775..84e8a2a 100644
--- a/src/jcgp/gui/population/GUIInput.java
+++ b/src/jcgp/gui/population/GUIInput.java
@@ -18,7 +18,6 @@ import jcgp.population.Output;
public class GUIInput extends GUIGene {
- private Circle outputSocket;
private Input input;
public GUIInput(ChromosomePane parentRef, final Input input) {
@@ -40,7 +39,7 @@ public class GUIInput extends GUIGene {
text.setX(-NODE_RADIUS);
text.setVisible(true);
- outputSocket = new Circle(NODE_RADIUS, 0, SOCKET_RADIUS, Paint.valueOf("white"));
+ Circle outputSocket = new Circle(NODE_RADIUS, 0, SOCKET_RADIUS, Paint.valueOf("white"));
outputSocket.setId(String.valueOf(0));
outputSocket.setStroke(Paint.valueOf("black"));
diff --git a/src/jcgp/gui/population/GUINode.java b/src/jcgp/gui/population/GUINode.java
index dd20006..eeacb9e 100644
--- a/src/jcgp/gui/population/GUINode.java
+++ b/src/jcgp/gui/population/GUINode.java
@@ -14,23 +14,14 @@ import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import jcgp.GUI;
-import jcgp.function.Function;
import jcgp.population.Connection;
import jcgp.population.Input;
import jcgp.population.Node;
-import jcgp.population.Output;
public class GUINode extends GUIGene {
- private Circle[] sockets;
- private Circle output;
-
private Line[] lines;
-
- private Label connectionNumber;
-
private Node node;
-
private int connectionIndex = 0;
public GUINode(ChromosomePane parentRef, final Node node, Line[] connectionLines) {
@@ -39,7 +30,7 @@ public class GUINode extends GUIGene {
this.parent = parentRef;
this.node = node;
this.lines = connectionLines;
-
+
// move the GUIGene to the right position
relocate(((node.getColumn() + 1) * (2 * NODE_RADIUS + SPACING)) + NODE_RADIUS,
(node.getRow() * (2 * NODE_RADIUS + SPACING)) + NODE_RADIUS);
@@ -47,32 +38,25 @@ public class GUINode extends GUIGene {
// set the line ends correctly
updateLines();
- connectionNumber = new Label();
+ final Label connectionNumber = new Label();
connectionNumber.setStyle("-fx-background-color:rgb(255, 255, 255); -fx-border-color:rgba(0, 0, 0, 0.5); ");
connectionNumber.setVisible(false);
- output = new Circle(NODE_RADIUS, 0, SOCKET_RADIUS, Paint.valueOf("white"));
+ 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());
- this.node.functionProperty().addListener(new ChangeListener<Function>() {
- @Override
- public void changed(ObservableValue<? extends Function> observable,
- Function oldValue, Function newValue) {
- text.setText(newValue.getName());
- }
- });
- text.setFont(Font.font("Arial", 12));
+ 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);
- sockets = new Circle[(int) GUI.resources.get("arity")];
+ Circle[] sockets = new Circle[(int) GUI.resources.get("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);
@@ -137,11 +121,15 @@ public class GUINode extends GUIGene {
s.addEventFilter(MouseDragEvent.MOUSE_RELEASED, new EventHandler<MouseEvent>() {
@Override
- public void handle(MouseEvent event) {
- if (event.isDragDetect()) {
+ 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) {
+ // no connection has been made, fallback
+ resetState();
+ updateLines();
}
}
});
@@ -157,19 +145,13 @@ public class GUINode extends GUIGene {
// this happens even if we are the source of the drag
if (isAllowed((GUIGene) event.getGestureSource(), (GUIGene) event.getSource())) {
((GUIGene) event.getGestureSource()).setConnectionLine((GUIGene) event.getSource());
- if (event.getGestureSource() instanceof GUINode) {
- Connection source = ((GUINode) event.getGestureSource()).getChangingConnection();
- if (node == source) {
- stateProperty.set(GUIGeneState.NO_CHANGE_TARGET);
- return;
- }
- } else if (event.getGestureSource() instanceof GUIOutput) {
- Output source = ((GUIOutput) event.getGestureSource()).getGene();
- if (((GUIGene) event.getSource()).getGene() == source.getSource()) {
- ((GUIGene) event.getSource()).setState(GUIGeneState.NO_CHANGE_TARGET);
- }
+
+ Connection source = ((GUIGene) event.getGestureSource()).getChangingConnection();
+ if (node == source) {
+ stateProperty.set(GUIGeneState.NO_CHANGE_TARGET);
+ } else {
+ stateProperty.set(GUIGeneState.TARGET);
}
- stateProperty.set(GUIGeneState.TARGET);
} else {
stateProperty.set(GUIGeneState.FORBIDDEN_TARGET);
}
@@ -289,7 +271,7 @@ public class GUINode extends GUIGene {
case HOVER:
mainCircle.setFill(Paint.valueOf(GUI.MEDIUM_HIGHLIGHT_COLOUR));
showLines(true);
- if ((oldValue != GUIGeneState.LOCKED_HOVER || oldValue != GUIGeneState.SOURCE) && locked <= 0) {
+ if (locked <= 0) {
setConnections(GUIGeneState.INDIRECT_HOVER);
} else {
setConnections(GUIGeneState.HOVER);
@@ -326,16 +308,16 @@ public class GUINode extends GUIGene {
}
});
- 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);
- }
- });
- }
+// 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);
+// }
+// });
+// }
}
diff --git a/src/jcgp/gui/population/GUIOutput.java b/src/jcgp/gui/population/GUIOutput.java
index 87d420e..57042eb 100644
--- a/src/jcgp/gui/population/GUIOutput.java
+++ b/src/jcgp/gui/population/GUIOutput.java
@@ -21,10 +21,6 @@ import jcgp.population.Output;
public class GUIOutput extends GUIGene {
- private Circle socket;
-
- private Label connectionLabel;
-
private Line sourceLine;
private Output output;
@@ -52,11 +48,11 @@ public class GUIOutput extends GUIGene {
text.setX(-NODE_RADIUS);
text.setVisible(true);
- socket = new Circle(-NODE_RADIUS, 0, SOCKET_RADIUS, Paint.valueOf("white"));
+ Circle socket = new Circle(-NODE_RADIUS, 0, SOCKET_RADIUS, Paint.valueOf("white"));
socket.setId(String.valueOf(0));
socket.setStroke(Paint.valueOf("black"));
- connectionLabel = new Label("S");
+ final Label connectionLabel = new Label("S");
connectionLabel.setStyle("-fx-background-color:rgb(255, 255, 255); -fx-border-color:rgba(0, 0, 0, 0.5); ");
connectionLabel.relocate(socket.getCenterX() + 5, socket.getCenterY() - 10);
connectionLabel.setVisible(false);
@@ -100,19 +96,27 @@ public class GUIOutput extends GUIGene {
socket.addEventFilter(MouseDragEvent.MOUSE_DRAGGED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
- sourceLine.setEndX(event.getX() + ((Circle) event.getSource()).getParent().getLayoutX());
- sourceLine.setEndY(event.getY() + ((Circle) event.getSource()).getParent().getLayoutY());
+ if (!parent.isTarget()) {
+ sourceLine.setEndX(event.getX() + ((Circle) event.getSource()).getParent().getLayoutX());
+ sourceLine.setEndY(event.getY() + ((Circle) event.getSource()).getParent().getLayoutY());
+ }
+
}
});
socket.addEventFilter(MouseDragEvent.MOUSE_RELEASED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent event) {
- if (event.isDragDetect()) {
+ if (event.isStillSincePress()) {
// mouse was released before dragging out of the socket
updateLines();
stateProperty.set(GUIGeneState.HOVER);
+ } else if (stateProperty.get() == GUIGeneState.SOURCE) {
+ // no connection has been made, fallback
+ resetState();
+ updateLines();
}
+
}
});
@@ -185,14 +189,9 @@ 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) {
- if (isLocked()) {
-
- } else {
- stateProperty.set(GUIGeneState.NEUTRAL);
- setConnections(GUIGeneState.NEUTRAL);
- }
-
+ if (stateProperty.get() == GUIGeneState.HOVER && !isLocked()) {
+ stateProperty.set(GUIGeneState.NEUTRAL);
+ setConnections(GUIGeneState.NEUTRAL);
}
}
});
@@ -279,8 +278,13 @@ public class GUIOutput extends GUIGene {
@Override
public void resetState() {
- stateProperty.set(GUIGeneState.NEUTRAL);
- setConnections(GUIGeneState.NEUTRAL);
+ if (locked > 0) {
+ stateProperty.set(GUIGeneState.HOVER);
+ setConnections(GUIGeneState.HOVER);
+ } else {
+ stateProperty.set(GUIGeneState.NEUTRAL);
+ setConnections(GUIGeneState.NEUTRAL);
+ }
}
@Override
diff --git a/src/jcgp/gui/settings/GUIBooleanParameter.java b/src/jcgp/gui/settings/GUIBooleanParameter.java
new file mode 100644
index 0000000..7b20c3b
--- /dev/null
+++ b/src/jcgp/gui/settings/GUIBooleanParameter.java
@@ -0,0 +1,24 @@
+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
new file mode 100644
index 0000000..d61899b
--- /dev/null
+++ b/src/jcgp/gui/settings/GUIDoubleParameter.java
@@ -0,0 +1,33 @@
+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
index 2bf5480..b7a23a4 100644
--- a/src/jcgp/gui/settings/GUIIntegerParameter.java
+++ b/src/jcgp/gui/settings/GUIIntegerParameter.java
@@ -1,23 +1,31 @@
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 {
- private TextField value;
-
public GUIIntegerParameter(IntegerParameter parameter) {
+ setAlignment(Pos.CENTER_LEFT);
+ setSpacing(5);
+
this.parameter = parameter;
name = new Text(parameter.getName());
- value = new TextField(String.valueOf((int) parameter.getValue()));
+ 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
index d084060..0547758 100644
--- a/src/jcgp/gui/settings/GUIParameter.java
+++ b/src/jcgp/gui/settings/GUIParameter.java
@@ -1,13 +1,14 @@
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 4997ce7..7cf0b8d 100644
--- a/src/jcgp/modules/Module.java
+++ b/src/jcgp/modules/Module.java
@@ -7,5 +7,8 @@ import jcgp.parameters.Parameter;
public interface Module {
- public HashMap<String, Parameter> activate(Resources parameters);
+ public void activate(Resources parameters);
+
+ public HashMap<String, Parameter> getLocalParameters();
+
}
diff --git a/src/jcgp/modules/ea/StandardEA.java b/src/jcgp/modules/ea/StandardEA.java
index 7e77977..1d27004 100644
--- a/src/jcgp/modules/ea/StandardEA.java
+++ b/src/jcgp/modules/ea/StandardEA.java
@@ -61,9 +61,19 @@ public class StandardEA implements EvolutionaryAlgorithm {
}
@Override
- public HashMap<String, Parameter> activate(Resources parameters) {
- parameters.setManagedParameter("popSize", true);
-
+ 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 cd131b5..77b282c 100644
--- a/src/jcgp/modules/fitness/TestCaseEvaluator.java
+++ b/src/jcgp/modules/fitness/TestCaseEvaluator.java
@@ -28,7 +28,17 @@ public class TestCaseEvaluator implements FitnessFunction {
}
@Override
- public HashMap<String, Parameter> activate(Resources parameters) {
+ public void activate(Resources parameters) {
+ // nothing
+ }
+
+ @Override
+ public HashMap<String, Parameter> getLocalParameters() {
return new HashMap<String, Parameter>();
}
+
+ @Override
+ public String toString() {
+ return "Test case";
+ }
}
diff --git a/src/jcgp/modules/mutator/PointMutator.java b/src/jcgp/modules/mutator/PointMutator.java
index 51a4390..e9be153 100644
--- a/src/jcgp/modules/mutator/PointMutator.java
+++ b/src/jcgp/modules/mutator/PointMutator.java
@@ -42,8 +42,18 @@ public class PointMutator implements Mutator {
}
@Override
- public HashMap<String, Parameter> activate(Resources parameters) {
+ public void activate(Resources parameters) {
+ // nothing
+ }
+
+ @Override
+ public HashMap<String, Parameter> getLocalParameters() {
return localParameters;
}
+ @Override
+ public String toString() {
+ return "Point mutation";
+ }
+
}