/* * This file is part of JGAP. * * JGAP offers a dual license model containing the LGPL as well as the MPL. * * For licensing information please see the file license.txt included with JGAP * or have a look at the top of class org.jgap.Chromosome which representatively * includes the JGAP license policy applicable for any file delivered with JGAP. */ package org.jgap.impl; import org.jgap.*; import junit.framework.*; /** * Tests for the BulkFitnessOffsetRemover class. * * @author Achim Westermann * @since 2.2 */ public class BulkFitnessOffsetRemoverTest extends JGAPTestCase { /** String containing the CVS revision. Read out via reflection! */ private final static String CVS_REVISION = "$Revision: 1.12 $"; // A plainforward implementation for this test. //--------------------------------------------- private final transient FitnessFunction m_fitnessFunction = new DummyFitnessFunction(); // The instance that is tested. //----------------------------- private final transient BulkFitnessFunction m_bulkFitnessFunction = new BulkFitnessOffsetRemover(m_fitnessFunction); public static Test suite() { TestSuite suite = new TestSuite(BulkFitnessOffsetRemoverTest.class); return suite; } /** * Test the inner class DummyFitnessFunction that is needed for this test with * IntegerGenes in a Chromosome. * * @throws Exception */ public void testDummyFitnessFunction_0() throws Exception { // setting up a Chromosome and assign values: //------------------------------------------- NumberGene[] genes = { new IntegerGene(conf), new IntegerGene(conf), new IntegerGene(conf)}; Number[] values = { new Integer(100), new Integer(200), new Integer(300)}; for (int i = 0; i < genes.length; i++) { genes[i].setAllele(values[i]); } Chromosome chromosome = new Chromosome(conf, genes); // Using the DummyFitnessFunction: //-------------------------------- assertNotNull(m_fitnessFunction); double fitness = m_fitnessFunction.getFitnessValue(chromosome); assertEquals( (double) (100 + 200 + 300), fitness, 0.0); } /** * Test the inner class DummyFitnessFunction that is needed for this test with * a mix of IntegerGenes and DoubleGenes in a Chromosome. * * @throws Exception */ public void testDummyFitnessFunction_1() throws Exception { // setting up a Chromosome and assign values: //------------------------------------------- NumberGene[] genes = { new IntegerGene(conf), new DoubleGene(conf), new DoubleGene(conf)}; Number[] values = { new Integer(100), new Double(2000.25), new Double(0.75e11)}; for (int i = 0; i < genes.length; i++) { genes[i].setAllele(values[i]); } Chromosome chromosome = new Chromosome(conf, genes); // Using the DummyFitnessFunction: //-------------------------------- assertNotNull(m_fitnessFunction); double fitness = m_fitnessFunction.getFitnessValue(chromosome); assertEquals( (double) (100 + 2000.25 + 0.75e11), fitness, 0.0); } public void testConstructor_0() { assertNotNull(m_fitnessFunction); new BulkFitnessOffsetRemover(m_fitnessFunction); } public void testConstructor_1() { try { BulkFitnessOffsetRemover test = new BulkFitnessOffsetRemover(null); fail("The constructor of " + test.getClass().getName() + " allows a null value!"); } catch (Throwable f) { ; //this is OK } } /** * Tests the method BulkFitnessOffsetRemover.evaluate(java.util.List) with a * list of two Chromosomes with each one IntegerGene with the allele 100. * * @author Achim Westermann * @since 2.2 * @throws Exception */ public void testEvaluate_0() throws Exception { assertNotNull(m_fitnessFunction); assertNotNull(m_bulkFitnessFunction); // setting up two Chromosomes and assign values: //-------------------------------------------------- Gene g100A = new IntegerGene(conf); g100A.setAllele(new Integer(100)); Gene g100B = new IntegerGene(conf); g100B.setAllele(new Integer(100)); Chromosome c100A = new Chromosome(conf, new Gene[] {g100A}); Chromosome c100B = new Chromosome(conf, new Gene[] {g100B}); // Running the evaluate method. // It will remove the common offset 100 and add 1. //------------------------------------------------- Population chromosomeList = new Population(conf); chromosomeList.addChromosome(c100A); chromosomeList.addChromosome(c100B); m_bulkFitnessFunction.evaluate(chromosomeList); // The offset should have been removed: //------------------------------------- assertEquals(1.0, c100A.getFitnessValue(), 0d); assertEquals(1.0, c100B.getFitnessValue(), 0d); } /** * Tests the method BulkFitnessOffsetRemover.evaluate(List) with a list of two * Chromosomes with one IntegerGene with the allele 100. The IntegerGene is * the same instance in both Chromosomes. * * @author Achim Westermann * @since 2.2 * @throws Exception */ public void testEvaluate_1() throws Exception { assertNotNull(m_fitnessFunction); assertNotNull(m_bulkFitnessFunction); // setting up two Chromosomes and assign values: //-------------------------------------------------- Gene G100 = new IntegerGene(conf); G100.setAllele(new Integer(100)); Chromosome C100A = new Chromosome(conf, new Gene[] {G100}); Chromosome C100B = new Chromosome(conf, new Gene[] {G100}); // Running the evaluate method. // It will remove the common offset 100 and add 1. //------------------------------------------------- Population chromosomeList = new Population(conf); chromosomeList.addChromosome(C100A); chromosomeList.addChromosome(C100B); m_bulkFitnessFunction.evaluate(chromosomeList); // The offset should have been removed: //------------------------------------- assertEquals(1.0, C100A.getFitnessValue(), 0d); assertEquals(1.0, C100B.getFitnessValue(), 0d); } /** * Tests the method BulkFitnessOffsetRemover.evaluate(List) with a list of two * Chromosomes with each one IntegerGene with the allele 200. The Chromosomes * ar the same instance in the List that is evaluated. * * @author Achim Westermann * @since 2.2 * @throws Exception */ public void testEvaluate_2() throws Exception { assertNotNull(m_fitnessFunction); assertNotNull(m_bulkFitnessFunction); // setting up two Chromosomes and assign values: //-------------------------------------------------- Gene G200 = new IntegerGene(conf); G200.setAllele(new Integer(200)); Chromosome C200 = new Chromosome(conf, new Gene[] {G200}); // Running the evaluate method. // It will remove the common offset 100 and add 1. //------------------------------------------------- Population chromosomeList = new Population(conf); chromosomeList.addChromosome(C200); chromosomeList.addChromosome(C200); m_bulkFitnessFunction.evaluate(chromosomeList); // The offset should have been removed: //------------------------------------- assertEquals(1.0, C200.getFitnessValue(), 0d); } /** * Tests the method BulkFitnessOffsetRemover.evaluate(List) with a list of two * Chromosomes with each two NumberGenes. <pre> * chromosomeA * / \ * IntegerGene DoubleGene => Fitness 4100.15 * | | * 100 4000.15 * chromosomeB * / \ * IntegerGene DoubleGene =>; Fitness 1234 + 14e-5 * | | * 1234 14e-5 * </pre> * * @author Achim Westermann * @since 2.2 * @throws Exception */ public void testEvaluate_3() throws Exception { assertNotNull(m_fitnessFunction); assertNotNull(m_bulkFitnessFunction); // setting up a two Chromosome instances and assign values: //--------------------------------------------------------- NumberGene[] genesA = { new IntegerGene(conf), new DoubleGene(conf)}; Number[] valuesA = { new Integer(100), new Double(4000.15)}; for (int i = 0; i < genesA.length; i++) { genesA[i].setAllele(valuesA[i]); } Chromosome chromosomeA = new Chromosome(conf, new Gene[] { genesA[0], genesA[1]}); NumberGene[] genesB = { new IntegerGene(conf), new DoubleGene(conf)}; Number[] valuesB = { new Integer(1234), new Double(14.e-5)}; for (int i = 0; i < genesA.length; i++) { genesB[i].setAllele(valuesB[i]); } Chromosome chromosomeB = new Chromosome(conf, new Gene[] { genesB[0], genesB[1]}); // Calculation of the estimated result: //-------------------------------------- double offset = Math.min( ( (IntegerGene) genesA[0]).intValue() + ( (DoubleGene) genesA[1]).doubleValue(), ( (IntegerGene) genesB[0]).intValue() + ( (DoubleGene) genesB[1]).doubleValue()); double estimateFitnessA = ( (IntegerGene) genesA[0]).intValue() + ( (DoubleGene) genesA[1]).doubleValue() - offset + 1d; double estimateFitnessB = ( (IntegerGene) genesB[0]).intValue() + ( (DoubleGene) genesB[1]).doubleValue() - offset + 1d; // Running the evaluate method. // It will remove the common offset. //------------------------------------------------- Population chromosomeList = new Population(conf); chromosomeList.addChromosome(chromosomeA); chromosomeList.addChromosome(chromosomeB); m_bulkFitnessFunction.evaluate(chromosomeList); // The offset should have been removed: //------------------------------------- assertEquals(estimateFitnessA, chromosomeA.getFitnessValue(), 0d); assertEquals(estimateFitnessB, chromosomeB.getFitnessValue(), 0d); } /** * * @author Klaus Meffert * @since 2.2 * @throws Exception */ public void testGetAbsoluteFitness_0() throws Exception { BulkFitnessOffsetRemover remover = new BulkFitnessOffsetRemover( new StaticFitnessFunction(33.345d)); NumberGene[] genes = { new IntegerGene(conf), new IntegerGene(conf), new IntegerGene(conf)}; Number[] values = { new Integer(100), new Integer(200), new Integer(300)}; for (int i = 0; i < genes.length; i++) { genes[i].setAllele(values[i]); } Chromosome chrom = new Chromosome(conf, genes); double fitness = remover.getAbsoluteFitness(chrom); assertEquals(33.345d, chrom.getFitnessValue(), DELTA); assertEquals(33.345d, fitness, DELTA); fitness = remover.getAbsoluteFitness(chrom); assertEquals(33.345d, chrom.getFitnessValue(), DELTA); assertEquals(33.345d, fitness, DELTA); } /** * <p> * This class is a helper to allow testing class * {@link BulkFitnessOffsetRemover}in a plainforward way: It only works * with {@link NumberGene}instances and returns the addition of their * primitive values as the fitness value. This way we can configure a * Chromosome with numerical value genes knowing their fitness and see what * fitness values should be installed by the method * {@link BulkFitnessOffsetRemover}. * </p> * <p> * Do not copy or use this implementation it is for this test only. It is * tested itself by the outer class ({@link #testDummyFitnessFunction()}) * to ensure valid test results. * </p> * * @author Achim Westermann * @since 2.2 */ private class DummyFitnessFunction extends FitnessFunction { /** * Casts every Gene to the subtype of NumberGene and calculates the sum * of the numerical values obtained. * * @param a_subject the Chromosome to be evaluated * @return the sum of all numerical values of the Genes within the * given Chromosome that only consists of NumberGene instances * @throws ClassCastException if a Gene within the Chromosome is not derived * from {@link NumberGene} * * @see org.jgap.FitnessFunction#evaluate(org.jgap.Chromosome) */ protected double evaluate(IChromosome a_subject) { double ret = 0d; Gene[] genes = a_subject.getGenes(); for (int i = genes.length - 1; i > -1; i--) { if (genes[i] instanceof DoubleGene) { ret += ( (DoubleGene) genes[i]).doubleValue(); } else if (genes[i] instanceof IntegerGene) { ret += ( (IntegerGene) genes[i]).intValue(); } else { throw new ClassCastException( "The FitnessFunction " + getClass().getName() + " is for testing purposes only and only handles DoubleGene " + "and NumberGene instances (used: " + genes[i].getClass().getName() + ")"); } } return ret; } } }