From a757deacded0d7357a9f68462d3f2051e16004ee Mon Sep 17 00:00:00 2001 From: Eduardo Pedroni Date: Mon, 31 Mar 2014 20:32:59 +0100 Subject: Need to do a few tests on windows --- src/jcgp/GUI.java | 53 ++- src/jcgp/JCGP.java | 4 +- src/jcgp/exceptions/ManagedModuleException.java | 10 + src/jcgp/gui/ChromosomePane.java | 122 +++++++ src/jcgp/gui/GUIConsole.java | 106 ------ src/jcgp/gui/Messenger.java | 7 + src/jcgp/gui/console/GUIConsole.java | 94 +++++ src/jcgp/gui/settings/SettingsPane.java | 400 +++++++++++++++++++++ .../settings/parameters/GUIBooleanParameter.java | 40 +++ .../settings/parameters/GUIDoubleParameter.java | 48 +++ .../settings/parameters/GUIIntegerParameter.java | 49 +++ src/jcgp/gui/settings/parameters/GUIParameter.java | 30 ++ src/jcgp/modules/ModuleStatus.java | 16 + src/jcgp/modules/ea/MuPlusLambda.java | 80 +++++ src/jcgp/modules/ea/TournamentSelection.java | 54 +++ src/jcgp/parameters/Parameter.java | 4 + src/jcgp/tests/InputTests.java | 2 +- 17 files changed, 981 insertions(+), 138 deletions(-) create mode 100644 src/jcgp/exceptions/ManagedModuleException.java create mode 100644 src/jcgp/gui/ChromosomePane.java delete mode 100644 src/jcgp/gui/GUIConsole.java create mode 100644 src/jcgp/gui/Messenger.java create mode 100644 src/jcgp/gui/console/GUIConsole.java create mode 100644 src/jcgp/gui/settings/SettingsPane.java create mode 100644 src/jcgp/gui/settings/parameters/GUIBooleanParameter.java create mode 100644 src/jcgp/gui/settings/parameters/GUIDoubleParameter.java create mode 100644 src/jcgp/gui/settings/parameters/GUIIntegerParameter.java create mode 100644 src/jcgp/gui/settings/parameters/GUIParameter.java create mode 100644 src/jcgp/modules/ModuleStatus.java create mode 100644 src/jcgp/modules/ea/MuPlusLambda.java create mode 100644 src/jcgp/modules/ea/TournamentSelection.java diff --git a/src/jcgp/GUI.java b/src/jcgp/GUI.java index 98545db..d81e760 100644 --- a/src/jcgp/GUI.java +++ b/src/jcgp/GUI.java @@ -1,6 +1,9 @@ package jcgp; +import java.util.concurrent.ExecutionException; + import javafx.application.Application; +import javafx.application.Platform; import javafx.concurrent.Service; import javafx.concurrent.Task; import javafx.scene.Scene; @@ -11,7 +14,7 @@ import javafx.scene.layout.BorderPane; import javafx.stage.Stage; import jcgp.JCGP.Resources; import jcgp.gui.ChromosomePane; -import jcgp.gui.GUIConsole; +import jcgp.gui.console.GUIConsole; import jcgp.gui.settings.SettingsPane; public class GUI extends Application { @@ -52,7 +55,7 @@ public class GUI extends Application { private GUIConsole console = new GUIConsole(); private SettingsPane settings; - private Service cgpService; + private Service cgpService; private static boolean evolving = false; @@ -65,22 +68,19 @@ public class GUI extends Application { @Override public void start(Stage primaryStage) throws Exception { - - - cgpService = new Service () { - + + cgpService = new Service () { + @Override - protected Task createTask() { - Task t = new Task() { + protected Task createTask() { + + Task t = new Task() { @Override - protected Object call() throws Exception { - while (true) { - if (isCancelled()) { - return null; - } else { - cgp.nextGeneration(); - } + protected Integer call() throws Exception { + while (!isCancelled()) { + cgp.nextGeneration(); } + return null; } }; @@ -135,11 +135,11 @@ public class GUI extends Application { public void playPause() { if (!evolving) { - setEvolving(true); + evolving = true; cgpService.restart(); } else { cgpService.cancel(); - setEvolving(false); + evolving = false; } } @@ -149,28 +149,21 @@ public class GUI extends Application { @Override protected Object call() throws Exception { cgp.nextGeneration(); - setEvolving(false); + evolving = false; return null; } }); - setEvolving(true); + evolving = 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; } + + public Service getCGPService() { + return cgpService; + } } diff --git a/src/jcgp/JCGP.java b/src/jcgp/JCGP.java index 1742b6a..807739f 100644 --- a/src/jcgp/JCGP.java +++ b/src/jcgp/JCGP.java @@ -196,6 +196,7 @@ public class JCGP { public int getTestCaseCount() { return testCases.length; } + } private Resources resources = new Resources(); @@ -228,6 +229,7 @@ public class JCGP { */ private Population population; + public JCGP() { population = new Population(resources); @@ -358,5 +360,5 @@ public class JCGP { nextGeneration(); } // TODO print something? - } + } } diff --git a/src/jcgp/exceptions/ManagedModuleException.java b/src/jcgp/exceptions/ManagedModuleException.java new file mode 100644 index 0000000..a327dfb --- /dev/null +++ b/src/jcgp/exceptions/ManagedModuleException.java @@ -0,0 +1,10 @@ +package jcgp.exceptions; + +public class ManagedModuleException extends RuntimeException { + + /** + * + */ + private static final long serialVersionUID = -3450063156524494967L; + +} diff --git a/src/jcgp/gui/ChromosomePane.java b/src/jcgp/gui/ChromosomePane.java new file mode 100644 index 0000000..b4a628f --- /dev/null +++ b/src/jcgp/gui/ChromosomePane.java @@ -0,0 +1,122 @@ +package jcgp.gui; + +import java.util.ArrayList; + +import javafx.scene.control.ScrollPane; +import javafx.scene.layout.Pane; +import javafx.scene.shape.Line; +import jcgp.JCGP.Resources; +import jcgp.gui.population.GUIGene; +import jcgp.gui.population.GUIInput; +import jcgp.gui.population.GUINode; +import jcgp.gui.population.GUIOutput; +import jcgp.population.Chromosome; +import jcgp.population.Connection; +import jcgp.population.Input; +import jcgp.population.Node; + + +public class ChromosomePane extends ScrollPane { + + private GUINode[][] guiNodes; + private GUIInput[] guiInputs; + private GUIOutput[] guiOutputs; + + private Pane content; + + private ArrayList connectionLines; + + private boolean target = false; + + public ChromosomePane(Chromosome chromosome, Resources resources) { + super(); + connectionLines = new ArrayList(); + + //setMouseTransparent(true); + + content = new Pane(); + content.setId("content pane for genes"); + + // generate the GUIGenes + // inputs + guiInputs = new GUIInput[resources.getInt("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[resources.getInt("rows")][resources.getInt("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[resources.getInt("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[resources.getInt("outputs")]; + for (int i = 0; i < guiOutputs.length; i++) { + xPos = ((resources.getInt("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; + } + + public void update() { + for (int r = 0; r < guiNodes.length; r++) { + for (int c = 0; c < guiNodes[r].length; c++) { + guiNodes[r][c].updateLines(); + guiNodes[r][c].updateFunction(); + } + } + for (int i = 0; i < guiOutputs.length; i++) { + guiOutputs[i].updateLines(); + } + } +} diff --git a/src/jcgp/gui/GUIConsole.java b/src/jcgp/gui/GUIConsole.java deleted file mode 100644 index 15ef2f6..0000000 --- a/src/jcgp/gui/GUIConsole.java +++ /dev/null @@ -1,106 +0,0 @@ -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; -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); - -// System.setOut(new PrintStream(new OutputStream() { -// @Override -// public void write(final int b) throws IOException { -// textArea.appendText(String.valueOf((char) b)); -// } -// })); - - 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() { - @Override - public void handle(MouseEvent event) { - // ignore clicks outside of the draggable margin - if(isInDraggableZone(event)) { - dragging = true; - } - } - }); - setOnMouseDragged(new EventHandler() { - @Override - public void handle(MouseEvent event) { - if(dragging) { - double newHeight = getHeight() - event.getY(); - if (newHeight >= getMinHeight()) { - setPrefHeight(newHeight); - } else { - setPrefHeight(getMinHeight()); - } - } - } - }); - setOnMouseMoved(new EventHandler() { - @Override - public void handle(MouseEvent event) { - if(isInDraggableZone(event) || dragging) { - setCursor(Cursor.V_RESIZE); - } - else { - setCursor(Cursor.DEFAULT); - } - } - }); - setOnMouseReleased(new EventHandler() { - @Override - public void handle(MouseEvent event) { - dragging = false; - setCursor(Cursor.DEFAULT); - } - }); - textArea.setOnMouseEntered(new EventHandler() { - @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/Messenger.java b/src/jcgp/gui/Messenger.java new file mode 100644 index 0000000..becf47c --- /dev/null +++ b/src/jcgp/gui/Messenger.java @@ -0,0 +1,7 @@ +package jcgp.gui; + +public class Messenger { + + + +} diff --git a/src/jcgp/gui/console/GUIConsole.java b/src/jcgp/gui/console/GUIConsole.java new file mode 100644 index 0000000..0ef2be3 --- /dev/null +++ b/src/jcgp/gui/console/GUIConsole.java @@ -0,0 +1,94 @@ +package jcgp.gui.console; + +import javafx.event.EventHandler; +import javafx.scene.Cursor; +import javafx.scene.control.TextArea; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.AnchorPane; +import jcgp.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); + + 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() { + @Override + public void handle(MouseEvent event) { + // ignore clicks outside of the draggable margin + if(isInDraggableZone(event)) { + dragging = true; + } + } + }); + setOnMouseDragged(new EventHandler() { + @Override + public void handle(MouseEvent event) { + if(dragging) { + double newHeight = getHeight() - event.getY(); + if (newHeight >= getMinHeight()) { + setPrefHeight(newHeight); + } else { + setPrefHeight(getMinHeight()); + } + } + } + }); + setOnMouseMoved(new EventHandler() { + @Override + public void handle(MouseEvent event) { + if(isInDraggableZone(event) || dragging) { + setCursor(Cursor.V_RESIZE); + } + else { + setCursor(Cursor.DEFAULT); + } + } + }); + setOnMouseReleased(new EventHandler() { + @Override + public void handle(MouseEvent event) { + dragging = false; + setCursor(Cursor.DEFAULT); + } + }); + textArea.setOnMouseEntered(new EventHandler() { + @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/settings/SettingsPane.java b/src/jcgp/gui/settings/SettingsPane.java new file mode 100644 index 0000000..9edcbdb --- /dev/null +++ b/src/jcgp/gui/settings/SettingsPane.java @@ -0,0 +1,400 @@ +package jcgp.gui.settings; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; + +import javafx.beans.property.SimpleIntegerProperty; +import javafx.event.ActionEvent; +import javafx.event.EventHandler; +import javafx.geometry.Insets; +import javafx.scene.Cursor; +import javafx.scene.control.Button; +import javafx.scene.control.CheckBox; +import javafx.scene.control.ComboBox; +import javafx.scene.control.ScrollPane; +import javafx.scene.input.MouseEvent; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.VBox; +import javafx.scene.text.Font; +import javafx.scene.text.FontSmoothingType; +import javafx.scene.text.Text; +import jcgp.GUI; +import jcgp.JCGP; +import jcgp.function.FunctionSet; +import jcgp.gui.settings.parameters.*; +import jcgp.modules.ea.EvolutionaryAlgorithm; +import jcgp.modules.fitness.FitnessFunction; +import jcgp.modules.mutator.Mutator; +import jcgp.parameters.*; + +public class SettingsPane extends AnchorPane { + + private VBox mainContainer; + private VBox bpPane, eaPane, mutatorPane, ffPane, nfPane; + private ArrayList parameters = new ArrayList(); + + private boolean dragging = false; + + public SettingsPane(JCGP cgp, GUI gui) { + super(); + + setResizeListeners(); + + mainContainer = new VBox(8); + mainContainer.setPadding(new Insets(5, GUI.RESIZE_MARGIN, 0, 2)); + + setMinWidth(GUI.SETTINGS_WIDTH); + setPrefWidth(GUI.SETTINGS_WIDTH); + + initialiseBaseParameters(cgp, gui); + + initialiseEAParameters(cgp); + + initialiseMutatorParameters(cgp); + + initialiseFitnessFunctionParameters(cgp); + + initialiseNodeFunctionParameters(cgp); + + createControls(cgp, gui); + + ScrollPane scroll = new ScrollPane(); + scroll.setFitToWidth(true); + scroll.setContent(mainContainer); + scroll.setStyle("-fx-background-color: #FFFFFF"); + + AnchorPane.setTopAnchor(scroll, 0.0); + AnchorPane.setBottomAnchor(scroll, 0.0); + AnchorPane.setRightAnchor(scroll, 0.0); + AnchorPane.setLeftAnchor(scroll, GUI.RESIZE_MARGIN); + + getChildren().add(scroll); + } + + private void initialiseBaseParameters(JCGP cgp, GUI gui) { + bpPane = new VBox(2); + + Text header = new Text("Base Parameters"); + header.setFont(Font.font("Arial", 14)); + header.setUnderline(true); + + bpPane.getChildren().add(header); + + final GUIIntegerParameter generation = new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("currentGen")); + final GUIIntegerParameter run = new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("currentRun")); + + parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("rows"))); + parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("columns"))); + parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("inputs"))); + parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("outputs"))); + parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("levelsBack"))); + + parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("popSize"))); + parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("generations"))); + parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("runs"))); + + parameters.add(generation); + parameters.add(run); + + parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("seed"))); + parameters.add(new GUIIntegerParameter((IntegerParameter) cgp.getResources().getParameter("report"))); + parameters.add(new GUIBooleanParameter((BooleanParameter) cgp.getResources().getParameter("verbose"))); + + bpPane.getChildren().addAll(parameters); + + mainContainer.getChildren().add(bpPane); + + generation.getTextField().textProperty().bind(((SimpleIntegerProperty) cgp.getResources().getParameter("currentGen").valueProperty()).asString()); + } + + private void initialiseEAParameters(final JCGP cgp) { + eaPane = new VBox(2); + + Text header = new Text("Evolutionary Algorithm"); + header.setFont(Font.font("Arial", 14)); + header.setUnderline(true); + + final ComboBox eaCBox = new ComboBox(); + eaCBox.getItems().addAll(cgp.getEvolutionaryAlgorithms()); + eaCBox.getSelectionModel().select(cgp.getEvolutionaryAlgorithm()); + eaCBox.prefWidthProperty().bind(mainContainer.widthProperty()); + + final VBox eaParameters = new VBox(); + eaParameters.setSpacing(2); + if (cgp.getEvolutionaryAlgorithm().getLocalParameters() != null) { + refreshParameters(cgp.getEvolutionaryAlgorithm().getLocalParameters().entrySet().iterator(), eaParameters); + } + + eaCBox.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + cgp.setEvolutionaryAlgorithm(eaCBox.getSelectionModel().getSelectedIndex()); + if (eaCBox.getSelectionModel().getSelectedItem().getLocalParameters() != null) { + refreshParameters(eaCBox.getSelectionModel().getSelectedItem().getLocalParameters().entrySet().iterator(), eaParameters); + } + } + }); + + eaPane.getChildren().addAll(header, eaCBox, eaParameters); + mainContainer.getChildren().add(eaPane); + } + + private void initialiseMutatorParameters(final JCGP cgp) { + mutatorPane = new VBox(2); + + Text header = new Text("Mutator"); + header.setFontSmoothingType(FontSmoothingType.LCD); + header.setFont(Font.font("Arial", 14)); + header.setUnderline(true); + + final ComboBox mutatorCBox = new ComboBox(); + mutatorCBox.getItems().addAll(cgp.getMutators()); + mutatorCBox.getSelectionModel().select(cgp.getMutator()); + mutatorCBox.prefWidthProperty().bind(mainContainer.widthProperty()); + + final VBox mutatorParameters = new VBox(); + mutatorParameters.setSpacing(2); + if (cgp.getEvolutionaryAlgorithm().getLocalParameters() != null) { + refreshParameters(cgp.getMutator().getLocalParameters().entrySet().iterator(), mutatorParameters); + } + + mutatorCBox.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + cgp.setEvolutionaryAlgorithm(mutatorCBox.getSelectionModel().getSelectedIndex()); + if (mutatorCBox.getSelectionModel().getSelectedItem().getLocalParameters() != null) { + refreshParameters(mutatorCBox.getSelectionModel().getSelectedItem().getLocalParameters().entrySet().iterator(), mutatorParameters); + } + } + }); + + mutatorPane.getChildren().addAll(header, mutatorCBox, mutatorParameters); + mainContainer.getChildren().add(mutatorPane); + } + + private void initialiseFitnessFunctionParameters(final JCGP cgp) { + ffPane= new VBox(2); + + Text header = new Text("Fitness Function"); + header.setFont(Font.font("Arial", 14)); + header.setUnderline(true); + + final ComboBox ffCBox = new ComboBox(); + ffCBox.getItems().addAll(cgp.getFitnessFunctions()); + ffCBox.getSelectionModel().select(cgp.getFitnessFunction()); + ffCBox.prefWidthProperty().bind(mainContainer.widthProperty()); + + final VBox ffParameters = new VBox(); + ffParameters.setSpacing(2); + if (cgp.getFitnessFunction().getLocalParameters() != null) { + refreshParameters(cgp.getFitnessFunction().getLocalParameters().entrySet().iterator(), ffParameters); + } + + ffCBox.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + cgp.setEvolutionaryAlgorithm(ffCBox.getSelectionModel().getSelectedIndex()); + if (ffCBox.getSelectionModel().getSelectedItem().getLocalParameters() != null) { + refreshParameters(ffCBox.getSelectionModel().getSelectedItem().getLocalParameters().entrySet().iterator(), ffParameters); + } + } + }); + + ffPane.getChildren().addAll(header, ffCBox, ffParameters); + mainContainer.getChildren().add(ffPane); + + } + + private void initialiseNodeFunctionParameters(JCGP cgp) { + nfPane = new VBox(2); + + Text header = new Text("Node Functions"); + header.setFont(Font.font("Arial", 14)); + header.setUnderline(true); + + final ComboBox nfCBox = new ComboBox(); + nfCBox.getItems().addAll(cgp.getResources().getFunctionSets()); + nfCBox.getSelectionModel().select(cgp.getResources().getFunctionSet()); + nfCBox.prefWidthProperty().bind(mainContainer.widthProperty()); + + final VBox nfParameters = new VBox(); + nfParameters.setSpacing(2); + refreshFunctions(cgp.getResources().getFunctionSet(), nfParameters); + + nfCBox.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + refreshFunctions(nfCBox.getSelectionModel().getSelectedItem(), nfParameters); + } + }); + + nfPane.getChildren().addAll(header, nfCBox, nfParameters); + mainContainer.getChildren().add(nfPane); + } + + private void createControls(final JCGP cgp, final GUI gui) { + final VBox controls = new VBox(2); + controls.setFillWidth(true); + + final HBox flowButtons = new HBox(2); + final Button play = new Button("Run"); + + play.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + gui.playPause(); + if (gui.isEvolving()) { + play.setText("Pause"); + } else { + play.setText("Run"); + } + } + }); + + Button step = new Button("Step"); + + step.setOnAction(new EventHandler() { + @Override + public void handle(ActionEvent event) { + gui.step(); + } + }); + + flowButtons.getChildren().addAll(play, step); + + HBox.setHgrow(play, Priority.ALWAYS); + play.setMaxWidth(Double.MAX_VALUE); + + HBox.setHgrow(step, Priority.ALWAYS); + step.setMaxWidth(Double.MAX_VALUE); + + controls.getChildren().add(flowButtons); + + mainContainer.getChildren().add(controls); + + } + + /** + * @param cgp + * @param vb + */ + private void refreshParameters(Iterator> it, VBox vb) { + parameters.removeAll(vb.getChildren()); + vb.getChildren().clear(); + while (it.hasNext()) { + Parameter parameter = ((Map.Entry) it.next()).getValue(); + if (parameter instanceof IntegerParameter) { + GUIIntegerParameter gip = new GUIIntegerParameter((IntegerParameter) parameter); + parameters.add(gip); + vb.getChildren().add(gip); + } else if (parameter instanceof DoubleParameter) { + GUIDoubleParameter gdp = new GUIDoubleParameter((DoubleParameter) parameter); + parameters.add(gdp); + vb.getChildren().add(gdp); + } else if (parameter instanceof BooleanParameter) { + GUIBooleanParameter gbp = new GUIBooleanParameter((BooleanParameter) parameter); + parameters.add(gbp); + vb.getChildren().add(gbp); + } + } + } + + private void refreshFunctions(final FunctionSet fs, VBox vb) { + vb.getChildren().clear(); + CheckBox cb; + for (int i = 0; i < fs.getTotalFunctionCount(); i++) { + cb = new CheckBox(fs.getFunction(i).getName()); + cb.setId(String.valueOf(i)); + cb.setSelected(fs.isEnabled(fs.getFunction(i))); + final int index = i; + cb.setOnAction(new EventHandler() { + @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() { + @Override + public void handle(MouseEvent event) { + if(isInDraggableZone(event)) { + dragging = true; + } + } + }); + setOnMouseDragged(new EventHandler() { + @Override + public void handle(MouseEvent event) { + if(dragging) { + double newWidth = getWidth() - event.getX(); + if (newWidth >= getMinWidth()) { + setPrefWidth(newWidth); + } else { + setPrefWidth(getMinWidth()); + } + } + } + }); + setOnMouseMoved(new EventHandler() { + @Override + public void handle(MouseEvent event) { + if(isInDraggableZone(event) || dragging) { + setCursor(Cursor.H_RESIZE); + } + else { + setCursor(Cursor.DEFAULT); + } + } + }); + setOnMouseReleased(new EventHandler() { + @Override + public void handle(MouseEvent event) { + dragging = false; + setCursor(Cursor.DEFAULT); + } + }); + } + + private boolean isInDraggableZone(MouseEvent event) { + return event.getX() < (GUI.RESIZE_MARGIN); + } + + public void refreshValues() { + for (GUIParameter parameter : parameters) { + parameter.refreshValue(); + } + //parent.updateNodeGrids(); + } + +// public void bindParameters() { +// for (GUIParameter parameter : parameters) { +// parameter.doBindings(); +// } +// } +// +// public void unbindParameters() { +// for (GUIParameter parameter : parameters) { +// parameter.undoBindings(); +// } +// } + + public void toggleSettings(boolean value) { + bpPane.setDisable(value); + eaPane.setDisable(value); + mutatorPane.setDisable(value); + ffPane.setDisable(value); + nfPane.setDisable(value); + } +} diff --git a/src/jcgp/gui/settings/parameters/GUIBooleanParameter.java b/src/jcgp/gui/settings/parameters/GUIBooleanParameter.java new file mode 100644 index 0000000..a9f6753 --- /dev/null +++ b/src/jcgp/gui/settings/parameters/GUIBooleanParameter.java @@ -0,0 +1,40 @@ +package jcgp.gui.settings.parameters; + +import javafx.scene.control.CheckBox; +import jcgp.parameters.BooleanParameter; + +public class GUIBooleanParameter extends GUIParameter { + + public GUIBooleanParameter(BooleanParameter parameter) { + super(); + + this.parameter = parameter; + + value = new CheckBox(parameter.getName()); + ((CheckBox) value).setSelected(parameter.get()); + + value.setDisable(!parameter.isEditable()); + + getChildren().add(value); + + } + +// @Override +// public void doBindings() { +// ((CheckBox) value).selectedProperty().bind(((BooleanParameter) parameter).valueProperty()); +// } +// +// @Override +// public void undoBindings() { +// ((CheckBox) value).selectedProperty().unbind(); +// } + + @Override + public void refreshValue() { + if (!((CheckBox) value).selectedProperty().isBound()) { + ((CheckBox) value).setSelected(((BooleanParameter) parameter).get()); + } + + } + +} diff --git a/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java b/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java new file mode 100644 index 0000000..25d5b9f --- /dev/null +++ b/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java @@ -0,0 +1,48 @@ +package jcgp.gui.settings.parameters; + +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) { + super(); + + this.parameter = parameter; + + name = new Text(parameter.getName()); + value = new TextField(String.valueOf(parameter.get())); + + ((TextField) value).setAlignment(Pos.CENTER_RIGHT); + + setHgrow(value, Priority.ALWAYS); + + name.setWrappingWidth(GUI.WRAP_WIDTH); + + ((TextField) value).setEditable(parameter.isEditable()); + + getChildren().addAll(name, value); + } + +// @Override +// public void doBindings() { +// ((TextField) value).textProperty().bind(((DoubleParameter) parameter).valueProperty().asString()); +// } +// +// @Override +// public void undoBindings() { +// ((TextField) value).textProperty().unbind(); +// } + + @Override + public void refreshValue() { + if (!((TextField) value).textProperty().isBound()) { + ((TextField) value).setText(String.valueOf(((DoubleParameter) parameter).get())); + } + } + +} diff --git a/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java b/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java new file mode 100644 index 0000000..6bcfd55 --- /dev/null +++ b/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java @@ -0,0 +1,49 @@ +package jcgp.gui.settings.parameters; + +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) { + super(); + + this.parameter = parameter; + + name = new Text(parameter.getName()); + value = new TextField(String.valueOf(parameter.get())); + + ((TextField) value).setAlignment(Pos.CENTER_RIGHT); + + setHgrow(value, Priority.ALWAYS); + + name.setWrappingWidth(GUI.WRAP_WIDTH); + + ((TextField) value).setEditable(parameter.isEditable()); + + getChildren().addAll(name, value); + } + +// @Override +// public void doBindings() { +// ((TextField) value).textProperty().bind(((IntegerParameter) parameter).valueProperty().asString()); +// } +// +// @Override +// public void undoBindings() { +// ((TextField) value).textProperty().unbind(); +// } + + public TextField getTextField() { + return (TextField) value; + } + + @Override + public void refreshValue() { + ((TextField) value).setText(String.valueOf(((IntegerParameter) parameter).get())); + } +} diff --git a/src/jcgp/gui/settings/parameters/GUIParameter.java b/src/jcgp/gui/settings/parameters/GUIParameter.java new file mode 100644 index 0000000..a2f2f9c --- /dev/null +++ b/src/jcgp/gui/settings/parameters/GUIParameter.java @@ -0,0 +1,30 @@ +package jcgp.gui.settings.parameters; + +import javafx.geometry.Pos; +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; + + public GUIParameter() { + setAlignment(Pos.CENTER_LEFT); + setSpacing(5); + } + + public Parameter getParameter() { + return parameter; + } + +// public abstract void doBindings(); +// +// public abstract void undoBindings(); + + public abstract void refreshValue(); + +} diff --git a/src/jcgp/modules/ModuleStatus.java b/src/jcgp/modules/ModuleStatus.java new file mode 100644 index 0000000..02e2c01 --- /dev/null +++ b/src/jcgp/modules/ModuleStatus.java @@ -0,0 +1,16 @@ +package jcgp.modules; + +public enum ModuleStatus { + ERROR, WARNING, READY; + + private String details; + + public void setDetails(String details) { + this.details = details; + } + + public String getDetails() { + return details; + } + +} diff --git a/src/jcgp/modules/ea/MuPlusLambda.java b/src/jcgp/modules/ea/MuPlusLambda.java new file mode 100644 index 0000000..94900ca --- /dev/null +++ b/src/jcgp/modules/ea/MuPlusLambda.java @@ -0,0 +1,80 @@ +package jcgp.modules.ea; + +import java.util.HashMap; + +import jcgp.JCGP.Resources; +import jcgp.modules.ModuleStatus; +import jcgp.modules.mutator.Mutator; +import jcgp.parameters.IntegerParameter; +import jcgp.parameters.Parameter; +import jcgp.population.Chromosome; +import jcgp.population.Population; + +/** + * (μ + λ) EA. + * + * + * @author Eduardo Pedroni + * + */ +public class MuPlusLambda implements EvolutionaryAlgorithm { + + private Chromosome fittestChromosome; + + private IntegerParameter parents, offspring; + + private HashMap localParameters; + + public MuPlusLambda() { + parents = new IntegerParameter(1, "Parents"); + offspring = new IntegerParameter(4, "Offspring"); + + localParameters = new HashMap(); + + 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 < parameters.getInt("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 < parameters.getInt("popSize"); i++) { + if (i != fittest) { + population.getChromosome(i).copyConnections(fc); + mutator.mutate(population.getChromosome(i), parameters); + } + } + } + + @Override + public Chromosome getFittestChromosome() { + return fittestChromosome; + } + + @Override + public HashMap getLocalParameters() { + return localParameters; + } + + @Override + public String toString() { + return "(μ + λ)"; + } + + @Override + public ModuleStatus getStatus(Resources resources) { + return ModuleStatus.READY; + } + +} diff --git a/src/jcgp/modules/ea/TournamentSelection.java b/src/jcgp/modules/ea/TournamentSelection.java new file mode 100644 index 0000000..c2915a5 --- /dev/null +++ b/src/jcgp/modules/ea/TournamentSelection.java @@ -0,0 +1,54 @@ +package jcgp.modules.ea; + +import java.util.HashMap; + +import jcgp.JCGP.Resources; +import jcgp.modules.ModuleStatus; +import jcgp.modules.mutator.Mutator; +import jcgp.parameters.IntegerParameter; +import jcgp.parameters.Parameter; +import jcgp.population.Chromosome; +import jcgp.population.Population; + +public class TournamentSelection implements EvolutionaryAlgorithm { + + private Chromosome fittestChromosome; + + private IntegerParameter tournament; + private HashMap localParameters; + + public TournamentSelection() { + tournament = new IntegerParameter(1, "Tournament size"); + + localParameters = new HashMap(); + localParameters.put("tournament", tournament); + } + + @Override + public HashMap getLocalParameters() { + return localParameters; + } + + @Override + public void evolve(Population population, Mutator mutator, + Resources parameters) { + + // TODO implement this + + } + + @Override + public Chromosome getFittestChromosome() { + return fittestChromosome; + } + + @Override + public String toString() { + return "Tournament"; + } + + @Override + public ModuleStatus getStatus(Resources resources) { + return null; + } +} diff --git a/src/jcgp/parameters/Parameter.java b/src/jcgp/parameters/Parameter.java index 42c70e4..a5ecf9e 100644 --- a/src/jcgp/parameters/Parameter.java +++ b/src/jcgp/parameters/Parameter.java @@ -1,5 +1,7 @@ package jcgp.parameters; +import javafx.beans.property.Property; + public abstract class Parameter { protected boolean hidden = false, editable = true; @@ -23,4 +25,6 @@ public abstract class Parameter { public String getName() { return name; } + + public abstract Property valueProperty(); } diff --git a/src/jcgp/tests/InputTests.java b/src/jcgp/tests/InputTests.java index 51d58d2..012a734 100644 --- a/src/jcgp/tests/InputTests.java +++ b/src/jcgp/tests/InputTests.java @@ -11,7 +11,7 @@ import org.junit.Test; * Tests which cover the behaviour specified for an input. * * - An input contains a single set value. This value can be freely set for - * fitness evaluation purposes. TODO this value should be generically typed. + * fitness evaluation purposes. * - It must be addressable by an index set upon construction only. * * -- cgit v1.2.3