1 package net.bmahe.genetics4j.core;
2
3 import java.util.Objects;
4 import java.util.function.Function;
5
6 import org.apache.commons.lang3.Validate;
7
8 /**
9 * Functional interface for evaluating the fitness of a genotype in an evolutionary algorithm.
10 *
11 * <p>The fitness function is a crucial component of evolutionary algorithms as it determines the quality or performance
12 * of individual solutions. It maps a genotype to a fitness value that can be used for selection, ranking, and
13 * determining evolutionary progress.
14 *
15 * <p>Implementations should be:
16 * <ul>
17 * <li><strong>Deterministic</strong>: The same genotype should always produce the same fitness value</li>
18 * <li><strong>Thread-safe</strong>: May be called concurrently from multiple threads</li>
19 * <li><strong>Fast</strong>: Called frequently during evolution, performance matters</li>
20 * </ul>
21 *
22 * <p>Common fitness function patterns:
23 * <ul>
24 * <li><strong>Minimization</strong>: Lower values indicate better solutions (errors, costs)</li>
25 * <li><strong>Maximization</strong>: Higher values indicate better solutions (profits, accuracy)</li>
26 * <li><strong>Multi-objective</strong>: Use FitnessVector from the MOO module for multiple objectives</li>
27 * </ul>
28 *
29 * @param <T> the type of the fitness value, must be comparable for selection operations
30 * @see Genotype
31 * @see Individual
32 * @see net.bmahe.genetics4j.core.evaluation.FitnessEvaluator
33 */
34 @FunctionalInterface
35 public interface Fitness<T extends Comparable<T>> {
36
37 /**
38 * Computes the fitness value for the specified genotype.
39 *
40 * <p>This method should evaluate how well the genotype solves the problem and return a comparable fitness value. The
41 * interpretation of "better" depends on whether the optimization is for minimization or maximization.
42 *
43 * @param genotype the genotype to evaluate
44 * @return the fitness value representing the quality of the genotype
45 * @throws RuntimeException if evaluation fails due to invalid genotype or computation error
46 */
47 T compute(Genotype genotype);
48
49 /**
50 * Creates a fitness function that evaluates a specific chromosome within a genotype.
51 *
52 * <p>This utility method simplifies fitness evaluation when the fitness depends on only one chromosome from the
53 * genotype. It extracts the chromosome at the specified index and applies the provided fitness function to it.
54 *
55 * <p>This is particularly useful for:
56 * <ul>
57 * <li>Single-chromosome problems where genotype contains only one chromosome</li>
58 * <li>Multi-chromosome problems where fitness depends on one specific chromosome</li>
59 * <li>Compositional fitness functions that evaluate chromosomes independently</li>
60 * </ul>
61 *
62 * @param <U> the type of the chromosome to evaluate
63 * @param <V> the type of the fitness value, must be comparable
64 * @param chromosomeIndex the zero-based index of the chromosome to evaluate within the genotype
65 * @param chromosomeFitness the function that computes fitness for the extracted chromosome
66 * @return a fitness function that evaluates the specified chromosome
67 * @throws IllegalArgumentException if chromosomeIndex is negative
68 * @throws NullPointerException if chromosomeFitness is null
69 * @throws ClassCastException at runtime if the chromosome at the specified index cannot be cast to type U
70 * @throws IllegalArgumentException at runtime if chromosomeIndex exceeds the genotype size
71 */
72 static <U, V extends Comparable<V>> Fitness<V> forChromosome(final int chromosomeIndex,
73 final Function<U, V> chromosomeFitness) {
74 Validate.isTrue(chromosomeIndex >= 0);
75 Objects.requireNonNull(chromosomeFitness);
76
77 return genotype -> {
78 @SuppressWarnings("unchecked")
79 final U chromosome = (U) genotype.getChromosome(chromosomeIndex);
80
81 return chromosomeFitness.apply(chromosome);
82 };
83 }
84
85 }