Fitness.java
package net.bmahe.genetics4j.core;
import java.util.Objects;
import java.util.function.Function;
import org.apache.commons.lang3.Validate;
/**
* Functional interface for evaluating the fitness of a genotype in an evolutionary algorithm.
*
* <p>The fitness function is a crucial component of evolutionary algorithms as it determines the quality or performance
* of individual solutions. It maps a genotype to a fitness value that can be used for selection, ranking, and
* determining evolutionary progress.
*
* <p>Implementations should be:
* <ul>
* <li><strong>Deterministic</strong>: The same genotype should always produce the same fitness value</li>
* <li><strong>Thread-safe</strong>: May be called concurrently from multiple threads</li>
* <li><strong>Fast</strong>: Called frequently during evolution, performance matters</li>
* </ul>
*
* <p>Common fitness function patterns:
* <ul>
* <li><strong>Minimization</strong>: Lower values indicate better solutions (errors, costs)</li>
* <li><strong>Maximization</strong>: Higher values indicate better solutions (profits, accuracy)</li>
* <li><strong>Multi-objective</strong>: Use FitnessVector from the MOO module for multiple objectives</li>
* </ul>
*
* @param <T> the type of the fitness value, must be comparable for selection operations
* @see Genotype
* @see Individual
* @see net.bmahe.genetics4j.core.evaluation.FitnessEvaluator
*/
@FunctionalInterface
public interface Fitness<T extends Comparable<T>> {
/**
* Computes the fitness value for the specified genotype.
*
* <p>This method should evaluate how well the genotype solves the problem and return a comparable fitness value. The
* interpretation of "better" depends on whether the optimization is for minimization or maximization.
*
* @param genotype the genotype to evaluate
* @return the fitness value representing the quality of the genotype
* @throws RuntimeException if evaluation fails due to invalid genotype or computation error
*/
T compute(Genotype genotype);
/**
* Creates a fitness function that evaluates a specific chromosome within a genotype.
*
* <p>This utility method simplifies fitness evaluation when the fitness depends on only one chromosome from the
* genotype. It extracts the chromosome at the specified index and applies the provided fitness function to it.
*
* <p>This is particularly useful for:
* <ul>
* <li>Single-chromosome problems where genotype contains only one chromosome</li>
* <li>Multi-chromosome problems where fitness depends on one specific chromosome</li>
* <li>Compositional fitness functions that evaluate chromosomes independently</li>
* </ul>
*
* @param <U> the type of the chromosome to evaluate
* @param <V> the type of the fitness value, must be comparable
* @param chromosomeIndex the zero-based index of the chromosome to evaluate within the genotype
* @param chromosomeFitness the function that computes fitness for the extracted chromosome
* @return a fitness function that evaluates the specified chromosome
* @throws IllegalArgumentException if chromosomeIndex is negative
* @throws NullPointerException if chromosomeFitness is null
* @throws ClassCastException at runtime if the chromosome at the specified index cannot be cast to type U
* @throws IllegalArgumentException at runtime if chromosomeIndex exceeds the genotype size
*/
static <U, V extends Comparable<V>> Fitness<V> forChromosome(final int chromosomeIndex,
final Function<U, V> chromosomeFitness) {
Validate.isTrue(chromosomeIndex >= 0);
Objects.requireNonNull(chromosomeFitness);
return genotype -> {
@SuppressWarnings("unchecked")
final U chromosome = (U) genotype.getChromosome(chromosomeIndex);
return chromosomeFitness.apply(chromosome);
};
}
}