From 3326c58f4d2d7e8c77738277dcd093aa864ad2a5 Mon Sep 17 00:00:00 2001 From: Eduardo Pedroni Date: Thu, 13 Feb 2014 17:43:59 +0000 Subject: Finished population tests, now thinking about methods to compare chromosomes --- README | 7 +++ src/jcgp/population/Population.java | 23 ++++---- src/jcgp/tests/ChromosomeTests.java | 55 ++++++++++++++++--- src/jcgp/tests/PopulationTests.java | 106 ++++++++++++++++++++++++++++++++---- 4 files changed, 161 insertions(+), 30 deletions(-) diff --git a/README b/README index f08fe1b..bf92331 100644 --- a/README +++ b/README @@ -114,5 +114,12 @@ Node tests done. Added exception support for Function in case not enough argumen Chromosome tests refactored to include the special case where columns = 1. Input and output tests written. +Population tests under way. + + +13/2 + +Writing the test for the population copy constructor will require the production of a method which compares two chromosomes. +It might be useful to incorporate this into the program as it is an interesting utility function. diff --git a/src/jcgp/population/Population.java b/src/jcgp/population/Population.java index 56f1b50..4153e0f 100644 --- a/src/jcgp/population/Population.java +++ b/src/jcgp/population/Population.java @@ -8,14 +8,17 @@ public class Population implements Iterable { private Chromosome[] population; - public Population(Chromosome ... chromosomes) { - if (chromosomes.length > 0) { - population = chromosomes; - } else { - population = new Chromosome[Parameters.getPopulationSize()]; - for (int c = 0; c < population.length; c++) { - population[c] = new Chromosome(); - } + public Population(Chromosome chromosome) { + population = new Chromosome[Parameters.getPopulationSize()]; + for (int c = 0; c < population.length; c++) { + population[c] = new Chromosome(chromosome); + } + } + + public Population() { + population = new Chromosome[Parameters.getPopulationSize()]; + for (int c = 0; c < population.length; c++) { + population[c] = new Chromosome(); } } @@ -44,10 +47,8 @@ public class Population implements Iterable { @Override public void remove() { // not allowed - // since this would shift everything back one position, increment index - // index++; + throw new UnsupportedOperationException("Removing chromosomes from the population is not allowed. Instead, re-instantiate the chromosome."); } - }; } } diff --git a/src/jcgp/tests/ChromosomeTests.java b/src/jcgp/tests/ChromosomeTests.java index cb2cb95..ff1de18 100644 --- a/src/jcgp/tests/ChromosomeTests.java +++ b/src/jcgp/tests/ChromosomeTests.java @@ -57,7 +57,7 @@ public class ChromosomeTests { Utilities.setResources(new Random(1234), functionSet); // initialise parameters - Parameters.setColumns(1); + Parameters.setColumns(30); Parameters.setRows(20); Parameters.setInputs(2); Parameters.setOutputs(4); @@ -90,13 +90,54 @@ public class ChromosomeTests { 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()); + // compare all elements, one by one + // check outputs + for (int o = 0; o < Parameters.getOutputs(); o++) { + // check that no cross-references exist between chromosomes + assertTrue("Cloned chromosome contained a reference to a member of the original chromosome.", + c.getOutput(o) != oc.getOutput(o) && + c.getOutput(o).getSource() != oc.getOutput(o).getSource()); + // check that the connections are equivalent + if (c.getOutput(o).getSource() instanceof Input && oc.getOutput(o).getSource() instanceof Input) { + assertTrue("Outputs did not connect to equivalent inputs.", + ((Input) c.getOutput(o).getSource()).getIndex() == ((Input) oc.getOutput(o).getSource()).getIndex()); + } else if (c.getOutput(o).getSource() instanceof Node && oc.getOutput(o).getSource() instanceof Node) { + assertTrue("Outputs did not connect to equivalent nodes.", + ((Node) c.getOutput(o).getSource()).getRow() == ((Node) oc.getOutput(o).getSource()).getRow() && + ((Node) c.getOutput(o).getSource()).getColumn() == ((Node) oc.getOutput(o).getSource()).getColumn()); + } else { + fail("Output source types did not match."); + } } + // check nodes, rows first + for (int row = 0; row < Parameters.getRows(); row++) { + for (int column = 0; column < Parameters.getColumns(); column++) { + // look at each connection + for (int connection = 0; connection < Parameters.getMaxArity(); connection++) { + if (c.getNode(row, column).getConnection(connection) instanceof Input && + oc.getNode(row, column).getConnection(connection) instanceof Input) { + + assertTrue("Nodes did not connect to equivalent inputs.", + ((Input) c.getNode(row, column).getConnection(connection)).getIndex() == + ((Input) oc.getNode(row, column).getConnection(connection)).getIndex()); + + } else if (c.getNode(row, column).getConnection(connection) instanceof Node && + oc.getNode(row, column).getConnection(connection) instanceof Node) { + + assertTrue("Nodes did not connect to equivalent nodes.", + ((Node) c.getNode(row, column).getConnection(connection)).getRow() == + ((Node) oc.getNode(row, column).getConnection(connection)).getRow() && + + ((Node) c.getNode(row, column).getConnection(connection)).getColumn() == + ((Node) oc.getNode(row, column).getConnection(connection)).getColumn()); + + } else { + fail("Connection types did not match."); + } + } + } + } + // change clone inputs, outputs should no longer match testInputs = new int[Parameters.getInputs()]; diff --git a/src/jcgp/tests/PopulationTests.java b/src/jcgp/tests/PopulationTests.java index 16a8d89..a8f55a2 100644 --- a/src/jcgp/tests/PopulationTests.java +++ b/src/jcgp/tests/PopulationTests.java @@ -2,6 +2,7 @@ package jcgp.tests; import static org.junit.Assert.*; +import java.util.Iterator; import java.util.Random; import jcgp.Parameters; @@ -10,6 +11,8 @@ import jcgp.function.Addition; import jcgp.function.FunctionSet; import jcgp.function.Subtraction; import jcgp.population.Chromosome; +import jcgp.population.Input; +import jcgp.population.Node; import jcgp.population.Population; import org.junit.Before; @@ -21,19 +24,20 @@ import org.junit.Test; * Tests which cover the behaviour specified for a population. * * - A population is a collection of chromosomes. It should be Iterable - * so the chromosomes can be accessed. Chromosomes should never be removed - * via the iterator. + * so the chromosomes can be accessed. + * - Iterator.remove() should generate an UnsupportedOperationException + * since chromosomes may not be removed. * - When constructed with no arguments, it should generate populationSize * random chromosomes. - * - If an array of chromosomes is passed as an argument to the constructor, - * it should use those chromosomes as the population. + * - If a chromosome is passed as an argument to the constructor, it should + * create a population of copies of that chromosome. * * * @author Eduardo Pedroni * */ public class PopulationTests { - + private Population population; @BeforeClass @@ -66,29 +70,107 @@ public class PopulationTests { public void iterableTest() { // check that Population is really Iterable assertTrue("Population must implement Iterable.", population instanceof Iterable); - + // iterate through, check that different chromosomes are returned and no chromosome can be removed Chromosome comparison = null; int iterationCount = 0; + boolean exceptionThrown = false; + for (Chromosome chromosome : population) { iterationCount++; assertTrue("Same chromosome returned twice.", comparison != chromosome); comparison = chromosome; - population.iterator().remove(); - assertTrue("Chromosome removed.", comparison == chromosome); + + try { + population.iterator().remove(); + } catch (UnsupportedOperationException e) { + exceptionThrown = true; + } + assertTrue("Chromosome removed.", exceptionThrown); + exceptionThrown = false; } // check that all chromosomes were iterated through - assertTrue("Not enough itearations occurred.", iterationCount == Parameters.getPopulationSize()); + assertTrue("Number of elements in population does not match specified parameter size.", + iterationCount == Parameters.getPopulationSize()); } - + @Test - public void contentsTest() { + public void defaultPopulationTest() { // check that the constructor really generates populationSize chromosomes when none is given int populationCount = 0; - for (Chromosome chromosome : population) { + for (Iterator iterator = population.iterator(); iterator.hasNext();) { populationCount++; + iterator.next(); } assertTrue("Incorrect number of chromosomes generated.", populationCount == Parameters.getPopulationSize()); } + @Test + public void preinitialisedChromosomeTest() { + // the original chromosome that will be cloned + Chromosome oc = new Chromosome(); + + // initialise a population with copies of it + population = new Population(oc); + // check that the chromosomes returned are identical to the one given + int index = 0; + for (Chromosome c : population) { + assertTrue("Incorrect chromosome in population.", c != oc); + index++; + } + // check that the right number of copies was made + assertTrue("Wrong number of chromosomes in population.", index == Parameters.getPopulationSize()); + + // check that the copies are exact copies + for (Chromosome c : population) { + // check outputs + for (int o = 0; o < Parameters.getOutputs(); o++) { + // check that no cross-references exist between chromosomes + assertTrue("Cloned chromosome contained a reference to a member of the original chromosome.", + c.getOutput(o) != oc.getOutput(o) && + c.getOutput(o).getSource() != oc.getOutput(o).getSource()); + // check that the connections are equivalent + if (c.getOutput(o).getSource() instanceof Input && oc.getOutput(o).getSource() instanceof Input) { + assertTrue("Outputs did not connect to equivalent inputs.", + ((Input) c.getOutput(o).getSource()).getIndex() == ((Input) oc.getOutput(o).getSource()).getIndex()); + } else if (c.getOutput(o).getSource() instanceof Node && oc.getOutput(o).getSource() instanceof Node) { + assertTrue("Outputs did not connect to equivalent nodes.", + ((Node) c.getOutput(o).getSource()).getRow() == ((Node) oc.getOutput(o).getSource()).getRow() && + ((Node) c.getOutput(o).getSource()).getColumn() == ((Node) oc.getOutput(o).getSource()).getColumn()); + } else { + fail("Output source types did not match."); + } + } + // check nodes, rows first + for (int row = 0; row < Parameters.getRows(); row++) { + for (int column = 0; column < Parameters.getColumns(); column++) { + // look at each connection + for (int connection = 0; connection < Parameters.getMaxArity(); connection++) { + if (c.getNode(row, column).getConnection(connection) instanceof Input && + oc.getNode(row, column).getConnection(connection) instanceof Input) { + + assertTrue("Nodes did not connect to equivalent inputs.", + ((Input) c.getNode(row, column).getConnection(connection)).getIndex() == + ((Input) oc.getNode(row, column).getConnection(connection)).getIndex()); + + } else if (c.getNode(row, column).getConnection(connection) instanceof Node && + oc.getNode(row, column).getConnection(connection) instanceof Node) { + + assertTrue("Nodes did not connect to equivalent nodes.", + ((Node) c.getNode(row, column).getConnection(connection)).getRow() == + ((Node) oc.getNode(row, column).getConnection(connection)).getRow() && + + ((Node) c.getNode(row, column).getConnection(connection)).getColumn() == + ((Node) oc.getNode(row, column).getConnection(connection)).getColumn()); + + } else { + fail("Connection types did not match."); + } + } + } + } + } + + } + } -- cgit v1.2.3