diff options
Diffstat (limited to 'src')
23 files changed, 246 insertions, 196 deletions
diff --git a/src/jcgp/CGP.java b/src/jcgp/CGP.java index d2be161..0ccd74e 100644 --- a/src/jcgp/CGP.java +++ b/src/jcgp/CGP.java @@ -1,6 +1,7 @@  package jcgp;  import java.util.Random; +  import jcgp.ea.EvolutionaryAlgorithm;  import jcgp.ea.Mutator;  import jcgp.ea.StandardEA; @@ -10,6 +11,7 @@ import jcgp.fitness.TestCase;  import jcgp.fitness.TruthTableEvaluator;  import jcgp.function.Addition;  import jcgp.function.FunctionSet; +import jcgp.function.Multiplication;  import jcgp.function.Subtraction;  import jcgp.population.Population; @@ -28,9 +30,10 @@ public final class CGP {  			Parameters.setCurrentGeneration(i);  			fitnessFunction.evaluate(population);  			ea.evolve(population, mutator); -		} -		 -		 +			if (ea.getBestFitness() >= 3) { +				break; +			} +		}	  	}  	/** @@ -38,19 +41,20 @@ public final class CGP {  	 */  	private void initialise() {  		// initialise function set -		FunctionSet functionSet = new FunctionSet(new Addition(), new Subtraction()); +		FunctionSet functionSet = new FunctionSet(new Addition(), new Subtraction(), new Multiplication());  		// initialise utilities  		Utilities.setResources(new Random(1234), functionSet);  		// initialise parameters  		Parameters.setColumns(3); -		Parameters.setRows(3); +		Parameters.setRows(6);  		Parameters.setInputs(3);  		Parameters.setOutputs(3); -		Parameters.setLevelsBack(1); +		Parameters.setLevelsBack(3); +		Parameters.setPopulationSize(1, 4);  		Parameters.setMutationRate(10); -		Parameters.setTotalGenerations(100); +		Parameters.setTotalGenerations(5000);  		Parameters.setTotalRuns(5);  		Parameters.setMaxArity(functionSet.getMaxArity()); diff --git a/src/jcgp/Main.java b/src/jcgp/Main.java index 598c720..97b5c4a 100644 --- a/src/jcgp/Main.java +++ b/src/jcgp/Main.java @@ -1,10 +1,10 @@  package jcgp;  public class Main { - +	  	public static void main(String[] args) {  		CGP cgp = new CGP();  		cgp.getClass(); +			  	} -  } diff --git a/src/jcgp/Parameters.java b/src/jcgp/Parameters.java index 26eb61c..0a6abd9 100644 --- a/src/jcgp/Parameters.java +++ b/src/jcgp/Parameters.java @@ -2,11 +2,12 @@ package jcgp;  public class Parameters { -	private static int rows, columns, inputs, outputs, levelsBack,  -					   mutationRate, populationSize, totalGenerations, -					   currentGeneration = 0, totalRuns, currentRun = 0, -					   maxArity, maxFitness; +	private static int rows = 0, columns = 0, inputs = 0, outputs = 0, levelsBack = 0,  +					   mutationRate = 0, totalGenerations = 0, parents = 0, offspring = 0, +					   currentGeneration = 0, totalRuns = 0, currentRun = 0, +					   maxArity = 0, maxFitness = 0; +	  	public static int getRows() {  		return rows;  	} @@ -36,9 +37,17 @@ public class Parameters {  	}  	public static int getPopulationSize() { -		return populationSize; +		return offspring + parents;  	} - +	 +	public static int getOffspringCount() { +		return offspring; +	} +	 +	public static int getParentCount() { +		return parents; +	} +	  	public static int getTotalGenerations() {  		return totalGenerations;  	} @@ -87,8 +96,17 @@ public class Parameters {  		Parameters.mutationRate = mutationRate;  	} -	public static void setPopulationSize(int populationSize) { -		Parameters.populationSize = populationSize; +	public static void setPopulationSize(int parents, int offspring) { +		Parameters.parents = parents; +		Parameters.offspring = offspring; +	} +	 +	public static void setOffspringCount(int offspring) { +		Parameters.offspring = offspring; +	} +	 +	public static void setParentCount(int parents) { +		Parameters.parents = parents;  	}  	public static void setTotalGenerations(int totalGenerations) { diff --git a/src/jcgp/ea/EvolutionaryAlgorithm.java b/src/jcgp/ea/EvolutionaryAlgorithm.java index 9e72a1b..e084da0 100644 --- a/src/jcgp/ea/EvolutionaryAlgorithm.java +++ b/src/jcgp/ea/EvolutionaryAlgorithm.java @@ -4,12 +4,8 @@ import jcgp.population.Population;  public interface EvolutionaryAlgorithm { -//	protected Mutator mutator; -//	 -//	public EvolutionaryAlgorithm(Mutator mutator) { -//		this.mutator = mutator; -//	} -	  	public abstract void evolve(Population population, Mutator mutator); +	public abstract int getBestFitness(); +  } diff --git a/src/jcgp/ea/StandardEA.java b/src/jcgp/ea/StandardEA.java index b34c421..901333b 100644 --- a/src/jcgp/ea/StandardEA.java +++ b/src/jcgp/ea/StandardEA.java @@ -1,18 +1,45 @@  package jcgp.ea; +import jcgp.Parameters;  import jcgp.population.Chromosome;  import jcgp.population.Population; +/** + * (1 + λ) EA. + *  + *  + * @author Eduardo Pedroni + * + */  public class StandardEA implements EvolutionaryAlgorithm { +	 +	private int bestFitness = 0;  	@Override -	public void evolve(Population population, Mutator mutator) {	 -		Chromosome select; -		for (Chromosome chromosome : population) { -			 -			 -			mutator.mutate(chromosome); +	public void evolve(Population population, Mutator mutator) { +		// select fittest chromosome +		int fittest = 0; +		 +		for (int i = 1; i < Parameters.getPopulationSize(); i++) { +			if (population.getChromosome(i).getFitness() >= population.getChromosome(fittest).getFitness()) { +				fittest = i; +			} +		} +		bestFitness = population.getChromosome(fittest).getFitness(); +		population.setBestIndividual(fittest); +		System.out.println("Best fitness: " + bestFitness); +		// create copies of fittest chromosome, mutate them +		Chromosome fc = population.getChromosome(fittest); +		for (int i = 0; i < Parameters.getPopulationSize(); i++) { +			if (i != fittest) { +				population.getChromosome(i).copyConnections(fc); +				mutator.mutate(population.getChromosome(i)); +			}  		}  	} - +	 +	@Override +	public int getBestFitness() { +		return bestFitness; +	}  } diff --git a/src/jcgp/ea/StandardMutator.java b/src/jcgp/ea/StandardMutator.java index 447338a..b9c0a4e 100644 --- a/src/jcgp/ea/StandardMutator.java +++ b/src/jcgp/ea/StandardMutator.java @@ -11,7 +11,7 @@ public class StandardMutator implements Mutator {  	@Override  	public void mutate(Chromosome chromosome) { -		int mutations = (int) (Parameters.getMutationRate() * ((double) Parameters.getNodeCount() / 100)); +		int mutations = (int) (Parameters.getMutationRate() * (((double) Parameters.getNodeCount() + Parameters.getOutputs()) / 100));  		for (int i = 0; i < mutations; i++) {  			MutableElement m = chromosome.getRandomMutableElement(); diff --git a/src/jcgp/population/InsufficientConnectionsException.java b/src/jcgp/exceptions/InsufficientConnectionsException.java index 807ec53..2ffc10f 100644 --- a/src/jcgp/population/InsufficientConnectionsException.java +++ b/src/jcgp/exceptions/InsufficientConnectionsException.java @@ -1,4 +1,4 @@ -package jcgp.population; +package jcgp.exceptions;  public class InsufficientConnectionsException extends RuntimeException { diff --git a/src/jcgp/function/InvalidArgumentsException.java b/src/jcgp/exceptions/InvalidArgumentsException.java index cf55937..537018d 100644 --- a/src/jcgp/function/InvalidArgumentsException.java +++ b/src/jcgp/exceptions/InvalidArgumentsException.java @@ -1,4 +1,4 @@ -package jcgp.function; +package jcgp.exceptions;  public class InvalidArgumentsException extends RuntimeException { diff --git a/src/jcgp/fitness/ParameterMismatchException.java b/src/jcgp/exceptions/ParameterMismatchException.java index 0ca69a7..93a8f10 100644 --- a/src/jcgp/fitness/ParameterMismatchException.java +++ b/src/jcgp/exceptions/ParameterMismatchException.java @@ -1,4 +1,4 @@ -package jcgp.fitness; +package jcgp.exceptions;  public class ParameterMismatchException extends RuntimeException { diff --git a/src/jcgp/fitness/TestCase.java b/src/jcgp/fitness/TestCase.java index 4c10de7..e506d38 100644 --- a/src/jcgp/fitness/TestCase.java +++ b/src/jcgp/fitness/TestCase.java @@ -1,6 +1,7 @@  package jcgp.fitness;  import jcgp.Parameters; +import jcgp.exceptions.ParameterMismatchException;  public class TestCase { diff --git a/src/jcgp/fitness/TruthTableEvaluator.java b/src/jcgp/fitness/TruthTableEvaluator.java index 4c26d60..2281b3f 100644 --- a/src/jcgp/fitness/TruthTableEvaluator.java +++ b/src/jcgp/fitness/TruthTableEvaluator.java @@ -2,26 +2,27 @@ package jcgp.fitness;  import jcgp.Parameters;  import jcgp.TruthTable; -import jcgp.population.Chromosome;  import jcgp.population.Population;  public class TruthTableEvaluator implements FitnessFunction {  	@Override  	public void evaluate(Population population) { -		for (Chromosome chromosome : population) { +		// for every chromosome in the population +		for (int i = 0; i < Parameters.getPopulationSize(); i++) { +			int fitness = 0; +			// for every test case  			for (int t = 0; t < TruthTable.getTestCaseCount(); t++) { -				chromosome.setInputs(TruthTable.getTestCase(t).getInputs()); -				int fitness = 0; +				population.getChromosome(i).setInputs(TruthTable.getTestCase(t).getInputs()); +				// check every output  				for (int o = 0; o < Parameters.getOutputs(); o++) { -					if (chromosome.getOutput(o).calculate() == TruthTable.getTestCase(t).getOutput(o)) { +					if (population.getChromosome(i).getOutput(o).calculate() == TruthTable.getTestCase(t).getOutput(o)) {  						fitness++;  					}  				} -				chromosome.setFitness(fitness); -				System.out.println("Fitness: " + fitness);  			} +			population.getChromosome(i).setFitness(fitness); +			System.out.println("active nodes: " + population.getChromosome(i).getActiveNodes().size());  		}  	} -  } diff --git a/src/jcgp/function/Addition.java b/src/jcgp/function/Addition.java index f40bc24..3a8f123 100644 --- a/src/jcgp/function/Addition.java +++ b/src/jcgp/function/Addition.java @@ -1,5 +1,6 @@  package jcgp.function; +import jcgp.exceptions.InvalidArgumentsException;  import jcgp.population.Connection;  public class Addition extends Function { @@ -11,7 +12,12 @@ public class Addition extends Function {  		if (connections.length < arity) {  			throw new InvalidArgumentsException("Not enough connections were given.");  		} else if (connections[0].getValue() instanceof Integer) { -			return ((Integer) connections[0].getValue()) + ((Integer) connections[1].getValue()); +			Integer arg1 = ((Integer) connections[0].getValue()); +			Integer arg2 = ((Integer) connections[1].getValue()); +			Integer result = arg1 + arg2; +			 +			System.out.println(arg1 + " + " + arg2 + " = " + result); +			return result;  		} else {  			throw new InvalidArgumentsException("Wrong data type, this function takes Integer.");  		} diff --git a/src/jcgp/function/Function.java b/src/jcgp/function/Function.java index 118131a..584421a 100644 --- a/src/jcgp/function/Function.java +++ b/src/jcgp/function/Function.java @@ -1,11 +1,11 @@  package jcgp.function; +import jcgp.exceptions.InvalidArgumentsException;  import jcgp.population.Connection; -import jcgp.population.InsufficientConnectionsException;  public abstract class Function { -	public abstract Object run(Connection ... connections) throws InsufficientConnectionsException; +	public abstract Object run(Connection ... connections) throws InvalidArgumentsException;  	public abstract int getArity(); diff --git a/src/jcgp/function/Multiplication.java b/src/jcgp/function/Multiplication.java new file mode 100644 index 0000000..986faa8 --- /dev/null +++ b/src/jcgp/function/Multiplication.java @@ -0,0 +1,31 @@ +package jcgp.function; + +import jcgp.exceptions.InvalidArgumentsException; +import jcgp.population.Connection; + +public class Multiplication extends Function { + +	private int arity = 2; + +	@Override +	public Object run(Connection... connections) { +		if (connections.length < arity) { +			throw new InvalidArgumentsException("Not enough connections were given."); +		} else if (connections[0].getValue() instanceof Integer) { +			Integer arg1 = ((Integer) connections[0].getValue()); +			Integer arg2 = ((Integer) connections[1].getValue()); +			Integer result = arg1 * arg2; +			 +			System.out.println(arg1 + " * " + arg2 + " = " + result); +			return result; +		} else { +			throw new InvalidArgumentsException("Wrong data type, this function takes Integer."); +		} +	} + +	@Override +	public int getArity() { +		return arity; +	} + +} diff --git a/src/jcgp/function/Subtraction.java b/src/jcgp/function/Subtraction.java index d785614..cfbb907 100644 --- a/src/jcgp/function/Subtraction.java +++ b/src/jcgp/function/Subtraction.java @@ -1,5 +1,6 @@  package jcgp.function; +import jcgp.exceptions.InvalidArgumentsException;  import jcgp.population.Connection;  public class Subtraction extends Function { @@ -11,7 +12,12 @@ public class Subtraction extends Function {  		if (connections.length < arity) {  			throw new InvalidArgumentsException("Not enough connections were given.");  		} else if (connections[0].getValue() instanceof Integer) { -			return ((Integer) connections[0].getValue()) - ((Integer) connections[1].getValue()); +			Integer arg1 = ((Integer) connections[0].getValue()); +			Integer arg2 = ((Integer) connections[1].getValue()); +			Integer result = arg1 - arg2; +			 +			System.out.println(arg1 + " - " + arg2 + " = " + result); +			return result;  		} else {  			throw new InvalidArgumentsException("Wrong data type, this function takes Integer.");  		} diff --git a/src/jcgp/population/Chromosome.java b/src/jcgp/population/Chromosome.java index 12a8978..3e61a10 100644 --- a/src/jcgp/population/Chromosome.java +++ b/src/jcgp/population/Chromosome.java @@ -4,7 +4,7 @@ import java.util.ArrayList;  import jcgp.Parameters;  import jcgp.Utilities; -import jcgp.fitness.ParameterMismatchException; +import jcgp.exceptions.ParameterMismatchException;  public class Chromosome { @@ -95,7 +95,7 @@ public class Chromosome {  	/**  	 * @param clone  	 */ -	private void copyConnections(Chromosome clone) { +	public void copyConnections(Chromosome clone) {  		// copy nodes - [rows][columns]  		for (int r = 0; r < nodes.length; r++) {  			for (int c = 0; c < nodes[r].length; c++) { diff --git a/src/jcgp/population/Connection.java b/src/jcgp/population/Connection.java index ff11d7c..751fe10 100644 --- a/src/jcgp/population/Connection.java +++ b/src/jcgp/population/Connection.java @@ -3,5 +3,6 @@ package jcgp.population;  public interface Connection {  	public Object getValue(); +	  } diff --git a/src/jcgp/population/Input.java b/src/jcgp/population/Input.java index 2154dd9..e793bf6 100644 --- a/src/jcgp/population/Input.java +++ b/src/jcgp/population/Input.java @@ -21,5 +21,4 @@ public class Input implements Connection {  	public int getIndex() {  		return index;  	} -  } diff --git a/src/jcgp/population/Node.java b/src/jcgp/population/Node.java index e58c1a4..35d33cb 100644 --- a/src/jcgp/population/Node.java +++ b/src/jcgp/population/Node.java @@ -5,6 +5,7 @@ import java.util.Arrays;  import jcgp.Parameters;  import jcgp.Utilities; +import jcgp.exceptions.InsufficientConnectionsException;  import jcgp.function.Function; diff --git a/src/jcgp/population/Output.java b/src/jcgp/population/Output.java index dae7278..b3ce74f 100644 --- a/src/jcgp/population/Output.java +++ b/src/jcgp/population/Output.java @@ -14,7 +14,9 @@ public class Output implements MutableElement {  	}  	public Object calculate() { -		return source.getValue(); +		Object result = source.getValue(); +		System.out.println("Output " + index + ": " + result); +		return result;  	}  	@Override diff --git a/src/jcgp/population/Population.java b/src/jcgp/population/Population.java index 4153e0f..9cd7430 100644 --- a/src/jcgp/population/Population.java +++ b/src/jcgp/population/Population.java @@ -1,54 +1,72 @@  package jcgp.population; -import java.util.Iterator; -  import jcgp.Parameters; -public class Population implements Iterable<Chromosome> { +public class Population { -	private Chromosome[] population; +	private Chromosome[] parents; +	private Chromosome[] offspring; +	private Chromosome bestIndividual; -	public Population(Chromosome chromosome) { -		population = new Chromosome[Parameters.getPopulationSize()]; -		for (int c = 0; c < population.length; c++) { -			population[c] = new Chromosome(chromosome); +	public Population(Chromosome parent) { +		parents = new Chromosome[Parameters.getParentCount()]; +		// make a clone for safety +		this.parents[0] = new Chromosome(parent); +		// generate the rest of parents +		for (int c = 1; c < parents.length; c++) { +			parents[c] = new Chromosome(); +		} +		 +		offspring = new Chromosome[Parameters.getOffspringCount()]; +		for (int c = 0; c < offspring.length; c++) { +			// completely random offspring? depending on EA, this means the given parent won't be selected +			offspring[c] = new Chromosome();  		}  	}  	public Population() { -		population = new Chromosome[Parameters.getPopulationSize()]; -		for (int c = 0; c < population.length; c++) { -			population[c] = new Chromosome(); +		parents = new Chromosome[Parameters.getParentCount()]; +		for (int c = 0; c < parents.length; c++) { +			parents[c] = new Chromosome();  		} -	} - -	@Override -	public Iterator<Chromosome> iterator() { -		return new Iterator<Chromosome>() { -			 -			private int index = 0; - -			@Override -			public boolean hasNext() { -				if (index < population.length) { -					return true; -				} else { -					return false; -				} -			} -			@Override -			public Chromosome next() { -				Chromosome next = population[index]; -				index++; -				return next; -			} +		offspring = new Chromosome[Parameters.getOffspringCount()]; +		for (int c = 0; c < offspring.length; c++) { +			offspring[c] = new Chromosome(); +		} +	} -			@Override -			public void remove() { -				// not allowed -				throw new UnsupportedOperationException("Removing chromosomes from the population is not allowed. Instead, re-instantiate the chromosome."); -			} -		}; +	public Chromosome getOffspring(int index) { +		return offspring[index]; +	} +	 +	public Chromosome getParent(int index) { +		return parents[index]; +	} +	 +	/** +	 * Returns all chromosomes, parents first, then offspring. +	 *  +	 * @param index +	 * @return +	 */ +	public Chromosome getChromosome(int index) { +		if (index < parents.length) { +			return parents[index]; +		} else { +			return offspring[index - parents.length]; +		} +	} +	 +	public void setBestIndividual(int index) { +		if (index < parents.length) { +			bestIndividual = parents[index]; +		} else { +			bestIndividual = offspring[index - parents.length]; +		} +	} +	 +	public Chromosome getBestIndividual() { +		return bestIndividual;  	}  } 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<Chromosome> 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);  	}  }  | 
