From e9290a500b228e2561a8537adbc13e86f1356747 Mon Sep 17 00:00:00 2001 From: Eduardo Pedroni Date: Sat, 15 Feb 2014 21:43:35 +0000 Subject: Population and Chromosome classes refactored so that EAs are easier to implement. --- src/jcgp/tests/ChromosomeTests.java | 12 ++- src/jcgp/tests/PopulationTests.java | 141 +++++++++++------------------------- 2 files changed, 46 insertions(+), 107 deletions(-) (limited to 'src/jcgp/tests') diff --git a/src/jcgp/tests/ChromosomeTests.java b/src/jcgp/tests/ChromosomeTests.java index 8092d60..c943da8 100644 --- a/src/jcgp/tests/ChromosomeTests.java +++ b/src/jcgp/tests/ChromosomeTests.java @@ -31,8 +31,7 @@ import org.junit.Test; * - 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 the inputs. - * - It should feature a clone constructor, which creates a deep copy of a - * specified Chromosome object. + * - It should feature a copy method, which creates a deep copy of a specified Chromosome object. * - It should be able to return a list of active nodes. * - It should contain a method to evaluate whether a given chromosome is identical * to it. @@ -65,11 +64,11 @@ public class ChromosomeTests { @Before public void setUp() throws Exception { - Parameters.setColumns(10); + Parameters.setColumns(5); Parameters.setRows(2); Parameters.setInputs(2); Parameters.setOutputs(4); - Parameters.setLevelsBack(10); + Parameters.setLevelsBack(5); chromosome = new Chromosome(); } @@ -183,10 +182,9 @@ public class ChromosomeTests { assertTrue("Connection is not an input.", connectionReturn); } - // get random connections with column 1 - // they should all be nodes, and their columns should be within range + // get random connections with the last column as reference, check that they're all within range int connectionNodes = 0, connectionOutOfRange = 0, connectionInputs = 0, connectionPicks = 100000; - int chosenColumn = 1; + int chosenColumn = Parameters.getColumns() - 1; for (int i = 0; i < connectionPicks; i++) { Connection c = chromosome.getRandomConnection(chosenColumn); if (c instanceof Node) { diff --git a/src/jcgp/tests/PopulationTests.java b/src/jcgp/tests/PopulationTests.java index bb8fece..b8639bf 100644 --- a/src/jcgp/tests/PopulationTests.java +++ b/src/jcgp/tests/PopulationTests.java @@ -2,7 +2,6 @@ package jcgp.tests; import static org.junit.Assert.*; -import java.util.Iterator; import java.util.Random; import jcgp.Parameters; @@ -11,8 +10,6 @@ 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; @@ -23,14 +20,13 @@ 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. - * - Iterator.remove() should generate an UnsupportedOperationException - * since chromosomes may not be removed. + * - A population should be able to return parents and offspring separately. + * - It should be possible to iterate through all the chromosomes in a population + * with one indexing system - parents then offspring. * - When constructed with no arguments, it should generate populationSize - * random chromosomes. - * - If a chromosome is passed as an argument to the constructor, it should - * create a population of copies of that chromosome. + * random chromosomes, distributed according to the EA parameters. + * - If one or more chromosomes are passed into the constructor, it should use them + * as parents to create the rest of the population. * * * @author Eduardo Pedroni @@ -57,7 +53,7 @@ public class PopulationTests { Parameters.setMutationRate(10); Parameters.setTotalGenerations(100); Parameters.setTotalRuns(5); - Parameters.setPopulationSize(5); + Parameters.setPopulationSize(1, 4); Parameters.setMaxArity(functionSet.getMaxArity()); } @@ -67,42 +63,43 @@ public class PopulationTests { } @Test - 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; - + public void defaultPopulationTest() { + // check that the constructor really generates populationSize chromosomes when none is given + int offspring = 0, parent = 0; + while (true) { try { - population.iterator().remove(); - } catch (UnsupportedOperationException e) { - exceptionThrown = true; + population.getOffspring(offspring); + } catch (IndexOutOfBoundsException e) { + break; } - assertTrue("Chromosome removed.", exceptionThrown); - exceptionThrown = false; + offspring++; } - // check that all chromosomes were iterated through - assertTrue("Number of elements in population does not match specified parameter size.", - iterationCount == Parameters.getPopulationSize()); + while (true) { + try { + population.getParent(parent); + } catch (IndexOutOfBoundsException e) { + break; + } + parent++; + } + assertTrue("Incorrect number of chromosomes generated.", offspring + parent == Parameters.getPopulationSize()); } - + @Test - public void defaultPopulationTest() { - // check that the constructor really generates populationSize chromosomes when none is given - int populationCount = 0; - for (Iterator iterator = population.iterator(); iterator.hasNext();) { - populationCount++; - iterator.next(); + public void offspringParentTest() { + // the first parent should not be the same as the first offspring + assertTrue("Same chromosome returned as parent and offspring", population.getOffspring(0) != population.getParent(0)); + } + + @Test + public void singleIndexTest() { + // assuming 1+4 + // the first chromosome should be the first (and only) parent + assertTrue("Incorrect chromosome returned.", population.getChromosome(0) == population.getParent(0)); + // the next 4 chromosomes should be the offspring, in order + for (int i = 0; i < Parameters.getOffspringCount(); i++) { + assertTrue("Incorrect chromosome returned.", population.getChromosome(i + 1) == population.getOffspring(i)); } - assertTrue("Incorrect number of chromosomes generated.", populationCount == Parameters.getPopulationSize()); } @Test @@ -110,65 +107,9 @@ public class PopulationTests { // the original chromosome that will be cloned Chromosome oc = new Chromosome(); - // initialise a population with copies of it + // initialise a population with a copy 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."); - } - } - } - } - } + // check that the first parent chromosome is identical to, but not the same instance as, the one given + assertTrue("Incorrect chromosome in population.", population.getParent(0).compareTo(oc) && population.getParent(0) != oc); } } -- cgit v1.2.3