com.ciphertool.zodiacengine.genetic.algorithms.BasicGeneticAlgorithmTest.java Source code

Java tutorial

Introduction

Here is the source code for com.ciphertool.zodiacengine.genetic.algorithms.BasicGeneticAlgorithmTest.java

Source

/**
 * Copyright 2012 George Belden
 * 
 * This file is part of ZodiacEngine.
 * 
 * ZodiacEngine is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * ZodiacEngine is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * ZodiacEngine. If not, see <http://www.gnu.org/licenses/>.
 */

package com.ciphertool.zodiacengine.genetic.algorithms;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;

import java.lang.reflect.InvocationTargetException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.InOrder;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import com.ciphertool.genetics.GeneticAlgorithmStrategy;
import com.ciphertool.genetics.Population;
import com.ciphertool.genetics.algorithms.BasicGeneticAlgorithm;
import com.ciphertool.genetics.algorithms.GeneticAlgorithm;
import com.ciphertool.genetics.algorithms.crossover.CrossoverAlgorithm;
import com.ciphertool.genetics.algorithms.crossover.LowestCommonGroupCrossoverAlgorithm;
import com.ciphertool.genetics.algorithms.mutation.SingleSequenceMutationAlgorithm;
import com.ciphertool.genetics.algorithms.selection.ProbabilisticSelectionAlgorithm;
import com.ciphertool.genetics.algorithms.selection.modes.RouletteSelector;
import com.ciphertool.genetics.algorithms.selection.modes.Selector;
import com.ciphertool.genetics.dao.ExecutionStatisticsDao;
import com.ciphertool.genetics.entities.Chromosome;
import com.ciphertool.genetics.util.FitnessEvaluator;
import com.ciphertool.zodiacengine.entities.Plaintext;
import com.ciphertool.zodiacengine.genetic.GeneticAlgorithmTestBase;
import com.ciphertool.zodiacengine.genetic.adapters.SolutionChromosome;
import com.ciphertool.zodiacengine.genetic.dao.PlaintextSequenceDao;
import com.ciphertool.zodiacengine.genetic.util.CipherSolutionKnownSolutionFitnessEvaluator;
import com.ciphertool.zodiacengine.genetic.util.SolutionBreeder;

public class BasicGeneticAlgorithmTest extends GeneticAlgorithmTestBase {
    @SuppressWarnings("unused")
    private static Logger log = Logger.getLogger(BasicGeneticAlgorithmTest.class);

    protected static Population population = new Population();
    protected static GeneticAlgorithm geneticAlgorithm;
    protected static SolutionBreeder solutionBreederMock = mock(SolutionBreeder.class);;

    protected static final int POPULATION_SIZE = 10;
    protected static final double SURVIVAL_RATE = 0.9;
    protected static final double MUTATION_RATE = 0.1;
    protected static final int MAX_MUTATIONS_PER_INDIVIDUAL = 5;
    protected static final double CROSSOVER_RATE = 1.0;
    protected static final int LIFESPAN = -1;
    protected static final int MAX_GENERATIONS = 2;
    protected static final int MAX_THREADS = 4;
    protected static final int THREAD_EXECUTOR_QUEUE_CAPACITY = 100;
    protected static final boolean MUTATE_DURING_CROSSOVER = true;

    @BeforeClass
    public static void setUp() {
        FitnessEvaluator fitnessEvaluator = new CipherSolutionKnownSolutionFitnessEvaluator();
        fitnessEvaluator.setGeneticStructure(zodiac408);

        CrossoverAlgorithm crossoverAlgorithm = new LowestCommonGroupCrossoverAlgorithm();
        crossoverAlgorithm.setFitnessEvaluator(fitnessEvaluator);

        SingleSequenceMutationAlgorithm mutationAlgorithm = new SingleSequenceMutationAlgorithm();
        mutationAlgorithm.setSequenceDao(new PlaintextSequenceDao());

        ProbabilisticSelectionAlgorithm selectionAlgorithm = new ProbabilisticSelectionAlgorithm();

        Selector selector = new RouletteSelector();

        GeneticAlgorithmStrategy geneticAlgorithmStrategy = new GeneticAlgorithmStrategy(zodiac408, POPULATION_SIZE,
                LIFESPAN, MAX_GENERATIONS, SURVIVAL_RATE, MUTATION_RATE, MAX_MUTATIONS_PER_INDIVIDUAL,
                CROSSOVER_RATE, MUTATE_DURING_CROSSOVER, fitnessEvaluator, crossoverAlgorithm, mutationAlgorithm,
                selectionAlgorithm, selector);

        population.setBreeder(solutionBreederMock);
        population.setSelector(selector);

        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(MAX_THREADS);
        taskExecutor.setMaxPoolSize(MAX_THREADS);
        taskExecutor.setQueueCapacity(THREAD_EXECUTOR_QUEUE_CAPACITY);
        taskExecutor.setKeepAliveSeconds(1);
        taskExecutor.setAllowCoreThreadTimeOut(true);
        taskExecutor.initialize();

        population.setTaskExecutor(taskExecutor);

        geneticAlgorithm = new BasicGeneticAlgorithm();
        geneticAlgorithm.setPopulation(population);
        geneticAlgorithm.setStrategy(geneticAlgorithmStrategy);

        ExecutionStatisticsDao executionStatisticsDaoMock = mock(ExecutionStatisticsDao.class);
        ((BasicGeneticAlgorithm) geneticAlgorithm).setExecutionStatisticsDao(executionStatisticsDaoMock);
    }

    @Before
    public void repopulate() {
        population.clearIndividuals();

        when(solutionBreederMock.breed()).thenReturn(knownSolution.clone(), knownSolution.clone(),
                knownSolution.clone(), knownSolution.clone(), knownSolution.clone(), knownSolution.clone(),
                knownSolution.clone(), knownSolution.clone(), knownSolution.clone(), knownSolution.clone(),
                knownSolution.clone(), knownSolution.clone(), knownSolution.clone(), knownSolution.clone(),
                knownSolution.clone(), knownSolution.clone(), knownSolution.clone(), knownSolution.clone(),
                knownSolution.clone(), knownSolution.clone());

        population.breed(POPULATION_SIZE);
        population.evaluateFitness(null);
    }

    @Test
    public void testSpawnInitialPopulation() {
        List<Chromosome> individualsBefore = new ArrayList<Chromosome>();
        int originalSize = population.size();
        for (int i = 0; i < originalSize; i++) {
            ((SolutionChromosome) population.getIndividuals().get(0)).setId(new BigInteger(String.valueOf(i)));
            individualsBefore.add(population.removeIndividual(0));
        }

        assertEquals(population.size(), 0);
        assertEquals(geneticAlgorithm.getPopulation().size(), 0);

        try {
            invokeMethod(geneticAlgorithm, "initialize", null, null);
        } catch (InvocationTargetException e) {
            fail(e.getMessage());
        }

        assertEquals(population.size(), POPULATION_SIZE);

        for (Chromosome individual : population.getIndividuals()) {
            // Make sure each individual has been evaluated
            assertTrue(individual.getFitness() > 0.0);

            // Make sure each individual is new
            for (Chromosome individualBefore : individualsBefore) {
                assertFalse(individual == individualBefore);
            }
        }
    }

    @Test
    public void testSelect() {
        assertEquals(population.size(), POPULATION_SIZE);

        geneticAlgorithm.select();

        assertEquals(population.size(), POPULATION_SIZE - 1);
    }

    @Test
    public void testMutate() {
        List<SolutionChromosome> clonedIndividuals = new ArrayList<SolutionChromosome>();

        for (Chromosome individual : population.getIndividuals()) {
            clonedIndividuals.add((SolutionChromosome) individual.clone());
        }

        geneticAlgorithm.mutate(population.size());
        population.resetEligibility();

        int numEqualIndividuals = 0;
        for (int i = 0; i < clonedIndividuals.size(); i++) {
            if (clonedIndividuals.get(i).equals(population.getIndividuals().get(i))) {
                numEqualIndividuals++;
            }
        }

        assertEquals(population.size(), POPULATION_SIZE + 1);
        assertEquals(numEqualIndividuals, POPULATION_SIZE);
    }

    @Test
    public void testCrossover() {
        SolutionChromosome dummySolution1 = knownSolution.clone();
        SolutionChromosome dummySolution2 = knownSolution.clone();

        for (Plaintext plaintext : dummySolution1.getPlaintextCharacters()) {
            plaintext.setValue("a");
        }

        for (Plaintext plaintext : dummySolution2.getPlaintextCharacters()) {
            plaintext.setValue("b");
        }

        population.clearIndividuals();
        population.addIndividual(dummySolution1);
        population.addIndividual(dummySolution2);

        List<SolutionChromosome> clonedIndividuals = new ArrayList<SolutionChromosome>();

        for (Chromosome individual : population.getIndividuals()) {
            clonedIndividuals.add((SolutionChromosome) individual.clone());
        }

        geneticAlgorithm.crossover(population.size());
        population.resetEligibility();

        int numEqualIndividuals = 0;
        for (Chromosome individual : population.getIndividuals()) {
            if (clonedIndividuals.contains(individual)) {
                numEqualIndividuals++;
            }
        }

        assertEquals(numEqualIndividuals, clonedIndividuals.size());
        assertEquals(population.size(), clonedIndividuals.size() + 1);
    }

    @Test
    public void testEvolve() {
        GeneticAlgorithm geneticAlgorithmSpy = spy(geneticAlgorithm);
        geneticAlgorithmSpy.evolveAutonomously();

        /*
         * Make sure the loop executes only twice and that all pertinent methods
         * are called
         */
        InOrder inOrder = inOrder(geneticAlgorithmSpy);
        inOrder.verify(geneticAlgorithmSpy, times(1)).select();
        inOrder.verify(geneticAlgorithmSpy, times(1)).crossover(anyInt());
        inOrder.verify(geneticAlgorithmSpy, times(1)).mutate(anyInt());
        inOrder.verify(geneticAlgorithmSpy, times(1)).select();
        inOrder.verify(geneticAlgorithmSpy, times(1)).crossover(anyInt());
        inOrder.verify(geneticAlgorithmSpy, times(1)).mutate(anyInt());
        inOrder.verify(geneticAlgorithmSpy, times(0)).select();
        inOrder.verify(geneticAlgorithmSpy, times(0)).crossover(anyInt());
        inOrder.verify(geneticAlgorithmSpy, times(0)).mutate(anyInt());
    }
}