package jcgp.backend.resources; import java.util.Random; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import jcgp.backend.function.Function; import jcgp.backend.function.FunctionSet; import jcgp.backend.resources.parameters.IntegerParameter; import jcgp.backend.resources.parameters.ParameterStatus; /** * * The resources class encapsulates all of the resources based on which the program operates. * Each instance of JCGP contains a single instance of Resources, which gets passed to the selected * modules as the program executes. * * @author Eduardo Pedroni * */ public class Resources { protected IntegerParameter rows, columns, inputs, outputs, populationSize, levelsBack, currentGeneration, generations, currentRun, runs, arity, seed, reportInterval; protected Random numberGenerator = new Random(); protected FunctionSet functionSet; // GUI console protected Console console; public Resources() { createBaseParameters(); } /** * @return the rows */ public int rows() { return rows.get(); } /** * @return the columns */ public int columns() { return columns.get(); } /** * @return the inputs */ public int inputs() { return inputs.get(); } /** * @return the outputs */ public int outputs() { return outputs.get(); } /** * @return the populationSize */ public int populationSize() { return populationSize.get(); } /** * @return the levelsBack */ public int levelsBack() { return levelsBack.get(); } /** * @return the nodes */ public int nodes() { return columns.get() * rows.get(); } /** * @return the currentGeneration */ public int currentGeneration() { return currentGeneration.get(); } /** * @return the generations */ public int generations() { return generations.get(); } /** * @return the currentRun */ public int currentRun() { return currentRun.get(); } /** * @return the runs */ public int runs() { return runs.get(); } /** * @return the arity */ public int arity() { return arity.get(); } /** * @return the seed */ public int seed() { return seed.get(); } /** * @return the report interval */ public int reportInterval() { return reportInterval.get(); } private void createBaseParameters() { rows = new IntegerParameter(5, "Rows", false, true) { @Override public void validate(Number newValue) { if (newValue.intValue() <= 0) { status = ParameterStatus.INVALID; status.setDetails("Chromosome must have at least 1 row."); } else { status = ParameterStatus.VALID; } } }; columns = new IntegerParameter(5, "Columns", false, true) { @Override public void validate(Number newValue) { if (newValue.intValue() <= 0) { status = ParameterStatus.INVALID; status.setDetails("Chromosome must have at least 1 column."); } else { status = ParameterStatus.VALID; } } }; inputs = new IntegerParameter(3, "Inputs", true, false) { @Override public void validate(Number newValue) { if (newValue.intValue() <= 0) { status = ParameterStatus.INVALID; status.setDetails("Chromosome must have at least 1 input."); } else { status = ParameterStatus.VALID; } } }; outputs = new IntegerParameter(3, "Outputs", true, false) { @Override public void validate(Number newValue) { if (newValue.intValue() <= 0) { status = ParameterStatus.INVALID; status.setDetails("Chromosome must have at least 1 output."); } else { status = ParameterStatus.VALID; } } }; populationSize = new IntegerParameter(5, "Population", false, true) { @Override public void validate(Number newValue) { if (newValue.intValue() <= 0) { status = ParameterStatus.INVALID; status.setDetails("Population size must be at least 1."); } else { status = ParameterStatus.VALID; } } }; levelsBack = new IntegerParameter(2, "Levels back", false, true) { @Override public void validate(Number newValue) { if (newValue.intValue() <= 0) { status = ParameterStatus.INVALID; status.setDetails("Levels back must be at least 1."); } else if (newValue.intValue() > columns.get()) { status = ParameterStatus.INVALID; status.setDetails("Levels back must be less than or equal to the number of columns."); } else { status = ParameterStatus.VALID; } } }; generations = new IntegerParameter(1000000, "Generations") { @Override public void validate(Number newValue) { if (newValue.intValue() <= 0) { status = ParameterStatus.INVALID; status.setDetails("Number of generations must be greater than 0."); } else if (newValue.intValue() < currentGeneration.get()) { status = ParameterStatus.WARNING_RESET; status.setDetails("Setting generations to less than the current generation will cause the experiment to restart."); } else { status = ParameterStatus.VALID; } } }; currentGeneration = new IntegerParameter(1, "Generation", true, false) { @Override public void validate(Number newValue) { // blank } }; runs = new IntegerParameter(5, "Runs") { @Override public void validate(Number newValue) { if (newValue.intValue() <= 0) { status = ParameterStatus.INVALID; status.setDetails("Number of runs must be greater than 0."); } else if (newValue.intValue() < currentRun.get()) { status = ParameterStatus.WARNING_RESET; status.setDetails("Setting runs to less than the current run will cause the experiment to restart."); } else { status = ParameterStatus.VALID; } } }; currentRun = new IntegerParameter(1, "Run", true, false) { @Override public void validate(Number newValue) { // blank } }; arity = new IntegerParameter(0, "Max arity", true, false) { @Override public void validate(Number newValue) { // blank } }; seed = new IntegerParameter(1234, "Seed", false, true) { @Override public void validate(Number newValue) { status = ParameterStatus.VALID; } }; seed.valueProperty().addListener(new ChangeListener() { @Override public void changed( ObservableValue observable, Number oldValue, Number newValue) { numberGenerator.setSeed(newValue.longValue()); } }); numberGenerator.setSeed(seed.get()); reportInterval = new IntegerParameter(1, "Report interval", false, false) { @Override public void validate(Number newValue) { if (newValue.intValue() > generations.get()) { status = ParameterStatus.WARNING; status.setDetails("No reports will be printed."); } else { status = ParameterStatus.VALID; } } }; } /* * Utility functions */ public int getRandomInt(int limit) { return numberGenerator.nextInt(limit); } public double getRandomDouble(int limit) { return numberGenerator.nextDouble() * limit; } public double getRandomDouble() { return numberGenerator.nextDouble(); } /* * FunctionSet functions */ public Function getRandomFunction() { Function f = functionSet.getAllowedFunction(numberGenerator.nextInt(functionSet.getAllowedFunctionCount())); return f; } public Function getFunction(int index) { return functionSet.getAllowedFunction(index); } /** * @return the functionSet */ public FunctionSet getFunctionSet() { return functionSet; } public int getFunctionIndex(Function function) { for (int i = 0; i < functionSet.getTotalFunctionCount(); i++) { if (function == functionSet.getFunction(i)) { return i; } } // not found, default to 0 return 0; } /* * Console functionality * These are affected by parameter report interval */ public void reportln(String s) { if (reportInterval.get() > 0) { if (currentGeneration.get() % reportInterval.get() == 0) { System.out.println(s); if (console != null) { console.println(s); } } } } public void report(String s) { if (reportInterval.get() > 0) { if (currentGeneration.get() % reportInterval.get() == 0) { System.out.print(s); if (console != null) { console.print(s); } } } } }