All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.evosuite.ga.metaheuristics.MonotonicGA Maven / Gradle / Ivy

/**
 * Copyright (C) 2010-2018 Gordon Fraser, Andrea Arcuri and EvoSuite
 * contributors
 *
 * This file is part of EvoSuite.
 *
 * EvoSuite is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3.0 of the License, or
 * (at your option) any later version.
 *
 * EvoSuite 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
 * Lesser Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with EvoSuite. If not, see .
 */
package org.evosuite.ga.metaheuristics;

import java.util.ArrayList;
import java.util.List;

import org.evosuite.Properties;
import org.evosuite.TimeController;
import org.evosuite.ga.Chromosome;
import org.evosuite.ga.ChromosomeFactory;
import org.evosuite.ga.ConstructionFailedException;
import org.evosuite.ga.FitnessFunction;
import org.evosuite.ga.FitnessReplacementFunction;
import org.evosuite.ga.ReplacementFunction;
import org.evosuite.ga.localsearch.LocalSearchBudget;
import org.evosuite.utils.Randomness;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Implementation of steady state GA
 * 
 * @author Gordon Fraser
 */
public class MonotonicGA extends GeneticAlgorithm {

	private static final long serialVersionUID = 7846967347821123201L;

	protected ReplacementFunction replacementFunction;

	private final Logger logger = LoggerFactory.getLogger(MonotonicGA.class);

	/**
	 * Constructor
	 * 
	 * @param factory
	 *            a {@link org.evosuite.ga.ChromosomeFactory} object.
	 */
	public MonotonicGA(ChromosomeFactory factory) {
		super(factory);

		setReplacementFunction(new FitnessReplacementFunction());
	}

	/**
	 * 

* keepOffspring *

* * @param parent1 * a {@link org.evosuite.ga.Chromosome} object. * @param parent2 * a {@link org.evosuite.ga.Chromosome} object. * @param offspring1 * a {@link org.evosuite.ga.Chromosome} object. * @param offspring2 * a {@link org.evosuite.ga.Chromosome} object. * @return a boolean. */ protected boolean keepOffspring(Chromosome parent1, Chromosome parent2, Chromosome offspring1, Chromosome offspring2) { return replacementFunction.keepOffspring(parent1, parent2, offspring1, offspring2); } /** {@inheritDoc} */ @SuppressWarnings("unchecked") @Override protected void evolve() { List newGeneration = new ArrayList(); // Elitism logger.debug("Elitism"); newGeneration.addAll(elitism()); // Add random elements // new_generation.addAll(randomism()); while (!isNextPopulationFull(newGeneration) && !isFinished()) { logger.debug("Generating offspring"); T parent1 = selectionFunction.select(population); T parent2; if (Properties.HEADLESS_CHICKEN_TEST) parent2 = newRandomIndividual(); // crossover with new random // individual else parent2 = selectionFunction.select(population); // crossover // with existing // individual T offspring1 = (T) parent1.clone(); T offspring2 = (T) parent2.clone(); try { // Crossover if (Randomness.nextDouble() <= Properties.CROSSOVER_RATE) { crossoverFunction.crossOver(offspring1, offspring2); } } catch (ConstructionFailedException e) { logger.info("CrossOver failed"); continue; } // Mutation notifyMutation(offspring1); offspring1.mutate(); notifyMutation(offspring2); offspring2.mutate(); if (offspring1.isChanged()) { offspring1.updateAge(currentIteration); } if (offspring2.isChanged()) { offspring2.updateAge(currentIteration); } // The two offspring replace the parents if and only if one of // the offspring is not worse than the best parent. for (FitnessFunction fitnessFunction : fitnessFunctions) { fitnessFunction.getFitness(offspring1); notifyEvaluation(offspring1); fitnessFunction.getFitness(offspring2); notifyEvaluation(offspring2); } if (keepOffspring(parent1, parent2, offspring1, offspring2)) { logger.debug("Keeping offspring"); // Reject offspring straight away if it's too long int rejected = 0; if (isTooLong(offspring1) || offspring1.size() == 0) { rejected++; } else { // if(Properties.ADAPTIVE_LOCAL_SEARCH == // AdaptiveLocalSearchTarget.ALL) // applyAdaptiveLocalSearch(offspring1); newGeneration.add(offspring1); } if (isTooLong(offspring2) || offspring2.size() == 0) { rejected++; } else { // if(Properties.ADAPTIVE_LOCAL_SEARCH == // AdaptiveLocalSearchTarget.ALL) // applyAdaptiveLocalSearch(offspring2); newGeneration.add(offspring2); } if (rejected == 1) newGeneration.add(Randomness.choice(parent1, parent2)); else if (rejected == 2) { newGeneration.add(parent1); newGeneration.add(parent2); } } else { logger.debug("Keeping parents"); newGeneration.add(parent1); newGeneration.add(parent2); } } population = newGeneration; // archive updateFitnessFunctionsAndValues(); currentIteration++; } private T newRandomIndividual() { T randomChromosome = chromosomeFactory.getChromosome(); for (FitnessFunction fitnessFunction : this.fitnessFunctions) { randomChromosome.addFitness(fitnessFunction); } return randomChromosome; } /** {@inheritDoc} */ @Override public void initializePopulation() { notifySearchStarted(); currentIteration = 0; // Set up initial population generateInitialPopulation(Properties.POPULATION); logger.debug("Calculating fitness of initial population"); calculateFitnessAndSortPopulation(); this.notifyIteration(); } private static final double DELTA = 0.000000001; // it seems there is some // rounding error in LS, // but hard to debug :( /** {@inheritDoc} */ @Override public void generateSolution() { if (Properties.ENABLE_SECONDARY_OBJECTIVE_AFTER > 0 || Properties.ENABLE_SECONDARY_OBJECTIVE_STARVATION) { disableFirstSecondaryCriterion(); } if (population.isEmpty()) { initializePopulation(); assert!population.isEmpty() : "Could not create any test"; } logger.debug("Starting evolution"); int starvationCounter = 0; double bestFitness = Double.MAX_VALUE; double lastBestFitness = Double.MAX_VALUE; if (getFitnessFunction().isMaximizationFunction()) { bestFitness = 0.0; lastBestFitness = 0.0; } while (!isFinished()) { logger.info("Population size before: " + population.size()); // related to Properties.ENABLE_SECONDARY_OBJECTIVE_AFTER; // check the budget progress and activate a secondary criterion // according to the property value. { double bestFitnessBeforeEvolution = getBestFitness(); evolve(); sortPopulation(); double bestFitnessAfterEvolution = getBestFitness(); if (getFitnessFunction().isMaximizationFunction()) assert(bestFitnessAfterEvolution >= (bestFitnessBeforeEvolution - DELTA)) : "best fitness before evolve()/sortPopulation() was: " + bestFitnessBeforeEvolution + ", now best fitness is " + bestFitnessAfterEvolution; else assert(bestFitnessAfterEvolution <= (bestFitnessBeforeEvolution + DELTA)) : "best fitness before evolve()/sortPopulation() was: " + bestFitnessBeforeEvolution + ", now best fitness is " + bestFitnessAfterEvolution; } { double bestFitnessBeforeLocalSearch = getBestFitness(); applyLocalSearch(); double bestFitnessAfterLocalSearch = getBestFitness(); if (getFitnessFunction().isMaximizationFunction()) assert(bestFitnessAfterLocalSearch >= (bestFitnessBeforeLocalSearch - DELTA)) : "best fitness before applyLocalSearch() was: " + bestFitnessBeforeLocalSearch + ", now best fitness is " + bestFitnessAfterLocalSearch; else assert(bestFitnessAfterLocalSearch <= (bestFitnessBeforeLocalSearch + DELTA)) : "best fitness before applyLocalSearch() was: " + bestFitnessBeforeLocalSearch + ", now best fitness is " + bestFitnessAfterLocalSearch; } /* * TODO: before explanation: due to static state handling, LS can * worse individuals. so, need to re-sort. * * now: the system tests that were failing have no static state... * so re-sorting does just hide the problem away, and reduce * performance (likely significantly). it is definitively a bug * somewhere... */ // sortPopulation(); double newFitness = getBestFitness(); if (getFitnessFunction().isMaximizationFunction()) assert(newFitness >= (bestFitness - DELTA)) : "best fitness was: " + bestFitness + ", now best fitness is " + newFitness; else assert(newFitness <= (bestFitness + DELTA)) : "best fitness was: " + bestFitness + ", now best fitness is " + newFitness; bestFitness = newFitness; if (Double.compare(bestFitness, lastBestFitness) == 0) { starvationCounter++; } else { logger.info("reset starvationCounter after " + starvationCounter + " iterations"); starvationCounter = 0; lastBestFitness = bestFitness; } updateSecondaryCriterion(starvationCounter); logger.info("Current iteration: " + currentIteration); this.notifyIteration(); logger.info("Population size: " + population.size()); logger.info("Best individual has fitness: " + population.get(0).getFitness()); logger.info("Worst individual has fitness: " + population.get(population.size() - 1).getFitness()); } // archive TimeController.execute(this::updateBestIndividualFromArchive, "update from archive", 5_000); notifySearchFinished(); } private double getBestFitness() { T bestIndividual = getBestIndividual(); for (FitnessFunction ff : fitnessFunctions) { ff.getFitness(bestIndividual); } return bestIndividual.getFitness(); } /** *

* setReplacementFunction *

* * @param replacement_function * a {@link org.evosuite.ga.ReplacementFunction} object. */ public void setReplacementFunction(ReplacementFunction replacement_function) { this.replacementFunction = replacement_function; } /** *

* getReplacementFunction *

* * @return a {@link org.evosuite.ga.ReplacementFunction} object. */ public ReplacementFunction getReplacementFunction() { return replacementFunction; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy