From dd3b6446671f31d716eb07e546c6150b4d080abd Mon Sep 17 00:00:00 2001 From: Eduardo Pedroni Date: Tue, 11 Feb 2014 16:50:27 +0000 Subject: Implemented more tests, refactored chromosome more, added the beginnings of active node detection --- src/jcgp/tests/ChromosomeTests.java | 216 ++++++++++++++++++++++++++++-------- 1 file changed, 172 insertions(+), 44 deletions(-) (limited to 'src/jcgp/tests') diff --git a/src/jcgp/tests/ChromosomeTests.java b/src/jcgp/tests/ChromosomeTests.java index 50d17b9..ece8203 100644 --- a/src/jcgp/tests/ChromosomeTests.java +++ b/src/jcgp/tests/ChromosomeTests.java @@ -1,15 +1,17 @@ package jcgp.tests; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; 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; import jcgp.population.Chromosome; +import jcgp.population.Connection; import jcgp.population.Input; import jcgp.population.MutableElement; import jcgp.population.Node; @@ -24,24 +26,24 @@ import org.junit.Test; * * - The chromosome should be able to return a specified node, input or output. * - It should be able to return a random MutableElement. - * - It should be able to return a random Connection + * - It should be able to return a random allowed connection given a column + * - It should be able to return any random connection * - It should contain a freely modifiable fitness value. - * - It should be a good citizen - fully initialised upon instantiation. + * - 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. * - It should feature a clone constructor, which creates a deep copy of a * specified Chromosome object. - * - It should be able to return the number of active nodes. - * - For truth table evaluations, it should be able to have its inputs set. + * - It should be able to return a list of active nodes. + * + * WARNING: changing parameters may cause the tests to incorrectly fail! * * @author Eduardo Pedroni * */ public class ChromosomeTests { - Chromosome chromosome; - int inputCount = 3, - rows = 3, - columns = 3, - outputCount = 3; + private Chromosome chromosome; @Before public void setUp() throws Exception { @@ -52,54 +54,180 @@ public class ChromosomeTests { Utilities.setResources(new Random(1234), functionSet); // initialise parameters - Parameters.setColumns(columns); - Parameters.setRows(rows); - Parameters.setInputs(inputCount); - Parameters.setOutputs(outputCount); - Parameters.setLevelsBack(1); + Parameters.setColumns(20); + Parameters.setRows(10); + Parameters.setInputs(2); + Parameters.setOutputs(4); + Parameters.setLevelsBack(20); Parameters.setMutationRate(10); Parameters.setTotalGenerations(100); Parameters.setTotalRuns(5); Parameters.setMaxArity(functionSet.getMaxArity()); - chromosome = new Chromosome(inputCount, rows, columns, outputCount); - + chromosome = new Chromosome(); + } + /** + * + */ @Test - public void test() { - // pick arbitrary node, assume that if one node is right, all nodes are right - boolean nodeReturn = chromosome.getNode(1, 2).getColumn() == 2 - && chromosome.getNode(1, 2).getRow() == 1 - && chromosome.getNode(1, 2) instanceof Node; - assertTrue("Incorrect node returned.", nodeReturn); - - // set input values, check that acquired values are correct - chromosome.setInputs(4, 5, 6); - boolean inputReturn = chromosome.getInput(0).getValue() == 4 && chromosome.getInput(0) instanceof Input - && chromosome.getInput(1).getValue() == 5 && chromosome.getInput(0) instanceof Input - && chromosome.getInput(2).getValue() == 6 && chromosome.getInput(0) instanceof Input; - assertTrue("Incorrect inputs returned.", inputReturn); - - // connect outputs to inputs, check that calculated outputs return input values - for (int i = 0; i < outputCount; i++) { - chromosome.getOutput(i).setConnection(chromosome.getInput(0)); - } - boolean outputReturn = chromosome.getOutput(0).calculate() == 4 && chromosome.getOutput(0) instanceof Output - && chromosome.getOutput(1).calculate() == 4 && chromosome.getOutput(0) instanceof Output - && chromosome.getOutput(2).calculate() == 4 && chromosome.getOutput(0) instanceof Output; - assertTrue("Incorrect output returned.", outputReturn); - - // get a mutable element, check that it is a Mutable - boolean mutableReturn = chromosome.getRandomMutableElement() != chromosome.getRandomMutableElement() && chromosome.getRandomMutableElement() instanceof MutableElement; - assertTrue("Returned the same element.", mutableReturn); + public void cloneTest() { + int[] testInputs; + // create a clone, check to see if it really is a clone + Chromosome clone = new Chromosome(chromosome); + // set input values + testInputs = new int[Parameters.getInputs()]; + for (int i = 0; i < Parameters.getInputs(); i++) { + testInputs[i] = i * 2 - 3; + } + chromosome.setInputs(testInputs); + clone.setInputs(testInputs); + // connect outputs to inputs, check that the outputs match + for (int i = 0; i < Parameters.getOutputs(); i++) { + chromosome.getOutput(i).setConnection(chromosome.getInput(i % Parameters.getInputs())); + clone.getOutput(i).setConnection(clone.getInput(i % Parameters.getInputs())); + assertTrue("Incorrect output returned.", chromosome.getOutput(i).calculate() == + clone.getOutput(i).calculate()); + } + // change clone inputs, outputs should no longer match + testInputs = new int[Parameters.getInputs()]; + for (int i = 0; i < Parameters.getInputs(); i++) { + testInputs[i] = i * 2; + } + clone.setInputs(testInputs); + for (int i = 0; i < Parameters.getOutputs(); i++) { + assertTrue("Incorrect output returned.", chromosome.getOutput(i).calculate() != + clone.getOutput(i).calculate()); + } + } + + /** + * + */ + @Test + public void fitnessTest() { // set a fitness value, check if returned value is the same chromosome.setFitness(10); assertTrue("Incorrect fitness returned.", chromosome.getFitness() == 10); - } + /** + * + */ + @Test + public void randomConnectionTest() { + // get random connections with column 0, check that they are all inputs + for (int i = 0; i < 10000; i++) { + boolean connectionReturn = chromosome.getRandomConnection(0) instanceof Input; + assertTrue("Connection is not an input.", connectionReturn); + } + + // get random connections with column 2 + // they should all be nodes, and their columns should be within range + int connectionNodes = 0, connectionOutOfRange = 0, connectionInputs = 0, connectionPicks = 100000; + int chosenColumn = 2; + for (int i = 0; i < connectionPicks; i++) { + Connection c = chromosome.getRandomConnection(chosenColumn); + if (c instanceof Node) { + connectionNodes++; + if (((Node) c).getColumn() >= chosenColumn) { + connectionOutOfRange++; + } + assertTrue("Connection is not allowed : " + ((Node) c).getColumn(), ((Node) c).getColumn() < chosenColumn && ((Node) c).getColumn() < chosenColumn); + } else if (c instanceof Input) { + connectionInputs++; + } else { + fail("Return is neither Node nor Input."); + + } + } + System.out.println("Out of " + connectionPicks + " connections picked from " + ((chosenColumn >= Parameters.getLevelsBack()) ? Parameters.getLevelsBack() : chosenColumn) * Parameters.getRows() + + " nodes and " + Parameters.getInputs() + " allowed nodes, " + connectionNodes + " were nodes and " + connectionInputs + " were inputs."); + + System.out.println("Node/input ratio: " + ((double) ((chosenColumn >= Parameters.getLevelsBack()) ? Parameters.getLevelsBack() : chosenColumn) * Parameters.getRows()) / (double) Parameters.getInputs() + + ", picked ratio: " + (double) connectionNodes / (double) connectionInputs); + + System.out.println(connectionOutOfRange + " nodes that disrespected levels back were picked."); + } + + /** + * + */ + @Test + public void randomMutableTest() { + // get mutable elements, check Node to Output ratio + int mutablePicks = 100000; + int mutableNodes = 0, mutableOutputs = 0; + for (int i = 0; i < mutablePicks; i++) { + MutableElement m = chromosome.getRandomMutableElement(); + + if (m instanceof Node) { + mutableNodes++; + } else if (m instanceof Output) { + mutableOutputs++; + } else { + fail("Return is neither Node nor Output."); + } + } + System.out.println("Out of " + mutablePicks + " mutable elements picked from " + Parameters.getNodeCount() + + " nodes and " + Parameters.getOutputs() + " outputs, " + mutableNodes + " were nodes and " + + mutableOutputs + " were outputs."); + System.out.println("Node/output ratio: " + (double) Parameters.getNodeCount() / (double) Parameters.getOutputs() + + ", picked ratio: " + (double) mutableNodes / (double) mutableOutputs + "\n"); + } + + /** + * + */ + @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()); + } + } + + /** + * @throws ParameterMismatchException + */ + @Test + public void setInputTest() throws ParameterMismatchException { + // set input values, check that acquired values are correct + int[] testInputs = new int[Parameters.getInputs()]; + for (int i = 0; i < Parameters.getInputs(); i++) { + testInputs[i] = i * 2 - 3; + } + chromosome.setInputs(testInputs); + for (int i = 0; i < Parameters.getInputs(); i++) { + assertTrue("Incorrect input returned.", chromosome.getInput(i).getValue() == i * 2 - 3); + } + } + + /** + * + */ + @Test + public void getNodeTest() { + // get all nodes one by one, check that they are all correct + for (int r = 0; r < Parameters.getRows(); r++) { + for (int c = 0; c < Parameters.getColumns(); c++) { + assertTrue("Incorrect node returned.", chromosome.getNode(r, c).getColumn() == c && + chromosome.getNode(r, c).getRow() == r); + } + } + } + + /** + * + */ + @Test + public void activeNodeTest() { + + } } -- cgit v1.2.3