diff options
author | Eduardo Pedroni <ep625@york.ac.uk> | 2014-04-26 19:56:24 +0100 |
---|---|---|
committer | Eduardo Pedroni <ep625@york.ac.uk> | 2014-04-26 19:56:24 +0100 |
commit | 4c8de2402f2878cde7587c7f3bbf4ffaea86efd4 (patch) | |
tree | 29156510f648a2d9f8de4df3b2617d4a056e1d90 | |
parent | b0c0698e5503c2506217117bf144fde31e6f6601 (diff) |
Moved files around to different folders, and commented some more packages. Aiming to have the entire backend fully commented by the end of today
27 files changed, 287 insertions, 184 deletions
diff --git a/src/cgp0.chr b/res/cgp0.chr index 3157c03..3157c03 100644 --- a/src/cgp0.chr +++ b/res/cgp0.chr diff --git a/src/epar3.plu b/res/epar3.plu index b554b66..b554b66 100644 --- a/src/epar3.plu +++ b/res/epar3.plu diff --git a/src/mult2.plu b/res/mult2.plu index e629d28..e629d28 100644 --- a/src/mult2.plu +++ b/res/mult2.plu diff --git a/src/parameters.par b/res/parameters.par index bf38c11..bf38c11 100644 --- a/src/parameters.par +++ b/res/parameters.par diff --git a/src/quintic-polynomial.dat b/res/quintic-polynomial.dat index 347b95a..347b95a 100644 --- a/src/quintic-polynomial.dat +++ b/res/quintic-polynomial.dat diff --git a/src/jcgp/JCGP.java b/src/jcgp/JCGP.java index 1e6d628..f36ac7c 100644 --- a/src/jcgp/JCGP.java +++ b/src/jcgp/JCGP.java @@ -264,13 +264,13 @@ public class JCGP { } public void loadParameters(File file) { - ParameterParser.parseParameters(file, resources); - FunctionParser.parseFunctions(file, problem, resources); + ParameterParser.parse(file, resources); + FunctionParser.parse(file, problem.getFunctionSet(), resources); reset(); } public void loadProblemData(File file) { - problem.parse(file, resources); + problem.parseProblemData(file, resources); reset(); } diff --git a/src/jcgp/backend/exceptions/InsufficientConnectionsException.java b/src/jcgp/backend/exceptions/InsufficientConnectionsException.java deleted file mode 100644 index 15ac845..0000000 --- a/src/jcgp/backend/exceptions/InsufficientConnectionsException.java +++ /dev/null @@ -1,10 +0,0 @@ -package jcgp.backend.exceptions; - -public class InsufficientConnectionsException extends RuntimeException { - - /** - * - */ - private static final long serialVersionUID = 660740514800883541L; - -} diff --git a/src/jcgp/backend/exceptions/InvalidArgumentsException.java b/src/jcgp/backend/exceptions/InvalidArgumentsException.java deleted file mode 100644 index bbae976..0000000 --- a/src/jcgp/backend/exceptions/InvalidArgumentsException.java +++ /dev/null @@ -1,20 +0,0 @@ -package jcgp.backend.exceptions; - -public class InvalidArgumentsException extends RuntimeException { - - /** - * - */ - private static final long serialVersionUID = 2675108124600817777L; - private String reason; - - public InvalidArgumentsException(String reason) { - super(); - this.reason = reason; - } - - public String getReason() { - return reason; - } - -} diff --git a/src/jcgp/backend/exceptions/ParameterMismatchException.java b/src/jcgp/backend/exceptions/ParameterMismatchException.java deleted file mode 100644 index 83e2ba2..0000000 --- a/src/jcgp/backend/exceptions/ParameterMismatchException.java +++ /dev/null @@ -1,10 +0,0 @@ -package jcgp.backend.exceptions; - -public class ParameterMismatchException extends RuntimeException { - - /** - * - */ - private static final long serialVersionUID = -3161318886125868134L; - -} diff --git a/src/jcgp/backend/modules/es/MuPlusLambda.java b/src/jcgp/backend/modules/es/MuPlusLambda.java index 50bf265..754e89b 100644 --- a/src/jcgp/backend/modules/es/MuPlusLambda.java +++ b/src/jcgp/backend/modules/es/MuPlusLambda.java @@ -76,6 +76,11 @@ public class MuPlusLambda implements EvolutionaryStrategy { } @Override + public Parameter<?>[] getLocalParameters() { + return new Parameter[] {mu, lambda, report}; + } + + @Override public void evolve(Population population, Mutator mutator, Resources resources) { /* Population is sorted in ascending order of fitness, so leave the last * mu chromosomes intact @@ -95,11 +100,6 @@ public class MuPlusLambda implements EvolutionaryStrategy { } @Override - public Parameter<?>[] getLocalParameters() { - return new Parameter[] {mu, lambda, report}; - } - - @Override public String toString() { return "(μ + λ)"; } diff --git a/src/jcgp/backend/modules/mutator/ProbabilisticMutator.java b/src/jcgp/backend/modules/mutator/ProbabilisticMutator.java index e3c1d03..cacb451 100644 --- a/src/jcgp/backend/modules/mutator/ProbabilisticMutator.java +++ b/src/jcgp/backend/modules/mutator/ProbabilisticMutator.java @@ -70,7 +70,7 @@ public class ProbabilisticMutator implements Mutator { for (int c = 0; c < resources.columns(); c++) { // go through all connections for (int a = 0; a < resources.arity(); a++) { - if (mutate()) { + if (mutateGene()) { Node n = chromosome.getNode(r, c); if (report.get()) resources.report("[Mutator] Mutating " + n + @@ -83,7 +83,7 @@ public class ProbabilisticMutator implements Mutator { } } // deal with node function next - if (mutate()) { + if (mutateGene()) { Node n = chromosome.getNode(r, c); if (report.get()) resources.report("[Mutator] Mutating " + n + ", changed function from " + n.getFunction()); @@ -96,7 +96,7 @@ public class ProbabilisticMutator implements Mutator { } // finally, mutate outputs for (int o = 0; o < resources.outputs(); o++) { - if (mutate()) { + if (mutateGene()) { Output out = chromosome.getOutput(o); if (report.get()) resources.report("[Mutator] Mutating " + out + @@ -120,7 +120,7 @@ public class ProbabilisticMutator implements Mutator { * * @return true if a mutation should be performed, false if otherwise. */ - private boolean mutate() { + private boolean mutateGene() { return resources.getRandomDouble(100) < mutationProbability.get(); } diff --git a/src/jcgp/backend/modules/problem/Problem.java b/src/jcgp/backend/modules/problem/Problem.java index 07183ea..368d512 100644 --- a/src/jcgp/backend/modules/problem/Problem.java +++ b/src/jcgp/backend/modules/problem/Problem.java @@ -9,6 +9,25 @@ import jcgp.backend.population.Population; import jcgp.backend.resources.ModifiableResources; import jcgp.backend.resources.Resources; +/** + * Defines the general behaviour of a CGP problem. The primary function of Problem + * is to evaluate a population and assign + * <br><br> + * Parameters may be specified to control the implemented problem. Any parameters + * returned by {@code getLocalParameters()} should be displayed by the user interface, + * if it is being used. See {@link Parameter} for more information. + * <br><br> + * It is advisable to use {@code Resources.reportln()} and {@code Resources.report()} + * to print any relevant information. Note that reportln() and report() are affected + * by the report interval base parameter. Use {@code Resources.println()} and + * {@code Resources.print()} to print information regardless of the current generation. + * See {@link Resources} for more information. + * + * @see Module + * + * @author Eduardo Pedroni + * + */ public abstract class Problem implements Module { protected FunctionSet functionSet; @@ -23,7 +42,7 @@ public abstract class Problem implements Module { public abstract boolean isPerfectSolution(Chromosome fittest); - public abstract void parse(File file, ModifiableResources resources); + public abstract void parseProblemData(File file, ModifiableResources resources); public void setFileExtension(String fileExtension) { this.fileExtension = fileExtension; diff --git a/src/jcgp/backend/modules/problem/TestCaseProblem.java b/src/jcgp/backend/modules/problem/TestCaseProblem.java index 6c4a7dc..7ce0327 100644 --- a/src/jcgp/backend/modules/problem/TestCaseProblem.java +++ b/src/jcgp/backend/modules/problem/TestCaseProblem.java @@ -119,8 +119,7 @@ public abstract class TestCaseProblem<U extends Object> extends Problem { testCases.clear(); } - public void parse(File file, ModifiableResources resources) { - TestCaseParser.parseParameters(file, resources); + public void parseProblemData(File file, ModifiableResources resources) { TestCaseParser.parse(file, this, resources); } } diff --git a/src/jcgp/backend/modules/problem/TravellingSalesmanProblem.java b/src/jcgp/backend/modules/problem/TravellingSalesmanProblem.java index 6491ec6..8363ef8 100644 --- a/src/jcgp/backend/modules/problem/TravellingSalesmanProblem.java +++ b/src/jcgp/backend/modules/problem/TravellingSalesmanProblem.java @@ -36,7 +36,7 @@ public class TravellingSalesmanProblem extends Problem { } @Override - public void parse(File file, ModifiableResources resources) { + public void parseProblemData(File file, ModifiableResources resources) { // TODO Auto-generated method stub } diff --git a/src/jcgp/backend/parsers/ChromosomeParser.java b/src/jcgp/backend/parsers/ChromosomeParser.java index ed1399a..92568cc 100644 --- a/src/jcgp/backend/parsers/ChromosomeParser.java +++ b/src/jcgp/backend/parsers/ChromosomeParser.java @@ -14,7 +14,7 @@ import jcgp.backend.resources.ModifiableResources; import jcgp.backend.resources.Resources; /** - * This class includes a method for parsing .chr files and another + * This class contains a method for parsing .chr files and another * for writing .chr files from given chromosomes. * * @author Eduardo Pedroni @@ -50,7 +50,7 @@ public abstract class ChromosomeParser { try { fr = new FileReader(file); } catch (FileNotFoundException e) { - resources.println("[Parser] Error: could not find " + file.getAbsolutePath() + "."); + resources.println("[Parser] Error: could not find " + file.getAbsolutePath()); return; } Scanner in = new Scanner(fr); @@ -70,7 +70,7 @@ public abstract class ChromosomeParser { try { fr = new FileReader(file); } catch (FileNotFoundException e) { - resources.println("[Parser] Error: could not find " + file.getAbsolutePath() + "."); + resources.println("[Parser] Error: could not find " + file.getAbsolutePath()); return; } in = new Scanner(fr); @@ -122,10 +122,10 @@ public abstract class ChromosomeParser { } in.close(); - resources.println("[Parser] File parsed successfully."); + resources.println("[Parser] File parsed successfully"); } else { - resources.println("[Parser] Error: the topology of the chromosome in " + file.getName() + " does not match that of the experiment."); + resources.println("[Parser] Error: the topology of the chromosome in " + file.getName() + " does not match that of the experiment"); } } @@ -143,7 +143,7 @@ public abstract class ChromosomeParser { try { writer = new PrintWriter(file); } catch (FileNotFoundException e) { - resources.println("[Parser] Error: could not find " + file.getAbsolutePath() + "."); + resources.println("[Parser] Error: could not find " + file.getAbsolutePath()); return; } @@ -184,7 +184,7 @@ public abstract class ChromosomeParser { writer.close(); - resources.println("[Parser] Chromosome saved successfully."); + resources.println("[Parser] Chromosome saved successfully"); } } diff --git a/src/jcgp/backend/parsers/FunctionParser.java b/src/jcgp/backend/parsers/FunctionParser.java index cc52ce9..806099e 100644 --- a/src/jcgp/backend/parsers/FunctionParser.java +++ b/src/jcgp/backend/parsers/FunctionParser.java @@ -6,21 +6,35 @@ import java.io.FileReader; import java.util.Scanner; import jcgp.backend.function.FunctionSet; -import jcgp.backend.modules.problem.Problem; -import jcgp.backend.resources.ModifiableResources; +import jcgp.backend.resources.Resources; /** - * Parses the functions from a .par file. - * Functions marked with a 1 are enabled, - * and those marked with 0 are disabled. + * Contains a static method for parsing functions from a + * .par file. * * @author Eduardo Pedroni * */ public abstract class FunctionParser { - public static void parseFunctions(File file, Problem problem, ModifiableResources resources) { - + /** + * Reads the specified file and attempts to enable + * and disable the functions in the FunctionSet + * accordingly. + * <br><br> + * Standard CGP .par files do not contain enough information + * to determine if they match the currently selected function set. + * For this reason, the parser assumes the function set is correct + * and treats functions by their index rather than their name. Any + * index outside the bounds of the function set is ignored and a + * warning message is printed once parsing is complete. + * + * @param file the .par file to parse. + * @param functionSet the function set whose functions should be modified. + * @param resources used for printing console messages. + */ + public static void parse(File file, FunctionSet functionSet, Resources resources) { + // create file reader and scanner to parse, return if file does not exist FileReader fr; try { fr = new FileReader(file); @@ -30,23 +44,56 @@ public abstract class FunctionParser { } Scanner in = new Scanner(fr); - FunctionSet functionSet = problem.getFunctionSet(); + boolean excessFunctions = false; resources.println("[Parser] Parsing file: " + file.getAbsolutePath() + "..."); + /* + * The encoding used in .par files is quite simple, so regex matches are used to extract + * the values. + * + * A standard .par file contains functions in the following format: + * + * 0 1 modulus-0 + * 0 1 sqrt-1 + * 0 1 reciprocal-2 + * + * The first integer signals whether to enable or disable the function. Any non-zero value + * is treated as "enable". The second integer is the function arity. The integer following + * the function name is the function index. + * + * The scanner is used to return each line separately. Every line that ends in a number + * is treated as a function line and split into an array, which holds its composing integers. + * This array is then used to enable or disabled the indexed function. + * + * A flag is raised if the index exceeds the total number of functions, and a warning is + * printed once parsing is complete regarding the index mismatch. + * + */ while (in.hasNextLine()) { String line = in.nextLine(); if (line.substring(line.length() - 1).matches("[0-9]")) { String[] splitString = line.split("[^0-9]+"); int functionIndex = Integer.parseInt(splitString[splitString.length - 1]); - if (Integer.parseInt(splitString[0]) != 0 && !functionSet.isEnabled(functionSet.getFunction(functionIndex))) { - functionSet.enableFunction(functionIndex); - resources.println("[Parser] Enabled function: " + functionSet.getFunction(functionIndex)); - } else if (Integer.parseInt(splitString[0]) == 0 && functionSet.isEnabled(functionSet.getFunction(functionIndex))) { - functionSet.disableFunction(functionIndex); - resources.println("[Parser] Disabled function: " + functionSet.getFunction(functionIndex)); + + if (functionIndex < functionSet.getTotalFunctionCount()) { + if (Integer.parseInt(splitString[0]) != 0) { + functionSet.enableFunction(functionIndex); + resources.println("[Parser] Enabled function: " + functionSet.getFunction(functionIndex)); + } else if (Integer.parseInt(splitString[0]) == 0) { + functionSet.disableFunction(functionIndex); + resources.println("[Parser] Disabled function: " + functionSet.getFunction(functionIndex)); + } + } else { + excessFunctions = true; } } } + + // warn the user function index went out of bounds + if (excessFunctions) { + resources.println("[Parser] Warning: the parameter file contained more functions than the current function set"); + } + in.close(); resources.println("[Parser] Finished parsing functions"); } diff --git a/src/jcgp/backend/parsers/ParameterParser.java b/src/jcgp/backend/parsers/ParameterParser.java index ae72126..711b4d2 100644 --- a/src/jcgp/backend/parsers/ParameterParser.java +++ b/src/jcgp/backend/parsers/ParameterParser.java @@ -7,71 +7,94 @@ import java.util.Scanner; import jcgp.backend.resources.ModifiableResources; +/** + * Contains a static method for parsing parameters from a + * .par file. + * + * @author Eduardo Pedroni + * + */ public abstract class ParameterParser { - public static void parseParameters(File file, ModifiableResources resources) { - + /** + * Parses the parameters from a specified CGP parameter file and + * modifies the experiment resources appropriately. + * <br><br> + * CGP .par files do not follow a very strict convention, so this + * parser does its best to cope with format irregularities. Parsing + * works even if the parameters are in the wrong order, and unknown + * parameters are simply ignored. + * + * @param file the .par file to parse. + * @param resources a reference to the resources object that must be modified. + */ + public static void parse(File file, ModifiableResources resources) { + // create reader and scanner, print message if file is missing FileReader fr; try { fr = new FileReader(file); } catch (FileNotFoundException e) { - resources.println("[Parser] Error: could not find " + file.getAbsolutePath() + "."); + resources.println("[Parser] Error: could not find " + file.getAbsolutePath()); return; } Scanner in = new Scanner(fr); resources.println("[Parser] Parsing file: " + file.getAbsolutePath() + "..."); + // parse line by line while (in.hasNextLine()) { + // split if one or more tabs or one or more spaces are found String[] splitString = in.nextLine().split("( |\t)+"); - - switch (splitString[1]) { - case "population_size": - resources.setPopulationSize(Integer.parseInt(splitString[0])); - resources.println("[Parser] Population size is now " + resources.populationSize() + "."); - break; - - case "num_generations": - resources.setGenerations(Integer.parseInt(splitString[0])); - resources.println("[Parser] Total generations is now " + resources.generations() + "."); - break; - - case "num_runs_total": - resources.setRuns(Integer.parseInt(splitString[0])); - resources.println("[Parser] Total runs is now " + resources.runs() + "."); - break; - - case "num_rows": - resources.setRows(Integer.parseInt(splitString[0])); - resources.println("[Parser] Row number is now " + resources.rows() + "."); - break; - - case "num_cols": - resources.setColumns(Integer.parseInt(splitString[0])); - resources.println("[Parser] Column number is now " + resources.columns() + "."); - break; + // expected length is 2, anything beyond that should also work + if (splitString.length >= 2) { + switch (splitString[1]) { + case "population_size": + resources.setPopulationSize(Integer.parseInt(splitString[0])); + resources.println("[Parser] Population size is now " + resources.populationSize()); + break; + + case "num_generations": + resources.setGenerations(Integer.parseInt(splitString[0])); + resources.println("[Parser] Total generations is now " + resources.generations()); + break; + + case "num_runs_total": + resources.setRuns(Integer.parseInt(splitString[0])); + resources.println("[Parser] Total runs is now " + resources.runs()); + break; + + case "num_rows": + resources.setRows(Integer.parseInt(splitString[0])); + resources.println("[Parser] Row number is now " + resources.rows()); + break; + + case "num_cols": + resources.setColumns(Integer.parseInt(splitString[0])); + resources.println("[Parser] Column number is now " + resources.columns()); + break; + + case "levels_back": + resources.setLevelsBack(Integer.parseInt(splitString[0])); + resources.println("[Parser] Levels back is now " + resources.levelsBack()); + break; + + case "report_interval": + resources.setReportInterval(Integer.parseInt(splitString[0])); + resources.println("[Parser] Report interval is now " + resources.levelsBack()); + break; + + case "global_seed": + resources.setSeed(Integer.parseInt(splitString[0])); + resources.println("[Parser] Seed is now " + resources.seed()); + break; - case "levels_back": - resources.setLevelsBack(Integer.parseInt(splitString[0])); - resources.println("[Parser] Levels back is now " + resources.levelsBack() + "."); - break; - - case "report_interval": - resources.setReportInterval(Integer.parseInt(splitString[0])); - resources.println("[Parser] Report interval is now " + resources.levelsBack() + "."); - break; - - case "global_seed": - resources.setSeed(Integer.parseInt(splitString[0])); - resources.println("[Parser] Seed is now " + resources.seed() + "."); - break; - - default: - break; + default: + break; + } } } in.close(); - resources.println("[Parser] Finished parsing parameters."); + resources.println("[Parser] Finished parsing parameters"); } } diff --git a/src/jcgp/backend/parsers/TestCaseParser.java b/src/jcgp/backend/parsers/TestCaseParser.java index cef018e..bcfa8a9 100644 --- a/src/jcgp/backend/parsers/TestCaseParser.java +++ b/src/jcgp/backend/parsers/TestCaseParser.java @@ -8,14 +8,34 @@ import java.util.Scanner; import jcgp.backend.modules.problem.TestCaseProblem; import jcgp.backend.resources.ModifiableResources; +/** + * Contains a static method for parsing values from a + * CGP problem data file. The actual file extension + * varies from problem to problem, and is therefore + * defined in the experiment's Problem instance. + * + * + * @author Eduardo Pedroni + * + */ public abstract class TestCaseParser { + /** + * Sets the number of inputs and outputs in the resources + * to match the given file, and parses each test case + * from the file into the specified problem. + * + * @param file the problem file to parse. + * @param problem the problem into which to parse the problem data. + * @param resources a modifiable reference to the experiment's resources + */ public static void parse(File file, TestCaseProblem<?> problem, ModifiableResources resources) { + // create reader and scanner, print error message if file is missing FileReader fr; try { fr = new FileReader(file); } catch (FileNotFoundException e) { - resources.println("[Parser] Error: could not find " + file.getAbsolutePath() + "."); + resources.println("[Parser] Error: could not find " + file.getAbsolutePath()); return; } resources.println("[Parser] Parsing file: " + file.getAbsolutePath() + "..."); @@ -24,28 +44,44 @@ public abstract class TestCaseParser { int inputs = 0, outputs = 0; int cases = 0; + // this overwrites any previously added test cases problem.clearTestCases(); while (in.hasNextLine()) { String nextLine = in.nextLine(); - + // set resources input count to parsed value if (nextLine.startsWith(".i")) { String[] split = nextLine.split(" +"); inputs = Integer.parseInt(split[1]); - } else if (nextLine.startsWith(".o")) { + resources.setInputs(inputs); + resources.println("[Parser] Number of inputs set to " + resources.inputs()); + } + // set resources output count to parsed value + else if (nextLine.startsWith(".o")) { String[] split = nextLine.split(" +"); outputs = Integer.parseInt(split[1]); + resources.setOutputs(outputs); + resources.println("[Parser] Number of outputs set to " + resources.outputs()); + } else if (nextLine.startsWith(".p") || nextLine.startsWith(".t")) { readingTestCases = true; + } else if (nextLine.startsWith(".e")) { readingTestCases = false; + + /* + * Split every line at one or more spaces or tabs, and + * parse the two sides into inputs and outputs. + */ } else if (readingTestCases) { String[] split = nextLine.split("( |\t)+"); String[] inputCases = new String[inputs]; String[] outputCases = new String[outputs]; + for (int i = 0; i < inputs; i++) { inputCases[i] = split[i]; } + for (int o = 0; o < outputs; o++) { outputCases[o] = split[o + inputs]; } @@ -54,37 +90,7 @@ public abstract class TestCaseParser { cases++; } } - resources.println("[Parser] Finished, added " + cases + " test cases."); - in.close(); - } - - public static void parseParameters(File file, ModifiableResources resources) { - - FileReader fr; - try { - fr = new FileReader(file); - } catch (FileNotFoundException e) { - resources.println("[Parser] Error: could not find " + file.getAbsolutePath() + "."); - return; - } - - resources.println("[Parser] Parsing parameters..."); - Scanner in = new Scanner(fr); - - while (in.hasNextLine()) { - String nextLine = in.nextLine(); - if (nextLine.startsWith(".i")) { - String[] split = nextLine.split(" +"); - resources.setInputs(Integer.parseInt(split[1])); - resources.println("[Parser] Number of inputs set to " + resources.inputs()); - } else if (nextLine.startsWith(".o")) { - String[] split = nextLine.split(" +"); - resources.setOutputs(Integer.parseInt(split[1])); - resources.println("[Parser] Number of outputs set to " + resources.outputs()); - } - } + resources.println("[Parser] Finished, added " + cases + " test cases"); in.close(); - - resources.println("[Parser] Finished parsing parameters."); } } diff --git a/src/jcgp/backend/population/Chromosome.java b/src/jcgp/backend/population/Chromosome.java index 9e53f85..d23f43c 100644 --- a/src/jcgp/backend/population/Chromosome.java +++ b/src/jcgp/backend/population/Chromosome.java @@ -2,7 +2,6 @@ package jcgp.backend.population; import java.util.ArrayList; -import jcgp.backend.exceptions.ParameterMismatchException; import jcgp.backend.resources.Resources; public class Chromosome implements Comparable<Chromosome> { @@ -168,7 +167,7 @@ public class Chromosome implements Comparable<Chromosome> { * @param values * @throws ParameterMismatchException */ - public void setInputs(Object ... values) throws ParameterMismatchException { + public void setInputs(Object ... values) { // if the values provided don't match the specified number of inputs, the user should be warned if (values.length == inputs.length) { // set inputs for evaluation @@ -176,7 +175,7 @@ public class Chromosome implements Comparable<Chromosome> { inputs[i].setValue(values[i]); } } else { - throw new ParameterMismatchException(); + throw new IllegalArgumentException("Received " + values.length + " inputs but needed exactly " + inputs.length); } } diff --git a/src/jcgp/backend/population/Node.java b/src/jcgp/backend/population/Node.java index 1ac5b10..74f6b54 100644 --- a/src/jcgp/backend/population/Node.java +++ b/src/jcgp/backend/population/Node.java @@ -1,9 +1,7 @@ package jcgp.backend.population; import java.util.ArrayList; -import java.util.Arrays; -import jcgp.backend.exceptions.InsufficientConnectionsException; import jcgp.backend.function.Function; @@ -22,7 +20,11 @@ public class Node extends Gene implements MutableElement, Connection { @Override public Object getValue() { - return function.run(Arrays.copyOfRange(connections, 0, function.getArity())); + Object[] args = new Object[function.getArity()]; + for (int i = 0; i < function.getArity(); i++) { + args[i] = connections[i].getValue(); + } + return function.run(args); } public void setFunction(Function newFunction) { @@ -31,23 +33,18 @@ public class Node extends Gene implements MutableElement, Connection { @Override public void setConnection(int index, Connection newConnection) { - if (newConnection instanceof Node) { - if (((Node) newConnection).getColumn() < column) { - connections[index] = newConnection; - chromosome.recomputeActiveNodes(); - } - } else if (newConnection instanceof Input) { + if (newConnection != null) { connections[index] = newConnection; chromosome.recomputeActiveNodes(); } } - public void initialise(Function newFunction, Connection ... newConnections) throws InsufficientConnectionsException { + public void initialise(Function newFunction, Connection ... newConnections) { function = newFunction; if (newConnections.length == chromosome.getResources().arity()) { connections = newConnections; } else { - throw new InsufficientConnectionsException(); + throw new IllegalArgumentException("Received " + newConnections.length + " connections but needed exactly " + chromosome.getResources().arity()); } } diff --git a/src/jcgp/backend/tests/ChromosomeTests.java b/src/jcgp/backend/tests/ChromosomeTests.java index bc0c57d..c326805 100644 --- a/src/jcgp/backend/tests/ChromosomeTests.java +++ b/src/jcgp/backend/tests/ChromosomeTests.java @@ -2,7 +2,6 @@ package jcgp.backend.tests; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import jcgp.backend.function.SymbolicRegressionFunctions; import jcgp.backend.population.Chromosome; import jcgp.backend.population.Connection; import jcgp.backend.population.Input; @@ -46,7 +45,7 @@ public class ChromosomeTests { @BeforeClass public static void setUpBeforeClass() { resources = new ModifiableResources(); - resources.setFunctionSet(new SymbolicRegressionFunctions()); + resources.setFunctionSet(new TestFunctionSet()); } @Before @@ -225,9 +224,12 @@ public class ChromosomeTests { chromosome.setInputs(5, 8, 4); + Integer output0 = (Integer) chromosome.getOutput(0).calculate(); + Integer output1 = (Integer) chromosome.getOutput(1).calculate(); + // with this configuration, the outputs should be 13 and 25. - assertTrue("Incorrect output returned.", (Integer) chromosome.getOutput(0).calculate() == 13); - assertTrue("Incorrect output returned.", (Integer) chromosome.getOutput(1).calculate() == 25); + assertTrue("Incorrect output returned: " + output0, output0 == 13.0); + assertTrue("Incorrect output returned: " + output1, output1 == 25.0); } /** diff --git a/src/jcgp/backend/tests/NodeTests.java b/src/jcgp/backend/tests/NodeTests.java index c63b41e..ee940a0 100644 --- a/src/jcgp/backend/tests/NodeTests.java +++ b/src/jcgp/backend/tests/NodeTests.java @@ -1,8 +1,6 @@ package jcgp.backend.tests; import static org.junit.Assert.assertTrue; -import jcgp.backend.exceptions.InvalidArgumentsException; -import jcgp.backend.function.SymbolicRegressionFunctions; import jcgp.backend.function.Function; import jcgp.backend.population.Chromosome; import jcgp.backend.population.Connection; @@ -41,15 +39,15 @@ public class NodeTests { public static void setUpBeforeClass() { resources = new ModifiableResources(); - resources.setFunctionSet(new SymbolicRegressionFunctions()); + resources.setFunctionSet(new TestFunctionSet()); chromosome = new Chromosome(resources); } @Before public void setUp() throws Exception { node = new Node(chromosome, 0, 0, resources.arity()); - // make node with anonymous addition function and hard-coded value connections - node.initialise(new SymbolicRegressionFunctions.Addition(), + // make node with addition function and hard-coded value connections + node.initialise(resources.getFunction(0), new Connection[]{new Connection() { @Override @@ -107,7 +105,7 @@ public class NodeTests { ((int) node.getValue()) == arg1 + arg2); // put in a different function, check the output has changed appropriately - node.setFunction(new SymbolicRegressionFunctions.Subtraction()); + node.setFunction(resources.getFunction(1)); assertTrue("Node did not return expected value (difference of arguments).", ((Integer) node.getValue()) == arg1 - arg2); @@ -136,8 +134,7 @@ public class NodeTests { Function function = new Function() { @Override - public Object run(Object... connections) - throws InvalidArgumentsException { + public Object run(Object... connections) { // blank return null; } diff --git a/src/jcgp/backend/tests/TestFunctionSet.java b/src/jcgp/backend/tests/TestFunctionSet.java new file mode 100644 index 0000000..1910d2a --- /dev/null +++ b/src/jcgp/backend/tests/TestFunctionSet.java @@ -0,0 +1,54 @@ +package jcgp.backend.tests; + +import jcgp.backend.function.Function; +import jcgp.backend.function.FunctionSet; + +public class TestFunctionSet extends FunctionSet { + + public TestFunctionSet() { + + functionList = new Function[] { + new Function() { + @Override + public Object run(Object... args) { + return (Integer) args[0] + (Integer) args[1]; + } + @Override + public int getArity() { + return 2; + } + }, + new Function() { + @Override + public Object run(Object... args) { + return (Integer) args[0] - (Integer) args[1]; + } + @Override + public int getArity() { + return 2; + } + }, + new Function() { + @Override + public Object run(Object... args) { + return (Integer) args[0] * (Integer) args[1]; + } + @Override + public int getArity() { + return 2; + } + }, + new Function() { + @Override + public Object run(Object... args) { + return (Integer) args[0] / (Integer) args[1]; + } + @Override + public int getArity() { + return 2; + } + } + }; + enableAll(); + } +}
\ No newline at end of file |