diff options
| author | Eduardo Pedroni <ep625@york.ac.uk> | 2014-04-04 17:14:44 +0100 | 
|---|---|---|
| committer | Eduardo Pedroni <ep625@york.ac.uk> | 2014-04-04 17:14:44 +0100 | 
| commit | c7969623b44f375e30fa3f15dcd7581609276a0f (patch) | |
| tree | d1743df21e685fed93b7a12dd91a524e44fa42bd /src | |
| parent | 0dbf126fc524bc029d9f5803d849b7c8f43fe389 (diff) | |
Parameter validation refactored and fully functional.
Diffstat (limited to 'src')
| -rw-r--r-- | src/jcgp/JCGP.java | 141 | ||||
| -rw-r--r-- | src/jcgp/backend/modules/ea/MuPlusLambda.java | 37 | ||||
| -rw-r--r-- | src/jcgp/backend/modules/ea/TournamentSelection.java | 4 | ||||
| -rw-r--r-- | src/jcgp/backend/parameters/BooleanParameter.java | 9 | ||||
| -rw-r--r-- | src/jcgp/backend/parameters/DoubleParameter.java | 2 | ||||
| -rw-r--r-- | src/jcgp/backend/parameters/IntegerParameter.java | 2 | ||||
| -rw-r--r-- | src/jcgp/backend/parameters/Parameter.java | 8 | ||||
| -rw-r--r-- | src/jcgp/backend/parameters/ParameterStatus.java | 2 | ||||
| -rw-r--r-- | src/jcgp/backend/population/Chromosome.java | 1 | ||||
| -rw-r--r-- | src/jcgp/gui/GUI.java | 126 | ||||
| -rw-r--r-- | src/jcgp/gui/console/GUIConsole.java | 7 | ||||
| -rw-r--r-- | src/jcgp/gui/settings/SettingsPane.java | 109 | ||||
| -rw-r--r-- | src/jcgp/gui/settings/parameters/GUIBooleanParameter.java | 43 | ||||
| -rw-r--r-- | src/jcgp/gui/settings/parameters/GUIDoubleParameter.java | 41 | ||||
| -rw-r--r-- | src/jcgp/gui/settings/parameters/GUIIntegerParameter.java | 42 | ||||
| -rw-r--r-- | src/jcgp/gui/settings/parameters/GUIParameter.java | 18 | 
16 files changed, 390 insertions, 202 deletions
| diff --git a/src/jcgp/JCGP.java b/src/jcgp/JCGP.java index 0c75f2b..962ddec 100644 --- a/src/jcgp/JCGP.java +++ b/src/jcgp/JCGP.java @@ -117,7 +117,7 @@ public class JCGP {  		private void createBaseParameters() {  			parameters.put("rows", new IntegerParameter(8, "Rows", false, true) {  				@Override -				protected void validate(int newValue) { +				public void validate(int newValue) {  					if (newValue <= 0) {  						status = ParameterStatus.INVALID;  						status.setDetails("Chromosome must have at least 1 row."); @@ -128,7 +128,7 @@ public class JCGP {  			});  			parameters.put("columns", new IntegerParameter(9, "Columns", false, true) {  				@Override -				protected void validate(int newValue) { +				public void validate(int newValue) {  					if (newValue <= 0) {  						status = ParameterStatus.INVALID;  						status.setDetails("Chromosome must have at least 1 column."); @@ -139,7 +139,7 @@ public class JCGP {  			});  			parameters.put("inputs", new IntegerParameter(3, "Inputs", false, true) {  				@Override -				protected void validate(int newValue) { +				public void validate(int newValue) {  					if (newValue <= 0) {  						status = ParameterStatus.INVALID;  						status.setDetails("Chromosome must have at least 1 input."); @@ -150,7 +150,7 @@ public class JCGP {  			});  			parameters.put("outputs", new IntegerParameter(3, "Outputs", false, true) {  				@Override -				protected void validate(int newValue) { +				public void validate(int newValue) {  					if (newValue <= 0) {  						status = ParameterStatus.INVALID;  						status.setDetails("Chromosome must have at least 1 output."); @@ -161,7 +161,7 @@ public class JCGP {  			});  			parameters.put("popSize", new IntegerParameter(5, "Population", false, true) {  				@Override -				protected void validate(int newValue) { +				public void validate(int newValue) {  					if (newValue <= 0) {  						status = ParameterStatus.INVALID;  						status.setDetails("Population size must be at least 1."); @@ -172,7 +172,7 @@ public class JCGP {  			});  			parameters.put("levelsBack", new IntegerParameter(2, "Levels back", false, true) {  				@Override -				protected void validate(int newValue) { +				public void validate(int newValue) {  					if (newValue <= 0) {  						status = ParameterStatus.INVALID;  						status.setDetails("Levels back must be at least 1."); @@ -187,7 +187,7 @@ public class JCGP {  			IntegerParameter nodes = new IntegerParameter(1, "Nodes", true, false) {  				@Override -				protected void validate(int newValue) { +				public void validate(int newValue) {  					// blank  				}  			}; @@ -196,12 +196,12 @@ public class JCGP {  			parameters.put("generations", new IntegerParameter(1000000, "Generations") {  				@Override -				protected void validate(int newValue) { +				public void validate(int newValue) {  					if (newValue <= 0) {  						status = ParameterStatus.INVALID;  						status.setDetails("Number of generations must be greater than 0."); -					} else if (newValue <= getInt("currentGen")) { -						status = ParameterStatus.WARNING; +					} else if (newValue < getInt("currentGen")) { +						status = ParameterStatus.WARNING_RESET;  						status.setDetails("Setting generations to less than the current generation will cause the experiment to restart.");  					} else {  						status = ParameterStatus.VALID; @@ -210,16 +210,19 @@ public class JCGP {  			});  			parameters.put("currentGen", new IntegerParameter(1, "Generation", true, false) {  				@Override -				protected void validate(int newValue) { +				public void validate(int newValue) {  					// blank  				}  			});  			parameters.put("runs", new IntegerParameter(5, "Runs") {  				@Override -				protected void validate(int newValue) { -					if (newValue <= getInt("currentRun")) { -						status = ParameterStatus.WARNING; +				public void validate(int newValue) { +					if (newValue <= 0) { +						status = ParameterStatus.INVALID; +						status.setDetails("Number of runs must be greater than 0."); +					} else if (newValue < getInt("currentRun")) { +						status = ParameterStatus.WARNING_RESET;  						status.setDetails("Setting runs to less than the current run will cause the experiment to restart.");  					} else {  						status = ParameterStatus.VALID; @@ -228,27 +231,27 @@ public class JCGP {  			});  			parameters.put("currentRun", new IntegerParameter(1, "Run", true, false) {  				@Override -				protected void validate(int newValue) { +				public void validate(int newValue) {  					// blank  				}  			});  			parameters.put("arity", new IntegerParameter(0, "Max arity", true, false) {  				@Override -				protected void validate(int newValue) { +				public void validate(int newValue) {  					// blank  				}  			}); -			parameters.put("maxFitness", new IntegerParameter(6, "Max fitness", true, true) { +			parameters.put("maxFitness", new IntegerParameter(3, "Max fitness", true, true) {  				@Override -				protected void validate(int newValue) { +				public void validate(int newValue) {  					// blank  				}  			});  			IntegerParameter seed = new IntegerParameter(123, "Seed", false, true) {  				@Override -				protected void validate(int newValue) { +				public void validate(int newValue) {  					status = ParameterStatus.VALID;  				}  			}; @@ -264,7 +267,7 @@ public class JCGP {  			parameters.put("report", new IntegerParameter(1, "Report", false, false) {  				@Override -				protected void validate(int newValue) { +				public void validate(int newValue) {  					if (newValue > getInt("generations")) {  						status = ParameterStatus.WARNING;  						status.setDetails("No reports will be printed."); @@ -366,7 +369,7 @@ public class JCGP {  		}  	} -	private Resources resources = new Resources(); +	private final Resources resources = new Resources();  	/*  	 * The following arrays contain all available modules. These collections are read by the GUI @@ -382,7 +385,7 @@ public class JCGP {  	// evolutionary algorithms  	private EvolutionaryAlgorithm[] evolutionaryAlgorithms = new EvolutionaryAlgorithm[] { -			new MuPlusLambda(), +			new MuPlusLambda(resources),  			new TournamentSelection()};  	private EvolutionaryAlgorithm evolutionaryAlgorithm; @@ -396,7 +399,7 @@ public class JCGP {  	 */  	private Population population; -	private boolean solutionFound = false; +	private boolean finished = false;  	public JCGP() { @@ -409,8 +412,7 @@ public class JCGP {  		fitnessFunction = fitnessFunctions[0]; -		resources.setTestCases(new TestCase(new Integer[]{1, 2, 3}, new Integer[]{4, 5, 6}), -							   new TestCase(new Integer[]{4, 7, 4}, new Integer[]{6, 21, 2})); +		resources.setTestCases(new TestCase(new Integer[]{1, 2, 3}, new Integer[]{-4, 5, 6}));  	} @@ -495,33 +497,88 @@ public class JCGP {  	}  	public void nextGeneration() { -		fitnessFunction.evaluate(population, resources); -		 -		if (population.getChromosome(evolutionaryAlgorithm.getFittestChromosome()).getFitness() >= resources.getInt("maxFitness")) { -			solutionFound  = true; -			resources.println("Solution found!"); -			population.getChromosome(evolutionaryAlgorithm.getFittestChromosome()).printNodes(); -		} else { -			resources.println("Generation: " + resources.getInt("currentGen") + ", fitness: " + population.getChromosome(evolutionaryAlgorithm.getFittestChromosome()).getFitness()); -			resources.set("currentGen", resources.getInt("currentGen") + 1); +		if (!finished) { +			fitnessFunction.evaluate(population, resources); + +			report(); + +			if (resources.getInt("currentGen") < resources.getInt("generations")) { +				// we still have generations left to go +				if (population.getChromosome(evolutionaryAlgorithm.getFittestChromosome()).getFitness() >= resources.getInt("maxFitness")) { +					// solution has been found, start next run +					resources.println("Solution found in generation " + resources.getInt("currentGen") + ", chromosome: " + evolutionaryAlgorithm.getFittestChromosome()); +					 +					if (resources.getInt("currentRun") < resources.getInt("runs")) { +						// there are still runs left +						resources.set("currentRun", resources.getInt("currentRun") + 1); +						resources.set("currentGen", 0); +						 +						// start a new population +						population = new Population(resources); +					} else { +						// no more generations and no more runs, we're done +						finished = true; +					} +				} else { +					resources.set("currentGen", resources.getInt("currentGen") + 1); +				} + +			} else { +				// the run has ended, check if any more runs must be done +				resources.println("Solution not found, highest fitness achieved was " +						+ population.getChromosome(evolutionaryAlgorithm.getFittestChromosome()).getFitness() +						+ " by chromosome " + evolutionaryAlgorithm.getFittestChromosome()); + +				if (resources.getInt("currentRun") < resources.getInt("runs")) { +					// the run has ended but there are still runs left +					resources.set("currentRun", resources.getInt("currentRun") + 1); +					resources.set("currentGen", 0); +					 +					// start a new population +					population = new Population(resources); +				} else { +					// no more generations and no more runs, we're done +					finished = true; +				} +			}  		} -		 +  		evolutionaryAlgorithm.evolve(population, mutator, resources); +		  	} -	public void start() {		 -		while (resources.getInt("currentGen") <= resources.getInt("generations")) { -			nextGeneration(); -			 -			if (solutionFound) { -				break; +	private void report() { +		if (resources.getInt("report") > 0) { +			if (resources.getInt("currentGen") % resources.getInt("report") == 0) { +				resources.println("Generation: " + resources.getInt("currentGen") + ", fitness: " + population.getChromosome(evolutionaryAlgorithm.getFittestChromosome()).getFitness());  			}  		} +		 +	} + +	public void start() { +		if (!finished) { +			while (resources.getInt("currentGen") <= resources.getInt("generations")) { +				nextGeneration(); +				if (finished) { +					break; +				} +			} +		} +		  	}  	public void reset() { -		solutionFound = false; +		finished = false;  		population = new Population(resources); +		resources.set("currentGen", 1); +		resources.set("currentRun", 1); +		resources.println("-----------------------------"); +		resources.println("New experiment");  	} +	public boolean isFinished() { +		return finished; +	} +	  } diff --git a/src/jcgp/backend/modules/ea/MuPlusLambda.java b/src/jcgp/backend/modules/ea/MuPlusLambda.java index 22a0876..ad8c5d8 100644 --- a/src/jcgp/backend/modules/ea/MuPlusLambda.java +++ b/src/jcgp/backend/modules/ea/MuPlusLambda.java @@ -3,8 +3,10 @@ package jcgp.backend.modules.ea;  import jcgp.JCGP.Resources;  import jcgp.backend.modules.ModuleStatus;  import jcgp.backend.modules.mutator.Mutator; +import jcgp.backend.parameters.BooleanParameter;  import jcgp.backend.parameters.IntegerParameter;  import jcgp.backend.parameters.Parameter; +import jcgp.backend.parameters.ParameterStatus;  import jcgp.backend.population.Population;  /** @@ -19,18 +21,41 @@ public class MuPlusLambda implements EvolutionaryAlgorithm {  	private int fittestChromosome;  	private IntegerParameter parents, offspring; +	private BooleanParameter report; -	public MuPlusLambda() {		 +	public MuPlusLambda(final Resources resources) {  		parents = new IntegerParameter(1, "Parents") {  			@Override -			protected void validate(int newValue) { -				 +			public void validate(int newValue) { +				if (newValue + offspring.get() != resources.getInt("popSize")) { +					status = ParameterStatus.INVALID; +					status.setDetails("Parents + offspring must equal population size."); +				} else if (newValue <= 0) { +					status = ParameterStatus.INVALID; +					status.setDetails("EA needs at least 1 parent."); +				} else { +					status = ParameterStatus.VALID; +				}  			}  		};  		offspring = new IntegerParameter(4, "Offspring") {  			@Override -			protected void validate(int newValue) { -				 +			public void validate(int newValue) { +				if (newValue + parents.get() != resources.getInt("popSize")) { +					status = ParameterStatus.INVALID; +					status.setDetails("Parents + offspring must equal population size."); +				} else if (newValue <= 0) { +					status = ParameterStatus.INVALID; +					status.setDetails("EA needs at least 1 offspring."); +				} else { +					status = ParameterStatus.VALID; +				} +			} +		}; +		report = new BooleanParameter(false, "Report") { +			@Override +			public void validate(boolean newValue) { +				// nothing  			}  		};  	} @@ -63,7 +88,7 @@ public class MuPlusLambda implements EvolutionaryAlgorithm {  	@Override  	public Parameter[] getLocalParameters() { -		return new Parameter[] {parents, offspring}; +		return new Parameter[] {parents, offspring, report};  	}  	@Override diff --git a/src/jcgp/backend/modules/ea/TournamentSelection.java b/src/jcgp/backend/modules/ea/TournamentSelection.java index 3c4a539..32ac54d 100644 --- a/src/jcgp/backend/modules/ea/TournamentSelection.java +++ b/src/jcgp/backend/modules/ea/TournamentSelection.java @@ -19,8 +19,8 @@ public class TournamentSelection implements EvolutionaryAlgorithm {  	public TournamentSelection() {		  		tournament = new IntegerParameter(1, "Tournament size") {  			@Override -			protected void validate(int newValue) { -				 +			public void validate(int newValue) { +				// TODO this  			}  		}; diff --git a/src/jcgp/backend/parameters/BooleanParameter.java b/src/jcgp/backend/parameters/BooleanParameter.java index db78419..43825be 100644 --- a/src/jcgp/backend/parameters/BooleanParameter.java +++ b/src/jcgp/backend/parameters/BooleanParameter.java @@ -11,6 +11,13 @@ public abstract class BooleanParameter extends Parameter {  		this.value = new SimpleBooleanProperty(value);  	} +	/** +	 * Simple BooleanParameter constructor,  +	 *  +	 *  +	 * @param value +	 * @param name +	 */  	public BooleanParameter(boolean value, String name) {  		super(name, false, false);  		this.value = new SimpleBooleanProperty(value); @@ -26,7 +33,7 @@ public abstract class BooleanParameter extends Parameter {  		}  	} -	protected abstract void validate(boolean newValue); +	public abstract void validate(boolean newValue);  	public SimpleBooleanProperty valueProperty() {  		return value; diff --git a/src/jcgp/backend/parameters/DoubleParameter.java b/src/jcgp/backend/parameters/DoubleParameter.java index 2b98991..53551f5 100644 --- a/src/jcgp/backend/parameters/DoubleParameter.java +++ b/src/jcgp/backend/parameters/DoubleParameter.java @@ -30,6 +30,6 @@ public abstract class DoubleParameter extends Parameter {  		return value;  	} -	protected abstract void validate(double newValue); +	public abstract void validate(double newValue);  } diff --git a/src/jcgp/backend/parameters/IntegerParameter.java b/src/jcgp/backend/parameters/IntegerParameter.java index 1127817..68095d9 100644 --- a/src/jcgp/backend/parameters/IntegerParameter.java +++ b/src/jcgp/backend/parameters/IntegerParameter.java @@ -31,6 +31,6 @@ public abstract class IntegerParameter extends Parameter {  		return value;  	} -	protected abstract void validate(int newValue); +	public abstract void validate(int newValue);  } diff --git a/src/jcgp/backend/parameters/Parameter.java b/src/jcgp/backend/parameters/Parameter.java index 26bc8f1..ddd5d5b 100644 --- a/src/jcgp/backend/parameters/Parameter.java +++ b/src/jcgp/backend/parameters/Parameter.java @@ -4,7 +4,7 @@ import javafx.beans.property.Property;  public abstract class Parameter { -	protected boolean monitor, critical; +	protected boolean monitor, critical, reset = false;  	protected ParameterStatus status = ParameterStatus.VALID; @@ -24,6 +24,10 @@ public abstract class Parameter {  		return critical;  	} +	public boolean requiresReset() { +		return critical || reset; +	} +	  	public String getName() {  		return name;  	} @@ -33,5 +37,5 @@ public abstract class Parameter {  	}  	public abstract Property<?> valueProperty(); -	 +		  } diff --git a/src/jcgp/backend/parameters/ParameterStatus.java b/src/jcgp/backend/parameters/ParameterStatus.java index ed235d4..86abe33 100644 --- a/src/jcgp/backend/parameters/ParameterStatus.java +++ b/src/jcgp/backend/parameters/ParameterStatus.java @@ -1,7 +1,7 @@  package jcgp.backend.parameters;  public enum ParameterStatus { -	INVALID, WARNING, VALID; +	INVALID, WARNING, WARNING_RESET, VALID;  	private String details; diff --git a/src/jcgp/backend/population/Chromosome.java b/src/jcgp/backend/population/Chromosome.java index 41ba06e..c7493b9 100644 --- a/src/jcgp/backend/population/Chromosome.java +++ b/src/jcgp/backend/population/Chromosome.java @@ -310,6 +310,7 @@ public class Chromosome {  	}  	public void printNodes() { +		// TODO make this proper  		int arity = resources.getInt("arity");  		for (int r = 0; r < (resources.getInt("rows")); r++) { diff --git a/src/jcgp/gui/GUI.java b/src/jcgp/gui/GUI.java index 0902b21..f7aa25d 100644 --- a/src/jcgp/gui/GUI.java +++ b/src/jcgp/gui/GUI.java @@ -53,12 +53,38 @@ public class GUI extends Application {  	private GUIConsole console = new GUIConsole();  	private SettingsPane settings; -	private Service<Void> cgpService; -	  	private boolean evolving = false;  	private Object printLock = new Object(); +	private Service<Void> cgpService = new Service<Void> () { +		@Override +		protected Task<Void> createTask() { +			Task<Void> t = new Task<Void>() { +				@Override +				protected Void call() throws Exception { +					while (!isCancelled() && !cgp.isFinished()) { +						synchronized (printLock) { +							Platform.runLater(consoleFlush); +							cgp.nextGeneration(); +							printLock.wait(); +						} +					} +					if (cgp.isFinished()) { +						Platform.runLater(new Runnable() { +							@Override +							public void run() { +								runningMode(false); +							} +						}); +					} +					return null; +				} +			}; +			return t; +		} +	}; +	  	private Runnable consoleFlush = new Runnable() {  		@Override  		public void run() { @@ -80,27 +106,6 @@ public class GUI extends Application {  	public void start(Stage primaryStage) throws Exception {  		resources.setConsole(console); -		cgpService = new Service<Void> () { -			@Override -			protected Task<Void> createTask() { -				 -				Task<Void> t = new Task<Void>() { -					@Override -					protected Void call() throws Exception { -						while (!isCancelled()) { -							Platform.runLater(consoleFlush); -							synchronized (printLock) { -								cgp.nextGeneration(); -								printLock.wait(); -							} -						} -						return null; -					} -				}; -				return t; -			} -		}; -		  		/*  		 * Instantiate the various GUI elements here.   		 *  @@ -167,45 +172,68 @@ public class GUI extends Application {  		chromosomeTabs.setDisable(value);  	} -	public void disable(boolean value) { -		chromosomeTabs.setDisable(value); -		settings.disableSettings(value); -	} - -	public void playPause() { -		if (!evolving) { -			disable(true); -			unlockOutputs(); -			evolving = true; -			cgpService.restart(); -		} else { -			disable(false); -			updateNodeGrids(); -			evolving = false; -			cgpService.cancel(); -			relockOutputs(); +	public void runPause() { +		if (!cgp.isFinished() && settings.areParametersValid()) { +			if (!evolving) { +				runningMode(true); +				cgpService.restart(); +			} else { +				cgpService.cancel(); +				runningMode(false); +			}  		}  	}  	public void step() { -		if (!evolving) { -			Thread t = new Thread(new Task<Void>() { +		if (!evolving && !cgp.isFinished() && settings.areParametersValid()) { +			if (settings.isResetRequired()) { +				reset(); +			} +			unlockOutputs(); +			Task<Void> task = new Task<Void>() {  				@Override  				protected Void call() throws Exception { -					unlockOutputs();  					cgp.nextGeneration(); -					console.flush(); -					updateNodeGrids(); -					relockOutputs(); +					Platform.runLater(consoleFlush);  					return null;  				} -			}); +			}; +			Thread t = new Thread(task);  			t.start(); +			try { +				t.join(); +			} catch (InterruptedException e) { +				// nothing +			} finally { +				updateNodeGrids(); +				relockOutputs(); +			}  		}  	}  	public void reset() { -		cgp.reset(); -		makeChromosomeTabPane(); +		if (!evolving && settings.areParametersValid()) { +			settings.applyParameters(); +			cgp.reset(); +			makeChromosomeTabPane(); +			settings.revalidateParameters(); +		} +	} +	 +	private void runningMode(boolean value) { +		chromosomeTabs.setDisable(value); +		settings.disableSettings(value); +		if (value) { +			unlockOutputs(); +			settings.getRunButton().setText("Pause"); +			if (settings.isResetRequired()) { +				reset(); +			} +		} else { +			updateNodeGrids(); +			relockOutputs(); +			settings.getRunButton().setText("Run"); +		} +		evolving = value;  	}  } diff --git a/src/jcgp/gui/console/GUIConsole.java b/src/jcgp/gui/console/GUIConsole.java index 8fdb1a5..d8625f5 100644 --- a/src/jcgp/gui/console/GUIConsole.java +++ b/src/jcgp/gui/console/GUIConsole.java @@ -10,15 +10,14 @@ import jcgp.gui.GUI;  public class GUIConsole extends AnchorPane implements Console {  	private boolean dragging; -	private TextArea textArea = new TextArea("Welcome to JCGP!\n"); +	private TextArea textArea = new TextArea("Welcome to JCGP!");  	private StringBuffer printBuffer = new StringBuffer();  	public GUIConsole() {  		super();  		textArea.setEditable(false); -		textArea.setWrapText(true); - +		  		setResizeListeners();  		AnchorPane.setTopAnchor(textArea, GUI.RESIZE_MARGIN); @@ -91,7 +90,7 @@ public class GUIConsole extends AnchorPane implements Console {  	@Override  	public void println(String s) { -		printBuffer.append(s + "\n"); +		printBuffer.append("\n" + s);  	}  	@Override diff --git a/src/jcgp/gui/settings/SettingsPane.java b/src/jcgp/gui/settings/SettingsPane.java index 41b1bba..cb066b7 100644 --- a/src/jcgp/gui/settings/SettingsPane.java +++ b/src/jcgp/gui/settings/SettingsPane.java @@ -32,17 +32,16 @@ public class SettingsPane extends AnchorPane {  	private VBox mainContainer;  	private VBox bpPane, eaPane, mutatorPane, ffPane, nfPane; -	private ArrayList<GUIParameter> parameters = new ArrayList<GUIParameter>(); -	private GUI gui; +	private Button runPause; +	private ArrayList<GUIParameter> parameters = new ArrayList<GUIParameter>(); +		  	private boolean dragging = false;  	public SettingsPane(JCGP cgp, GUI gui) {  		super(); -		 -		this.gui = gui; -		 +				  		setResizeListeners();  		mainContainer = new VBox(8); @@ -85,22 +84,22 @@ public class SettingsPane extends AnchorPane {  		bpPane.getChildren().add(header); -		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("rows"))); -		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("columns"))); -		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("inputs"))); -		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("outputs"))); -		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("levelsBack"))); +		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("rows"), this)); +		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("columns"), this)); +		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("inputs"), this)); +		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("outputs"), this)); +		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("levelsBack"), this)); -		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("popSize"))); -		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("generations"))); -		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("runs"))); +		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("popSize"), this)); +		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("generations"), this)); +		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("runs"), this)); -		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("currentGen"))); -		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("currentRun")));				 +		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("currentGen"), this)); +		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("currentRun"), this));				 -		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("maxFitness"))); -		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("seed"))); -		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("report"))); +		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("maxFitness"), this)); +		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("seed"), this)); +		parameters.add(GUIParameter.create((IntegerParameter) cgp.getResources().getParameter("report"), this));  		bpPane.getChildren().addAll(parameters); @@ -238,43 +237,41 @@ public class SettingsPane extends AnchorPane {  		controls.setFillWidth(true);  		final HBox flowButtons = new HBox(2); -		final Button play = new Button("Run"); -		 -		play.setOnAction(new EventHandler<ActionEvent>() { +		runPause = new Button("Run"); +		runPause.setOnAction(new EventHandler<ActionEvent>() {  			@Override  			public void handle(ActionEvent event) {				 -				if (play.getText() == "Run") { -					if (isResetRequired()) { -						resetExperiment(); -					} -					play.setText("Pause"); -				} else { -					play.setText("Run"); -				} -				gui.playPause(); +				gui.runPause();  			}  		});  		Button step = new Button("Step"); -		  		step.setOnAction(new EventHandler<ActionEvent>() {  			@Override  			public void handle(ActionEvent event) { -				if (isResetRequired()) { -					resetExperiment(); -				}  				gui.step();  			}  		}); -		flowButtons.getChildren().addAll(play, step); +		Button reset = new Button("Reset"); +		reset.setOnAction(new EventHandler<ActionEvent>() { +			@Override +			public void handle(ActionEvent event) { +				gui.reset(); +			} +		}); +		 +		flowButtons.getChildren().addAll(runPause, step, reset); -		HBox.setHgrow(play, Priority.ALWAYS); -		play.setMaxWidth(Double.MAX_VALUE); +		HBox.setHgrow(runPause, Priority.ALWAYS); +		runPause.setMaxWidth(Double.MAX_VALUE);  		HBox.setHgrow(step, Priority.ALWAYS);  		step.setMaxWidth(Double.MAX_VALUE); +		HBox.setHgrow(reset, Priority.ALWAYS); +		reset.setMaxWidth(Double.MAX_VALUE); +		  		controls.getChildren().add(flowButtons);  		mainContainer.getChildren().add(controls);	 @@ -288,11 +285,12 @@ public class SettingsPane extends AnchorPane {  		parameters.removeAll(vb.getChildren());  		vb.getChildren().clear();  		for (int i = 0; i < newParameters.length; i++) { -	        GUIParameter gp = GUIParameter.create(newParameters[i]); +	        GUIParameter gp = GUIParameter.create(newParameters[i], this);  	        parameters.add(gp);          	vb.getChildren().add(gp);  		} +		revalidateParameters();  	}  	private void refreshFunctions(final FunctionSet fs, VBox vb) { @@ -377,21 +375,38 @@ public class SettingsPane extends AnchorPane {  	 *   	 * @return true if the experiment needs to be reset, false otherwise.  	 */ -	private boolean isResetRequired() { -		boolean reset = false; +	public boolean isResetRequired() {  		for (GUIParameter parameter : parameters) { -			reset |= parameter.requiresReset(); +			if (parameter.requiresReset()) { +				return true; +			}  		} -		System.out.println("reset: " + reset); -		return reset; +		return false;  	} -	private void resetExperiment() { +	public boolean areParametersValid() {  		for (GUIParameter parameter : parameters) { -			parameter.applyValue(); +			if (!parameter.isValid()) { +				return false; +			}  		} -		gui.reset(); -		 +		return true; +	} +	 +	public void revalidateParameters() { +		for (GUIParameter parameter : parameters) { +			parameter.validate(); +		} +	} +	 +	public void applyParameters() { +		for (GUIParameter parameter : parameters) { +			parameter.applyValue(); +		}	 +	} +	 +	public Button getRunButton() { +		return runPause;  	} diff --git a/src/jcgp/gui/settings/parameters/GUIBooleanParameter.java b/src/jcgp/gui/settings/parameters/GUIBooleanParameter.java index da564f7..fc66e7d 100644 --- a/src/jcgp/gui/settings/parameters/GUIBooleanParameter.java +++ b/src/jcgp/gui/settings/parameters/GUIBooleanParameter.java @@ -6,12 +6,13 @@ import javafx.scene.control.CheckBox;  import jcgp.backend.parameters.BooleanParameter;  import jcgp.backend.parameters.ParameterStatus;  import jcgp.gui.GUI; +import jcgp.gui.settings.SettingsPane;  public class GUIBooleanParameter extends GUIParameter {  	private boolean originalValue; -	GUIBooleanParameter(final BooleanParameter parameter) { +	GUIBooleanParameter(final BooleanParameter parameter, final SettingsPane sp) {  		super();  		this.parameter = parameter; @@ -32,18 +33,8 @@ public class GUIBooleanParameter extends GUIParameter {  						ObservableValue<? extends Boolean> observable,  						Boolean oldValue, Boolean newValue) {  					parameter.set(newValue); -					if (parameter.getStatus() == ParameterStatus.INVALID) { -						valueControl.setStyle(GUI.INVALID_PARAMETER_STYLE); -						valueControl.setTooltip(tooltip); -						tooltip.setText(parameter.getStatus().getDetails()); -					} else if (parameter.getStatus() == ParameterStatus.WARNING) { -						valueControl.setStyle(GUI.WARNING_PARAMETER_STYLE); -						valueControl.setTooltip(tooltip); -						tooltip.setText(parameter.getStatus().getDetails()); -					} else { -						valueControl.setStyle(GUI.VALID_PARAMETER_STYLE); -						valueControl.setTooltip(null); -					} +					setValidityStyle(); +					sp.revalidateParameters();  				}  			});  		} @@ -60,7 +51,8 @@ public class GUIBooleanParameter extends GUIParameter {  	@Override  	public boolean requiresReset() { -		return parameter.isCritical() && ((BooleanParameter) parameter).get() != originalValue; +		return (parameter.isCritical() && ((BooleanParameter) parameter).get() != originalValue) +				|| parameter.getStatus() == ParameterStatus.WARNING_RESET;  	}  	@Override @@ -68,4 +60,27 @@ public class GUIBooleanParameter extends GUIParameter {  		originalValue = ((BooleanParameter) parameter).get();  	} +	/** +	 * @param parameter +	 */ +	private void setValidityStyle() { +		if (parameter.getStatus() == ParameterStatus.INVALID) { +			valueControl.setStyle(GUI.INVALID_PARAMETER_STYLE); +			valueControl.setTooltip(tooltip); +			tooltip.setText(parameter.getStatus().getDetails()); +		} else if (parameter.getStatus() == ParameterStatus.WARNING || parameter.getStatus() ==  ParameterStatus.WARNING_RESET) { +			valueControl.setStyle(GUI.WARNING_PARAMETER_STYLE); +			valueControl.setTooltip(tooltip); +			tooltip.setText(parameter.getStatus().getDetails()); +		} else { +			valueControl.setStyle(GUI.VALID_PARAMETER_STYLE); +			valueControl.setTooltip(null); +		} +	} + +	@Override +	public void validate() { +		((BooleanParameter) parameter).validate(((BooleanParameter) parameter).get()); +		setValidityStyle(); +	}  } diff --git a/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java b/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java index a1b4526..190f4b7 100644 --- a/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java +++ b/src/jcgp/gui/settings/parameters/GUIDoubleParameter.java @@ -11,12 +11,13 @@ import javafx.scene.text.Text;  import jcgp.backend.parameters.DoubleParameter;  import jcgp.backend.parameters.ParameterStatus;  import jcgp.gui.GUI; +import jcgp.gui.settings.SettingsPane;  public class GUIDoubleParameter extends GUIParameter {  	private double originalValue; -	GUIDoubleParameter(final DoubleParameter parameter) { +	GUIDoubleParameter(final DoubleParameter parameter, final SettingsPane sp) {  		super();  		this.parameter = parameter; @@ -54,18 +55,8 @@ public class GUIDoubleParameter extends GUIParameter {  						String oldValue, String newValue) {  					if (!newValue.isEmpty()) {  						parameter.set(Double.parseDouble(newValue)); -						if (parameter.getStatus() == ParameterStatus.INVALID) { -							valueControl.setStyle(GUI.INVALID_PARAMETER_STYLE); -							valueControl.setTooltip(tooltip); -							tooltip.setText(parameter.getStatus().getDetails()); -						} else if (parameter.getStatus() == ParameterStatus.WARNING) { -							valueControl.setStyle(GUI.WARNING_PARAMETER_STYLE); -							valueControl.setTooltip(tooltip); -							tooltip.setText(parameter.getStatus().getDetails()); -						} else { -							valueControl.setStyle(GUI.VALID_PARAMETER_STYLE); -							valueControl.setTooltip(null); -						} +						setValidityStyle(); +						sp.revalidateParameters();  					}  				} @@ -93,7 +84,8 @@ public class GUIDoubleParameter extends GUIParameter {  	@Override  	public boolean requiresReset() { -		return parameter.isCritical() && ((DoubleParameter) parameter).get() != originalValue; +		return (parameter.isCritical() && ((DoubleParameter) parameter).get() != originalValue) +				|| parameter.getStatus() == ParameterStatus.WARNING_RESET;  	}  	@Override @@ -101,4 +93,25 @@ public class GUIDoubleParameter extends GUIParameter {  		originalValue = ((DoubleParameter) parameter).get();  	} +	@Override +	public void validate() { +		((DoubleParameter) parameter).validate(((DoubleParameter) parameter).get()); +		setValidityStyle(); +	} +	 +	private void setValidityStyle() { +		if (parameter.getStatus() == ParameterStatus.INVALID) { +			valueControl.setStyle(GUI.INVALID_PARAMETER_STYLE); +			valueControl.setTooltip(tooltip); +			tooltip.setText(parameter.getStatus().getDetails()); +		} else if (parameter.getStatus() == ParameterStatus.WARNING || parameter.getStatus() ==  ParameterStatus.WARNING_RESET) { +			valueControl.setStyle(GUI.WARNING_PARAMETER_STYLE); +			valueControl.setTooltip(tooltip); +			tooltip.setText(parameter.getStatus().getDetails()); +		} else { +			valueControl.setStyle(GUI.VALID_PARAMETER_STYLE); +			valueControl.setTooltip(null); +		} +	} +  } diff --git a/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java b/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java index bf1a61e..a2040d7 100644 --- a/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java +++ b/src/jcgp/gui/settings/parameters/GUIIntegerParameter.java @@ -11,12 +11,13 @@ import javafx.scene.text.Text;  import jcgp.backend.parameters.IntegerParameter;  import jcgp.backend.parameters.ParameterStatus;  import jcgp.gui.GUI; +import jcgp.gui.settings.SettingsPane;  public class GUIIntegerParameter extends GUIParameter {  	private int originalValue; -	GUIIntegerParameter(final IntegerParameter parameter) {	 +	GUIIntegerParameter(final IntegerParameter parameter, final SettingsPane sp) {	  		super();  		this.parameter = parameter; @@ -54,18 +55,8 @@ public class GUIIntegerParameter extends GUIParameter {  						String oldValue, String newValue) {  					if (!newValue.isEmpty()) {  						parameter.set(Integer.parseInt(newValue)); -						if (parameter.getStatus() == ParameterStatus.INVALID) { -							valueControl.setStyle(GUI.INVALID_PARAMETER_STYLE); -							valueControl.setTooltip(tooltip); -							tooltip.setText(parameter.getStatus().getDetails()); -						} else if (parameter.getStatus() == ParameterStatus.WARNING) { -							valueControl.setStyle(GUI.WARNING_PARAMETER_STYLE); -							valueControl.setTooltip(tooltip); -							tooltip.setText(parameter.getStatus().getDetails()); -						} else { -							valueControl.setStyle(GUI.VALID_PARAMETER_STYLE); -							valueControl.setTooltip(null); -						} +						setValidityStyle(); +						sp.revalidateParameters();  					}  				} @@ -92,7 +83,9 @@ public class GUIIntegerParameter extends GUIParameter {  	@Override  	public boolean requiresReset() { -		return parameter.isCritical() && ((IntegerParameter) parameter).get() != originalValue; +		// true if critical and the value has changed, or it requires a reset anyway +		return (parameter.isCritical() && ((IntegerParameter) parameter).get() != originalValue) +				|| parameter.getStatus() == ParameterStatus.WARNING_RESET;  	}  	@Override @@ -100,4 +93,25 @@ public class GUIIntegerParameter extends GUIParameter {  		originalValue = ((IntegerParameter) parameter).get();  	} +	@Override +	public void validate() { +		((IntegerParameter) parameter).validate(((IntegerParameter) parameter).get()); +		setValidityStyle(); +	} +	 +	private void setValidityStyle() { +		if (parameter.getStatus() == ParameterStatus.INVALID) { +			valueControl.setStyle(GUI.INVALID_PARAMETER_STYLE); +			valueControl.setTooltip(tooltip); +			tooltip.setText(parameter.getStatus().getDetails()); +		} else if (parameter.getStatus() == ParameterStatus.WARNING || parameter.getStatus() ==  ParameterStatus.WARNING_RESET) { +			valueControl.setStyle(GUI.WARNING_PARAMETER_STYLE); +			valueControl.setTooltip(tooltip); +			tooltip.setText(parameter.getStatus().getDetails()); +		} else { +			valueControl.setStyle(GUI.VALID_PARAMETER_STYLE); +			valueControl.setTooltip(null); +		} +	} +  } diff --git a/src/jcgp/gui/settings/parameters/GUIParameter.java b/src/jcgp/gui/settings/parameters/GUIParameter.java index 9d6f07a..da2fe86 100644 --- a/src/jcgp/gui/settings/parameters/GUIParameter.java +++ b/src/jcgp/gui/settings/parameters/GUIParameter.java @@ -14,6 +14,8 @@ import jcgp.backend.parameters.BooleanParameter;  import jcgp.backend.parameters.DoubleParameter;  import jcgp.backend.parameters.IntegerParameter;  import jcgp.backend.parameters.Parameter; +import jcgp.backend.parameters.ParameterStatus; +import jcgp.gui.settings.SettingsPane;  public abstract class GUIParameter extends HBox { @@ -59,15 +61,23 @@ public abstract class GUIParameter extends HBox {  	public abstract void applyValue(); -	public static GUIParameter create(Parameter parameter) { +	public abstract void validate(); +	 +	public static GUIParameter create(Parameter parameter, SettingsPane sp) {  		if (parameter instanceof IntegerParameter) { -			return new GUIIntegerParameter((IntegerParameter) parameter); +			return new GUIIntegerParameter((IntegerParameter) parameter, sp);  		} else if (parameter instanceof DoubleParameter) { -			return new GUIDoubleParameter((DoubleParameter) parameter); +			return new GUIDoubleParameter((DoubleParameter) parameter, sp);  		} else if (parameter instanceof BooleanParameter) { -			return new GUIBooleanParameter((BooleanParameter) parameter); +			return new GUIBooleanParameter((BooleanParameter) parameter, sp);  		} else {  			throw new ClassCastException("No GUIParameter subclass exists for argument of type " + parameter.getClass());  		}  	} +	 +	public boolean isValid() { +		return parameter.getStatus() == ParameterStatus.VALID +				|| parameter.getStatus() == ParameterStatus.WARNING +				|| parameter.getStatus() == ParameterStatus.WARNING_RESET; +	}  } | 
