From afa484021ba94d12e98da682a9ff69c3837d5dbb Mon Sep 17 00:00:00 2001 From: Eduardo Pedroni Date: Fri, 14 Feb 2014 18:13:21 +0000 Subject: Generic data type functionality implemented. All tests were refactored to reflect this, and some chromosome tests were rewritten with more rigorous assertions. --- src/jcgp/tests/ChromosomeTests.java | 124 ++++++++++++++++++++---------------- src/jcgp/tests/InputTests.java | 2 +- src/jcgp/tests/NodeTests.java | 99 +++++++++------------------- src/jcgp/tests/OutputTests.java | 6 +- src/jcgp/tests/PopulationTests.java | 2 - 5 files changed, 105 insertions(+), 128 deletions(-) (limited to 'src/jcgp/tests') diff --git a/src/jcgp/tests/ChromosomeTests.java b/src/jcgp/tests/ChromosomeTests.java index d2407a6..8092d60 100644 --- a/src/jcgp/tests/ChromosomeTests.java +++ b/src/jcgp/tests/ChromosomeTests.java @@ -6,7 +6,6 @@ import java.util.Random; import jcgp.Parameters; import jcgp.Utilities; -import jcgp.fitness.ParameterMismatchException; import jcgp.function.Addition; import jcgp.function.FunctionSet; import jcgp.function.Subtraction; @@ -31,8 +30,7 @@ import org.junit.Test; * - It should be able to return a random connection. * - It should contain a freely modifiable fitness value. * - For truth table evaluations, it should be able to have its inputs set. - * - For truth table evaluations, the output should return a value according to what - * it is set to. + * - For truth table evaluations, the output should return a value according to the inputs. * - It should feature a clone constructor, which creates a deep copy of a * specified Chromosome object. * - It should be able to return a list of active nodes. @@ -40,7 +38,6 @@ import org.junit.Test; * to it. * - Same as above, but only looking at the active portion of a chromosome. * - * TODO: bashing (strange value ranges, etc) * * WARNING: changing parameters may cause the tests to incorrectly fail! * @@ -60,19 +57,19 @@ public class ChromosomeTests { Utilities.setResources(new Random(1234), functionSet); // initialise parameters - Parameters.setColumns(30); - Parameters.setRows(20); - Parameters.setInputs(2); - Parameters.setOutputs(4); - Parameters.setLevelsBack(1); Parameters.setMutationRate(10); - Parameters.setTotalGenerations(100); + Parameters.setTotalGenerations(10); Parameters.setTotalRuns(5); Parameters.setMaxArity(functionSet.getMaxArity()); } @Before public void setUp() throws Exception { + Parameters.setColumns(10); + Parameters.setRows(2); + Parameters.setInputs(2); + Parameters.setOutputs(4); + Parameters.setLevelsBack(10); chromosome = new Chromosome(); } @@ -81,7 +78,6 @@ public class ChromosomeTests { */ @Test public void cloneTest() { - int[] testInputs; // create a clone, check to see if it really is a clone Chromosome clone = new Chromosome(chromosome); @@ -146,29 +142,26 @@ public class ChromosomeTests { } } - // set input values - testInputs = new int[Parameters.getInputs()]; - for (int i = 0; i < Parameters.getInputs(); i++) { - testInputs[i] = (i + 1) * 2 - 3; - } - chromosome.setInputs(testInputs); - clone.setInputs(testInputs); + // check cloning given a known topology + chromosome = createKnownConfiguration(); + clone = new Chromosome(chromosome); + + Integer[] testInputs = new Integer[] {5, 8, 4}; + chromosome.setInputs((Object[]) testInputs); + clone.setInputs((Object[]) testInputs); // check that both chromosomes have the same outputs for (int i = 0; i < Parameters.getOutputs(); i++) { - assertTrue("Incorrect output returned.", chromosome.getOutput(i).calculate() == - clone.getOutput(i).calculate()); + assertTrue("Incorrect output returned", ((Integer) chromosome.getOutput(i).calculate()) == ((Integer) clone.getOutput(i).calculate())); } - // mutate an active node in clone, check that the same node in chromosome produces a different output - // NOTE: given a small grid this mutation may actually pick the same connection (causing no effective change) and therefore the test would fail. - Node node = clone.getActiveNodes().get(Utilities.getRandomInt(clone.getActiveNodes().size())); - node.setConnection(clone.getRandomConnection(node.getColumn())); + // mutate an output in clone, check that the same node in chromosome produces a different output + clone.getOutput(1).setConnection(clone.getInput(2)); - assertTrue("Mutation affected both nodes in both chromosomes.", node.getValue() != chromosome.getNode(node.getRow(), node.getColumn()).getValue()); + assertTrue("Mutation affected nodes in both chromosomes.", + clone.getOutput(1).calculate() != chromosome.getOutput(1).calculate()); } - /** * */ @@ -217,7 +210,6 @@ public class ChromosomeTests { System.out.println(connectionOutOfRange + " nodes that disrespected levels back were picked."); } - /** * */ @@ -249,27 +241,28 @@ public class ChromosomeTests { */ @Test public void getOutputsTest() { - // connect outputs to inputs, check that calculated outputs return input values - for (int i = 0; i < Parameters.getOutputs(); i++) { - chromosome.getOutput(i).setConnection(chromosome.getInput(i % Parameters.getInputs())); - assertTrue("Incorrect output returned.", chromosome.getOutput(i).calculate() == - chromosome.getInput(i % Parameters.getInputs()).getValue()); - } + chromosome = createKnownConfiguration(); + + chromosome.setInputs(5, 8, 4); + + // 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); } /** - * @throws ParameterMismatchException + * */ @Test - public void setInputTest() throws ParameterMismatchException { + public void setInputTest() { // set input values, check that acquired values are correct - int[] testInputs = new int[Parameters.getInputs()]; + Integer[] testInputs = new Integer[Parameters.getInputs()]; for (int i = 0; i < Parameters.getInputs(); i++) { testInputs[i] = i * 2 - 3; } - chromosome.setInputs(testInputs); + chromosome.setInputs((Object[]) testInputs); for (int i = 0; i < Parameters.getInputs(); i++) { - assertTrue("Incorrect input returned.", chromosome.getInput(i).getValue() == i * 2 - 3); + assertTrue("Incorrect input returned.", ((Integer) chromosome.getInput(i).getValue()) == i * 2 - 3); } } @@ -294,20 +287,15 @@ public class ChromosomeTests { public void activeNodeTest() { // active node detection happens recursively, the user only calls a single method // set connections to a known configuration - for (int i = 0; i < Parameters.getOutputs(); i++) { - chromosome.getOutput(i).setConnection(chromosome.getNode(0, 0)); - } - - chromosome.getNode(0, 0).setConnection(chromosome.getInput(0)); - - assertTrue("Active node not in list.", chromosome.getActiveNodes().contains(chromosome.getNode(0, 0))); - - // change outputs, print list - chromosome.getOutput(0).setConnection(chromosome.getNode(0, Parameters.getColumns() - 1)); - - System.out.println("Active connections: " + chromosome.getActiveNodes().toString() + "\n"); + chromosome = createKnownConfiguration(); + + assertTrue("Active node missing from list.", chromosome.getActiveNodes().contains(chromosome.getNode(0, 0))); + assertTrue("Active node missing from list.", chromosome.getActiveNodes().contains(chromosome.getNode(1, 1))); + assertTrue("Active node missing from list.", chromosome.getActiveNodes().contains(chromosome.getNode(1, 2))); + + assertTrue("List has the wrong number of nodes.", chromosome.getActiveNodes().size() == 3); } - + /** * */ @@ -317,12 +305,12 @@ public class ChromosomeTests { Chromosome c = new Chromosome(chromosome); assertTrue("Active nodes did not match.", chromosome.compareActiveTo(c)); assertTrue("Symmetry not obeyed.", c.compareActiveTo(chromosome)); - + // create a new random chromosome, this time they should not match c = new Chromosome(); assertTrue("Active nodes did match.", !chromosome.compareActiveTo(c)); } - + /** * */ @@ -332,9 +320,37 @@ public class ChromosomeTests { Chromosome c = new Chromosome(chromosome); assertTrue("Chromosomes did not match.", chromosome.compareTo(c)); assertTrue("Symmetry not obeyed.", c.compareTo(chromosome)); - + // create a new random chromosome, this time they should not match c = new Chromosome(); assertTrue("Chromosomes did match.", !chromosome.compareTo(c)); } + /** + * Utility for creating a chromosome of known configuration. + * Topology is 3x3, with 3 inputs and 2 outputs. + * Given inputs 5, 8 and 4 outputs should be 13 and 25. + * + * Active nodes (r, c): [0, 0], [1, 1], [1, 2] + * + * @return the configured chromosome + */ + private Chromosome createKnownConfiguration() { + // with a small topology, build a chromosome of known connections and check outputs + Parameters.setColumns(3); + Parameters.setRows(3); + Parameters.setInputs(3); + Parameters.setOutputs(2); + Parameters.setLevelsBack(3); + + Chromosome c = new Chromosome(); + + c.getNode(0, 0).initialise(Utilities.getFunction(0), c.getInput(0), c.getInput(1)); + c.getNode(1, 1).initialise(Utilities.getFunction(0), c.getNode(0, 0), c.getInput(1)); + c.getNode(1, 2).initialise(Utilities.getFunction(0), c.getNode(1, 1), c.getInput(2)); + + c.getOutput(0).setConnection(c.getNode(0, 0)); + c.getOutput(1).setConnection(c.getNode(1, 2)); + + return c; + } } diff --git a/src/jcgp/tests/InputTests.java b/src/jcgp/tests/InputTests.java index 3803990..51d58d2 100644 --- a/src/jcgp/tests/InputTests.java +++ b/src/jcgp/tests/InputTests.java @@ -35,7 +35,7 @@ public class InputTests { // assign a value to input, check that the returned value is correct input.setValue(inputValue); - assertTrue("Incorrect value returned.", input.getValue() == inputValue); + assertTrue("Incorrect value returned.", ((Integer) input.getValue()) == inputValue); } @Test diff --git a/src/jcgp/tests/NodeTests.java b/src/jcgp/tests/NodeTests.java index 5b378d2..9ea6769 100644 --- a/src/jcgp/tests/NodeTests.java +++ b/src/jcgp/tests/NodeTests.java @@ -6,11 +6,11 @@ import java.util.Random; import jcgp.Parameters; import jcgp.Utilities; +import jcgp.function.Addition; import jcgp.function.Function; -import jcgp.function.InsufficientArgumentsException; +import jcgp.function.Subtraction; import jcgp.population.Chromosome; import jcgp.population.Connection; -import jcgp.population.InsufficientConnectionsException; import jcgp.population.Node; import org.junit.Before; @@ -63,44 +63,25 @@ public class NodeTests { public void setUp() throws Exception { node = new Node(chromosome, 0, 0); // make node with anonymous addition function and hard-coded value connections - node.initialise(new Function() { - private int arity = 2; + node.initialise(new Addition(), + new Connection[]{new Connection() { - @Override - public int run(Connection... connections) { - - // add together the first n inputs if they exist, else throw exception - if (connections.length >= arity) { - return connections[0].getValue() + connections[1].getValue(); - } else { - throw new InsufficientArgumentsException(); - } - } + @Override + public Object getValue() { + // hardcode a value + return arg1; + } - @Override - public int getArity() { - // addition with arity 2 - return arity; - } + }, + new Connection() { - }, new Connection[]{new Connection() { + @Override + public Object getValue() { + // hardcode a value + return arg2; + } - @Override - public int getValue() { - // hardcode a value - return arg1; - } - - }, - new Connection() { - - @Override - public int getValue() { - // hardcode a value - return arg2; - } - - }}); + }}); } @Test @@ -115,8 +96,7 @@ public class NodeTests { Function f = new Function() { @Override - public int run(Connection... connections) - throws InsufficientConnectionsException { + public Object run(Connection... connections) { // blank return 0; } @@ -133,36 +113,19 @@ public class NodeTests { // check that the function returned by the node is f assertTrue("Incorrect function returned.", node.getFunction() == f); // check that it outputs 0 as it should - assertTrue("Incorrect function output.", node.getValue() == 0); + assertTrue("Incorrect function output.", ((Integer) node.getValue()) == 0); } @Test public void evaluationTest() { // check that addition is working - assertTrue("Node did not return expected value (sum of arguments).", node.getValue() == arg1 + arg2); + assertTrue("Node did not return expected value (sum of arguments). Output was: " + ((int) node.getValue()), + ((int) node.getValue()) == arg1 + arg2); // put in a different function, check the output has changed appropriately - node.setFunction(new Function() { + node.setFunction(new Subtraction()); - private int arity = 2; - - @Override - public int run(Connection... connections) throws InsufficientConnectionsException { - // add together the first n inputs if they exist, else throw exception - if (connections.length >= arity) { - return connections[0].getValue() - connections[1].getValue(); - } else { - throw new InsufficientArgumentsException(); - } - } - - @Override - public int getArity() { - return arity; - } - }); - - assertTrue("Node did not return expected value (difference of arguments).", node.getValue() == arg1 - arg2); + assertTrue("Node did not return expected value (difference of arguments).", ((Integer) node.getValue()) == arg1 - arg2); } @@ -173,7 +136,7 @@ public class NodeTests { conn0 = new Connection() { @Override - public int getValue() { + public Object getValue() { // blank return 0; } @@ -182,31 +145,31 @@ public class NodeTests { conn1 = new Connection() { @Override - public int getValue() { + public Object getValue() { // blank return 0; } }; node.initialise(null, conn0, conn1); - + assertTrue("Connection 0 is incorrect.", node.getConnection(0) == conn0); assertTrue("Connection 1 is incorrect.", node.getConnection(1) == conn1); - + // make yet another connection, set it randomly, check that it is one of the node's connections conn2 = new Connection() { @Override - public int getValue() { + public Object getValue() { // blank return 0; } }; node.setConnection(conn2); - + assertTrue("Connection was not found in node.", node.getConnection(0) == conn2 || node.getConnection(1) == conn2); - + } - + } diff --git a/src/jcgp/tests/OutputTests.java b/src/jcgp/tests/OutputTests.java index 04eac7f..c877c03 100644 --- a/src/jcgp/tests/OutputTests.java +++ b/src/jcgp/tests/OutputTests.java @@ -64,13 +64,13 @@ public class OutputTests { output.setConnection(new Connection() { @Override - public int getValue() { + public Object getValue() { // test value return outputValue; } }); - assertTrue("Incorrect evaluation.", output.calculate() == outputValue); + assertTrue("Incorrect evaluation.", ((Integer) output.calculate()) == outputValue); } @Test @@ -79,7 +79,7 @@ public class OutputTests { Connection newConn = new Connection() { @Override - public int getValue() { + public Object getValue() { // blank return 0; } diff --git a/src/jcgp/tests/PopulationTests.java b/src/jcgp/tests/PopulationTests.java index a8f55a2..bb8fece 100644 --- a/src/jcgp/tests/PopulationTests.java +++ b/src/jcgp/tests/PopulationTests.java @@ -170,7 +170,5 @@ public class PopulationTests { } } } - } - } -- cgit v1.2.3