View Javadoc
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 }