1 package net.bmahe.genetics4j.core.evaluation;
2
3 import java.util.List;
4
5 import net.bmahe.genetics4j.core.Genotype;
6
7 /**
8 * Facade interface for abstracting different fitness evaluation strategies in evolutionary algorithms.
9 *
10 * <p>FitnessEvaluator provides a unified interface for computing fitness values regardless of the underlying evaluation
11 * mechanism. This abstraction allows the evolutionary algorithm to work with various evaluation strategies including
12 * synchronous, asynchronous, parallel, and distributed evaluation approaches.
13 *
14 * <p>The evaluator supports different execution models:
15 * <ul>
16 * <li><strong>Synchronous evaluation</strong>: Sequential evaluation of individuals</li>
17 * <li><strong>Parallel evaluation</strong>: Concurrent evaluation using thread pools</li>
18 * <li><strong>Asynchronous evaluation</strong>: Non-blocking evaluation with future-based results</li>
19 * <li><strong>Distributed evaluation</strong>: Evaluation across multiple machines or processes</li>
20 * <li><strong>Cached evaluation</strong>: Memoized results for previously evaluated genotypes</li>
21 * </ul>
22 *
23 * <p>Key responsibilities include:
24 * <ul>
25 * <li><strong>Fitness computation</strong>: Converting genotypes into comparable fitness values</li>
26 * <li><strong>Resource management</strong>: Handling computational resources and external dependencies</li>
27 * <li><strong>Performance optimization</strong>: Efficient evaluation strategies for large populations</li>
28 * <li><strong>Error handling</strong>: Managing evaluation failures and providing fallback mechanisms</li>
29 * </ul>
30 *
31 * <p>Lifecycle methods provide hooks for:
32 * <ul>
33 * <li><strong>Setup</strong>: Initialize resources before evaluation begins</li>
34 * <li><strong>Cleanup</strong>: Release resources after evaluation completes</li>
35 * <li><strong>Batch processing</strong>: Optimize evaluation of entire populations</li>
36 * </ul>
37 *
38 * <p>Common implementation patterns:
39 * <ul>
40 * <li><strong>Wrapper pattern</strong>: Adapting {@link net.bmahe.genetics4j.core.Fitness} functions</li>
41 * <li><strong>Decorator pattern</strong>: Adding caching, logging, or monitoring capabilities</li>
42 * <li><strong>Strategy pattern</strong>: Switching between different evaluation approaches</li>
43 * <li><strong>Template method</strong>: Providing common evaluation infrastructure</li>
44 * </ul>
45 *
46 * <p>Example implementations:
47 *
48 * <pre>{@code
49 * // Simple synchronous evaluator
50 * FitnessEvaluator<Double> syncEvaluator = (generation, genotypes) -> {
51 * return genotypes.stream()
52 * .map(genotype -> computeFitness(genotype))
53 * .collect(toList());
54 * };
55 *
56 * // Parallel evaluator with thread pool
57 * FitnessEvaluator<Double> parallelEvaluator = (generation, genotypes) -> {
58 * return genotypes.parallelStream()
59 * .map(genotype -> computeFitness(genotype))
60 * .collect(toList());
61 * };
62 *
63 * // Cached evaluator for expensive fitness functions
64 * FitnessEvaluator<Double> cachedEvaluator = new CachedFitnessEvaluator<>(
65 * baseFitnessFunction,
66 * maxCacheSize: 10000
67 * );
68 * }</pre>
69 *
70 * <p>Performance considerations:
71 * <ul>
72 * <li><strong>Evaluation cost</strong>: Balance accuracy with computational efficiency</li>
73 * <li><strong>Parallelization</strong>: Utilize multiple cores for independent evaluations</li>
74 * <li><strong>Memory usage</strong>: Manage memory for large populations and complex fitness functions</li>
75 * <li><strong>External resources</strong>: Handle databases, web services, or file system access efficiently</li>
76 * </ul>
77 *
78 * @param <T> the type of fitness values produced, must be comparable for selection operations
79 * @see net.bmahe.genetics4j.core.Fitness
80 * @see FitnessEvaluatorSync
81 * @see FitnessEvaluatorBulkAsync
82 * @see net.bmahe.genetics4j.core.EASystem
83 */
84 public interface FitnessEvaluator<T extends Comparable<T>> {
85
86 /**
87 * Called before fitness evaluation begins for a generation.
88 *
89 * <p>This lifecycle method allows implementations to perform setup operations such as initializing resources,
90 * establishing connections, or preparing computational environments before the evaluation process starts.
91 *
92 * <p>Common setup activities include:
93 * <ul>
94 * <li>Starting thread pools or worker processes</li>
95 * <li>Establishing database or network connections</li>
96 * <li>Loading configuration or reference data</li>
97 * <li>Initializing caches or temporary storage</li>
98 * </ul>
99 *
100 * <p>The default implementation does nothing, making this method optional for implementations that don't require
101 * setup.
102 *
103 * @throws RuntimeException if setup fails and evaluation cannot proceed
104 */
105 default void preEvaluation() {
106 }
107
108 /**
109 * Called after fitness evaluation completes for a generation.
110 *
111 * <p>This lifecycle method allows implementations to perform cleanup operations such as releasing resources, closing
112 * connections, or persisting results after the evaluation process completes.
113 *
114 * <p>Common cleanup activities include:
115 * <ul>
116 * <li>Shutting down thread pools or worker processes</li>
117 * <li>Closing database or network connections</li>
118 * <li>Flushing caches or saving state</li>
119 * <li>Logging performance metrics or statistics</li>
120 * </ul>
121 *
122 * <p>The default implementation does nothing, making this method optional for implementations that don't require
123 * cleanup.
124 *
125 * @throws RuntimeException if cleanup fails (should not prevent evolution from continuing)
126 */
127 default void postEvaluation() {
128 }
129
130 /**
131 * Evaluates the fitness of all genotypes in the given population.
132 *
133 * <p>This is the core method that computes fitness values for an entire population of genotypes. The implementation
134 * strategy (synchronous, parallel, asynchronous) is determined by the specific evaluator implementation.
135 *
136 * <p>Requirements:
137 * <ul>
138 * <li>Return fitness values in the same order as input genotypes</li>
139 * <li>Return exactly one fitness value per input genotype</li>
140 * <li>Ensure fitness values are comparable for selection operations</li>
141 * <li>Handle empty populations gracefully (return empty list)</li>
142 * </ul>
143 *
144 * <p>The generation parameter can be used for:
145 * <ul>
146 * <li>Adaptive fitness functions that change over time</li>
147 * <li>Logging and monitoring evaluation progress</li>
148 * <li>Implementing generation-specific evaluation strategies</li>
149 * <li>Debugging and performance analysis</li>
150 * </ul>
151 *
152 * @param generation the current generation number (0-based)
153 * @param genotypes the population of genotypes to evaluate
154 * @return a list of fitness values corresponding to each genotype
155 * @throws IllegalArgumentException if genotypes list is null
156 * @throws RuntimeException if evaluation fails due to computational errors or resource issues
157 */
158 List<T> evaluate(final long generation, final List<Genotype> genotypes);
159 }