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

org.evosuite.ga.Chromosome 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;

import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;
import org.evosuite.Properties;
import org.evosuite.ga.localsearch.LocalSearchObjective;
import org.evosuite.utils.PublicCloneable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Abstract base class of chromosomes
 * 
 * @author Gordon Fraser, Jose Miguel Rojas
 */
public abstract class Chromosome implements Comparable, Serializable,
		PublicCloneable {

	private static final long serialVersionUID = -6921897301005213358L;

	/** Constant logger */
	private static final Logger logger = LoggerFactory.getLogger(Chromosome.class);

	/**
	 * only used for testing/debugging
	 */
	protected Chromosome() {
		// empty
	}
	/** Last recorded fitness value */
	private LinkedHashMap, Double> fitnessValues = new LinkedHashMap, Double>();
	
	/** Previous fitness, to see if there was an improvement */
	private LinkedHashMap, Double> previousFitnessValues = new LinkedHashMap, Double>();

	/** Has this chromosome changed since its fitness was last evaluated? */
	private boolean changed = true;

	/** Has local search been applied to this individual since it was last changed? */
	private boolean localSearchApplied = false;

	private LinkedHashMap, Double> coverageValues = new LinkedHashMap, Double>();

	private LinkedHashMap, Integer> numsNotCoveredGoals = new LinkedHashMap, Integer>();

	private LinkedHashMap, Integer> numsCoveredGoals = new LinkedHashMap, Integer>();

	
	// protected double coverage = 0.0;

	// protected int numOfCoveredGoals = 0;

	/** Generation in which this chromosome was created */
	protected int age = 0;

	/** */
	protected int rank = -1;

	/** */
	protected double distance = 0.0;

	/** Keep track of how many times this Chromosome has been mutated */
	private int numberOfMutations = 0;

	/** Keep track of how many times this Chromosome has been evaluated */
	private int numberOfEvaluations = 0;

	// It is a non-negative number and it quantifies the tolerance of the system accepting a worse
	// solution than the existing one. (field used by Chemical Reaction Optimization algorithms)
	protected double kineticEnergy = Properties.INITIAL_KINETIC_ENERGY;

	// When a molecule undergoes a collision, one of the elementary reactions will be triggered and it
	// may experience a change in its molecular structure. It is a record of the total number of collisions
	// a molecule has taken. (field used by Chemical Reaction Optimization algorithms)
	protected int numCollisions = 0;

	/**
	 * Return current fitness value
	 * 
	 * @return a double.
	 */
	public double getFitness() {
		if (fitnessValues.size() > 1) {
			double sumFitnesses = 0.0;
			for (FitnessFunction fitnessFunction : fitnessValues.keySet()) {
				sumFitnesses += fitnessValues.get(fitnessFunction);
			}
			return sumFitnesses;
		} else
			return fitnessValues.isEmpty() ? 0.0 : fitnessValues.get(fitnessValues.keySet().iterator().next());
	}

	public  double getFitness(FitnessFunction ff) {
		return fitnessValues.containsKey(ff) ? fitnessValues.get(ff) : ff.getFitness((T)this); // Calculate new value if non is cached
	}

	public Map, Double> getFitnessValues() {
		return this.fitnessValues;
	}

	public Map, Double> getPreviousFitnessValues() {
		return this.previousFitnessValues;
	}
	
	public boolean hasExecutedFitness(FitnessFunction ff) {
		return this.previousFitnessValues.containsKey(ff);
	}

	public void setFitnessValues(Map, Double> fits) {
		//TODO mainfitness?
		this.fitnessValues.clear();
		this.fitnessValues.putAll(fits);
	}

	public void setPreviousFitnessValues(Map, Double> lastFits) {
		this.previousFitnessValues.clear();
		this.previousFitnessValues.putAll(lastFits);
	}

	/**
	 * Adds a fitness function and sets fitness, coverage, and numCoveredGoal
	 * default.
	 *
	 * @param ff
	 *            a fitness function
	 */
	public void addFitness(FitnessFunction ff) {
		if (ff.isMaximizationFunction())
			this.addFitness(ff, 0.0, 0.0, 0);
		else
			this.addFitness(ff, Double.MAX_VALUE, 0.0, 0);
	}

	/**
	 * Adds a fitness function with an associated fitness value
	 *
	 * @param ff
	 *            a fitness function
	 * @param fitnessValue
	 *            the fitness value for {@code ff}
	 */
	public void addFitness(FitnessFunction ff, double fitnessValue) {
		this.addFitness(ff, fitnessValue, 0.0, 0);
	}

	/**
	 * Adds a fitness function with an associated fitness value and coverage
	 * value
	 *
	 * @param ff
	 *            a fitness function
	 * @param fitnessValue
	 *            the fitness value for {@code ff}
	 * @param coverage
	 *            the coverage value for {@code ff}
	 */
	public void addFitness(FitnessFunction ff, double fitnessValue, double coverage) {
		this.addFitness(ff, fitnessValue, coverage, 0);
	}

	/**
	 * Adds a fitness function with an associated fitness value, coverage value,
	 * and number of covered goals.
	 *
	 * @param ff
	 *            a fitness function
	 * @param fitnessValue
	 *            the fitness value for {@code ff}
	 * @param coverage
	 *            the coverage value for {@code ff}
	 * @param numCoveredGoals
	 *            the number of covered goals for {@code ff}
	 */
	public void addFitness(FitnessFunction ff, double fitnessValue, double coverage,
			int numCoveredGoals) { 
		this.fitnessValues.put(ff, fitnessValue);
		this.previousFitnessValues.put(ff, fitnessValue);
		this.coverageValues.put(ff, coverage);
		this.numsCoveredGoals.put(ff, numCoveredGoals);
		this.numsNotCoveredGoals.put(ff, -1);
	}

	/**
	 * Set new fitness value
	 * 
	 * @param value
	 *            a double.
	 */
	public void setFitness(FitnessFunction ff, double value) throws IllegalArgumentException {
		if ((Double.compare(value, Double.NaN) == 0) || (Double.isInfinite(value))) {
//				 || ( value < 0 ) || ( ff == null )) 
			throw new IllegalArgumentException("Invalid value of Fitness: " + value + ", Fitness: "
					+ ff.getClass().getName());
		}

		if (!fitnessValues.containsKey(ff)) {
			previousFitnessValues.put(ff, value);
			fitnessValues.put(ff, value);
		} else {
			previousFitnessValues.put(ff, fitnessValues.get(ff));
			fitnessValues.put(ff, value);
		}
	}

	public boolean hasFitnessChanged() {
		for (FitnessFunction ff : fitnessValues.keySet()) {
			if (!fitnessValues.get(ff).equals(previousFitnessValues.get(ff))) {
				return true;
			}
		}
		return false;
	}

	/**
	 * {@inheritDoc}
	 * 
	 * Create a deep copy of the chromosome
	 */
	@Override
	public abstract Chromosome clone();

	/** {@inheritDoc} */
	@Override
	public abstract boolean equals(Object obj);

	/** {@inheritDoc} */
	@Override
	public abstract int hashCode();

	/**
	 * {@inheritDoc}
	 * 
	 * Determine relative ordering of this chromosome to another chromosome. If
	 * the fitness values are equal, go through all secondary objectives and try
	 * to find one where the two are not equal.
	 */
	@Override
	public int compareTo(Chromosome c) {
		int i = (int) Math.signum(this.getFitness() - c.getFitness());
		if (i == 0){
			return compareSecondaryObjective(c);
		}else
			return i;
	}

	/**
	 * Secondary Objectives are specific to chromosome types
	 * 
	 * @param o
	 *            a {@link org.evosuite.ga.Chromosome} object.
	 * @return a int.
	 */
	public abstract  int compareSecondaryObjective(T o);

	/**
	 * Apply mutation
	 */
	public abstract void mutate();

	/**
	 * Fixed single point cross over
	 * 
	 * @param other
	 *            a {@link org.evosuite.ga.Chromosome} object.
	 * @param position
	 *            a int.
	 * @throws org.evosuite.ga.ConstructionFailedException
	 *             if any.
	 */
	public void crossOver(Chromosome other, int position) throws ConstructionFailedException {
		crossOver(other, position, position);
	}

	/**
	 * Single point cross over
	 * 
	 * @param other
	 *            a {@link org.evosuite.ga.Chromosome} object.
	 * @param position1
	 *            a int.
	 * @param position2
	 *            a int.
	 * @throws org.evosuite.ga.ConstructionFailedException
	 *             if any.
	 */
	public abstract void crossOver(Chromosome other, int position1, int position2)
			throws ConstructionFailedException;

	/**
	 * Apply the local search
	 * 
	 * @param objective
	 *            a {@link org.evosuite.ga.localsearch.LocalSearchObjective}
	 *            object.
	 */
	public abstract boolean localSearch(LocalSearchObjective objective);

	/**
	 * Apply the local search
	 * 
	 * @param objective
	 *            a {@link org.evosuite.ga.LocalSearchObjective} object.
	 */
	// public void applyAdaptiveLocalSearch(LocalSearchObjective objective) {
	// // No-op
	// }

	/**
	 * Apply DSE
	 * 
	 * @param algorithm
	 *            a {@link org.evosuite.ga.GeneticAlgorithm} object.
	 */
	// public abstract boolean applyDSE(GeneticAlgorithm algorithm);

	/**
	 * Return length of individual
	 * 
	 * @return a int.
	 */
	public abstract int size();

	/**
	 * Return whether the chromosome has changed since the fitness value was
	 * computed last
	 * 
	 * @return a boolean.
	 */
	public boolean isChanged() {
		return changed;
	}

	/**
	 * Set changed status to @param changed
	 * 
	 * @param changed
	 *            a boolean.
	 */
	public void setChanged(boolean changed) {
		this.changed = changed;
		// If it's changed, then that also implies LS is possible again
		localSearchApplied = false;
	}
	
	
	public boolean hasLocalSearchBeenApplied() {
		return localSearchApplied;
	}

	public void setLocalSearchApplied(boolean localSearchApplied) {
		this.localSearchApplied = localSearchApplied;
	}

	/**
	 * 

* Getter for the field coverage. *

* * Returns a single coverage value calculated as the average of * coverage values for all fitness functions. * * @return a double. */ public double getCoverage() { double sum = 0; for (FitnessFunction fitnessFunction : coverageValues.keySet()) { sum += coverageValues.get(fitnessFunction); } double cov = coverageValues.isEmpty() ? 0.0 : sum / coverageValues.size(); assert (cov >= 0.0 && cov <= 1.0) : "Incorrect coverage value " + cov + ". Expected value between 0 and 1"; return cov; } public int getNumOfCoveredGoals() { int sum = 0; for (FitnessFunction fitnessFunction : numsCoveredGoals.keySet()) { sum += numsCoveredGoals.get(fitnessFunction); } return sum; } public int getNumOfNotCoveredGoals() { int sum = 0; for (FitnessFunction fitnessFunction : numsNotCoveredGoals.keySet()) { sum += numsNotCoveredGoals.get(fitnessFunction); } return sum; } public void setNumsOfCoveredGoals(Map, Integer> fits) { this.numsCoveredGoals.clear(); this.numsCoveredGoals.putAll(fits); } public void setNumsOfNotCoveredGoals(Map, Integer> fits) { this.numsNotCoveredGoals.clear(); this.numsNotCoveredGoals.putAll(fits); } public void setNumOfNotCoveredGoals(FitnessFunction ff, int numCoveredGoals) { this.numsNotCoveredGoals.put(ff, numCoveredGoals); } public Map, Integer> getNumsOfCoveredGoals() { return this.numsCoveredGoals; } public LinkedHashMap, Integer> getNumsNotCoveredGoals() { return numsNotCoveredGoals; } public Map, Double> getCoverageValues() { return this.coverageValues; } public void setCoverageValues(Map, Double> coverages) { this.coverageValues.clear(); this.coverageValues.putAll(coverages); } // public void setNumOfCoveredGoals(int numOfCoveredGoals) { // this.numOfCoveredGoals = numOfCoveredGoals; // } /** * Gets the coverage value for a given fitness function * * @param ff * a fitness function * @return the number of covered goals for {@code ff} */ public double getCoverage(FitnessFunction ff) { return coverageValues.containsKey(ff) ? coverageValues.get(ff) : 0.0; } /** * Sets the coverage value for a given fitness function * * @param ff * a fitness function * @param coverage * the coverage value */ public void setCoverage(FitnessFunction ff, double coverage) { this.coverageValues.put(ff, coverage); } /** * Gets the number of covered goals for a given fitness function * * @param ff * a fitness function * @return the number of covered goals for {@code ff} */ public int getNumOfCoveredGoals(FitnessFunction ff) { return numsCoveredGoals.containsKey(ff) ? numsCoveredGoals.get(ff) : 0; } /** * Gets the number of not covered goals for a given fitness function * * @param ff * a fitness function * @return the number of covered goals for {@code ff} */ public int getNumOfNotCoveredGoals(FitnessFunction ff) { return numsNotCoveredGoals.containsKey(ff) ? numsNotCoveredGoals.get(ff) : 0; } /** * Sets the number of covered goals for a given fitness function * * @param ff * a fitness function * @param numCoveredGoals * the number of covered goals */ public void setNumOfCoveredGoals(FitnessFunction ff, int numCoveredGoals) { this.numsCoveredGoals.put(ff, numCoveredGoals); } public void updateAge(int generation) { this.age = generation; } public int getAge() { return age; } public int getRank() { return this.rank; } public void setRank(int r) { this.rank = r; } public double getDistance() { return this.distance; } public void setDistance(double d) { this.distance = d; } public double getFitnessInstanceOf(Class clazz) { for (FitnessFunction fitnessFunction : fitnessValues.keySet()) { if (clazz.isInstance(fitnessFunction)) return fitnessValues.get(fitnessFunction); } return 0.0; } public double getCoverageInstanceOf(Class clazz) { for (FitnessFunction fitnessFunction : coverageValues.keySet()) { if (clazz.isInstance(fitnessFunction)) return coverageValues.get(fitnessFunction); } return 0.0; } /** * Increases by one the number of times this chromosome has been mutated */ public void increaseNumberOfMutations() { this.numberOfMutations++; } /** * Return number of times this chromosome has been mutated */ public int getNumberOfMutations() { return this.numberOfMutations; } /** * Set number of times this chromosome has been mutated */ public void setNumberOfMutations(int numberOfMutations) { this.numberOfMutations = numberOfMutations; } /** * Increases by one the number of times this chromosome has been evaluated */ public void increaseNumberOfEvaluations() { this.numberOfEvaluations++; } /** * Return number of times this chromosome has been evaluated */ public int getNumberOfEvaluations() { return this.numberOfEvaluations; } /** * Set number of times this chromosome has been evaluated */ public void setNumberOfEvaluations(int numberOfEvaluations) { this.numberOfEvaluations = numberOfEvaluations; } /** * Returns the tolerance of the system accepting a worse solution than the existing one. (Note: * method used by Chemical Reaction Optimization algorithms) * * @return a double value */ public double getKineticEnergy() { return this.kineticEnergy; } /** * Sets the tolerance of the system accepting a worse solution than the existing one. (Note: * method used by Chemical Reaction Optimization algorithms) * * @param kineticEnergy a double value */ public void setKineticEnergy(double kineticEnergy) { this.kineticEnergy = kineticEnergy; } /** * Returns the total number of collisions a chromosome (i.e., a molecule in a CRO scenario) has * taken. (Note: method used by Chemical Reaction Optimization algorithms) * * @return a integer value */ public int getNumCollisions() { return this.numCollisions; } /** * Sets the total number of collisions of a chromosome (i.e., a molecule in a CRO scenario). * (Note: method used by Chemical Reaction Optimization algorithms) * * @param numCollisions a integer value */ public void setNumCollisions(int numCollisions) { this.numCollisions = numCollisions; } /** * Sets the total number of collisions of a chromosome (i.e., a molecule in a CRO scenario) to * zero. (Note: method used by Chemical Reaction Optimization algorithms) */ public void resetNumCollisions() { this.numCollisions = 0; } /** * Increases the total number of collisions of a chromosome (i.e., a molecule in a CRO scenario) * by one. (Note: method used by Chemical Reaction Optimization algorithms) */ public void increaseNumCollisionsByOne() { this.numCollisions++; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy