/*
* 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;
import java.io.*;
import org.jgap.util.*;
/**
* Fitness functions are used to determine how optimal a particular solution
* is relative to other solutions. This abstract class should be extended and
* the evaluate() method implemented. The fitness function is given a Chromosome
* to evaluate and should return a positive double that reflects its fitness
* value. The higher the value, the more fit the Chromosome. The actual range
* of fitness values isn't important (other than the fact that they must be
* positive doubles): it's the relative difference as a percentage that
* tends to determine the success or failure of a Chromosome. So in other words,
* two Chromosomes with respective fitness values of 1 and 100 have the same
* relative fitness to each other as two Chromosomes with respective fitness
* values of 10 and 1000 (in each case, the first is 1% as fit as the second).
* <p>
* Note: Two Chromosomes with equivalent sets of genes should always be
* assigned the same fitness value by any implementation of this interface.
*
* @author Neil Rotstan
* @author Klaus Meffert
* @since 1.0
*/
public abstract class FitnessFunction
implements Serializable, ICloneable {
/** String containing the CVS revision. Read out via reflection!*/
private final static String CVS_REVISION = "$Revision: 1.22 $";
public final static double NO_FITNESS_VALUE = -1.0000000d;
public final static double DELTA = 0.0000001d;
/**
* The fitness value computed during the previous run
*/
private double m_lastComputedFitnessValue = NO_FITNESS_VALUE;
/**
* Retrieves the fitness value of the given Chromosome. The fitness
* value will be a positive double.
*
* @param a_subject the Chromosome for which to compute and return the
* fitness value
* @return the fitness value of the given Chromosome
*
* @author Neil Rotstan
* @author Klaus Meffert
* @since 2.0 (until 1.1: return type int)
*/
public double getFitnessValue(final IChromosome a_subject) {
// Delegate to the evaluate() method to actually compute the
// fitness value. If the returned value is less than one,
// then we throw a runtime exception.
// ---------------------------------------------------------
double fitnessValue = evaluate(a_subject);
if (fitnessValue < 0.00000000d) {
throw new RuntimeException(
"Fitness values must be positive! Received value: "
+ fitnessValue);
}
m_lastComputedFitnessValue = fitnessValue;
return fitnessValue;
}
/**
* @return the last fitness value computed via method getFitnessValue(
* Chromosome), or NO_FITNES_VALUE if the former method has not been called
* yet
*
* @author Klaus Meffert
* @since 2.4
*/
public double getLastComputedFitnessValue() {
return m_lastComputedFitnessValue;
}
/**
* Determine the fitness of the given Chromosome instance. The higher the
* return value, the more fit the instance. This method should always
* return the same fitness value for two equivalent Chromosome instances.
*
* @param a_subject the Chromosome instance to evaluate
*
* @return positive double reflecting the fitness rating of the given
* Chromosome. Note that if a non-positive double is returned, a
* RuntimeException should be generated
*
* @author Neil Rotstan
* @author Klaus Meffert
* @since 2.0 (until 1.1: return type int)
*/
protected abstract double evaluate(IChromosome a_subject);
/**
* Please override in your implementations!
*
* @return deep clone of the current instance
*
* @author Klaus Meffert
* @since 3.2
*/
public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException cex) {
throw new CloneException(cex);
}
}
}