EASystemFactory.java

1
package net.bmahe.genetics4j.core;
2
3
import java.util.ArrayList;
4
import java.util.List;
5
import java.util.Objects;
6
import java.util.Optional;
7
import java.util.concurrent.ExecutorService;
8
import java.util.concurrent.ForkJoinPool;
9
import java.util.stream.Collectors;
10
11
import net.bmahe.genetics4j.core.combination.ChromosomeCombinator;
12
import net.bmahe.genetics4j.core.combination.ChromosomeCombinatorResolver;
13
import net.bmahe.genetics4j.core.evaluation.FitnessEvaluator;
14
import net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorBulkAsync;
15
import net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorSync;
16
import net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThread;
17
import net.bmahe.genetics4j.core.mutation.MutationPolicyHandlerResolver;
18
import net.bmahe.genetics4j.core.mutation.Mutator;
19
import net.bmahe.genetics4j.core.replacement.ReplacementStrategyHandler;
20
import net.bmahe.genetics4j.core.selection.SelectionPolicyHandlerResolver;
21
import net.bmahe.genetics4j.core.spec.AbstractEAConfiguration;
22
import net.bmahe.genetics4j.core.spec.AbstractEAExecutionContext;
23
import net.bmahe.genetics4j.core.spec.EAConfiguration;
24
import net.bmahe.genetics4j.core.spec.EAConfigurationBulkAsync;
25
import net.bmahe.genetics4j.core.spec.EAExecutionContext;
26
import net.bmahe.genetics4j.core.spec.combination.CombinationPolicy;
27
import net.bmahe.genetics4j.core.spec.mutation.MutationPolicy;
28
29
/**
30
 * Factory class providing convenient methods for creating properly configured {@link EASystem} instances.
31
 * 
32
 * <p>EASystemFactory simplifies the complex process of assembling all the components required for evolutionary
33
 * algorithms by providing pre-configured factory methods that handle the initialization and wiring of selection
34
 * strategies, mutation operators, combination policies, and fitness evaluators.
35
 * 
36
 * <p>The factory abstracts away the complexity of manually creating and configuring:
37
 * <ul>
38
 * <li><strong>Selection policy resolvers</strong>: Components that match selection strategies to implementations</li>
39
 * <li><strong>Mutation policy resolvers</strong>: Components that handle different mutation strategies</li>
40
 * <li><strong>Chromosome combinators</strong>: Components responsible for crossover operations</li>
41
 * <li><strong>Replacement strategy handlers</strong>: Components managing population replacement</li>
42
 * <li><strong>Fitness evaluators</strong>: Components handling fitness computation strategies</li>
43
 * </ul>
44
 * 
45
 * <p>Factory methods are organized by evaluation strategy:
46
 * <ul>
47
 * <li><strong>Synchronous evaluation</strong>: Traditional single-threaded or parallel evaluation using
48
 * {@link EAConfiguration}</li>
49
 * <li><strong>Bulk asynchronous evaluation</strong>: Batch processing for external services or GPU acceleration using
50
 * {@link EAConfigurationBulkAsync}</li>
51
 * <li><strong>Custom evaluation</strong>: User-provided {@link FitnessEvaluator} implementations</li>
52
 * </ul>
53
 * 
54
 * <p>Common usage patterns:
55
 * 
56
 * <pre>{@code
57
 * // Simple synchronous evaluation with default thread pool
58
 * EAConfiguration<Double> config = EAConfigurationBuilder.<Double>builder()
59
 * 		.chromosomeSpecs(chromosomeSpec)
60
 * 		.parentSelectionPolicy(Tournament.of(3))
61
 * 		.combinationPolicy(SinglePointCrossover.build())
62
 * 		.mutationPolicies(List.of(RandomMutation.of(0.1)))
63
 * 		.replacementStrategy(Elitism.builder()
64
 * 				.offspringRatio(0.8)
65
 * 				.build())
66
 * 		.build();
67
 * 
68
 * EAExecutionContext<Double> context = EAExecutionContextBuilder.<Double>builder()
69
 * 		.populationSize(100)
70
 * 		.fitness(genotype -> computeFitness(genotype))
71
 * 		.termination(Generations.of(100))
72
 * 		.build();
73
 * 
74
 * EASystem<Double> eaSystem = EASystemFactory.from(config, context);
75
 * 
76
 * // Asynchronous evaluation for expensive fitness functions
77
 * EAConfigurationBulkAsync<Double> asyncConfig = EAConfigurationBulkAsyncBuilder.<Double>builder()
78
 * 		.chromosomeSpecs(chromosomeSpec)
79
 * 		.parentSelectionPolicy(Tournament.of(3))
80
 * 		.combinationPolicy(SinglePointCrossover.build())
81
 * 		.mutationPolicies(List.of(RandomMutation.of(0.1)))
82
 * 		.replacementStrategy(Elitism.builder()
83
 * 				.offspringRatio(0.8)
84
 * 				.build())
85
 * 		.fitnessBulkAsync(genotypes -> evaluateBatch(genotypes))
86
 * 		.build();
87
 * 
88
 * EASystem<Double> asyncSystem = EASystemFactory.from(asyncConfig, context);
89
 * 
90
 * // Custom evaluation strategy
91
 * FitnessEvaluator<Double> customEvaluator = new CachedFitnessEvaluator<>(baseFitness, cacheSize);
92
 * EASystem<Double> customSystem = EASystemFactory.from(config, context, executorService, customEvaluator);
93
 * }</pre>
94
 * 
95
 * <p>Factory method selection guide:
96
 * <ul>
97
 * <li><strong>Fast fitness functions</strong>: Use synchronous methods with {@link EAConfiguration}</li>
98
 * <li><strong>Expensive fitness functions</strong>: Use asynchronous methods with {@link EAConfigurationBulkAsync}</li>
99
 * <li><strong>External fitness computation</strong>: Use custom evaluator methods</li>
100
 * <li><strong>GPU acceleration</strong>: Use bulk async methods for batch processing</li>
101
 * </ul>
102
 * 
103
 * <p>Thread pool considerations:
104
 * <ul>
105
 * <li><strong>Default behavior</strong>: Uses {@link ForkJoinPool#commonPool()} for automatic parallelization</li>
106
 * <li><strong>Custom thread pools</strong>: Provide specific {@link ExecutorService} for resource control</li>
107
 * <li><strong>Single-threaded</strong>: Use {@link java.util.concurrent.Executors#newSingleThreadExecutor()}</li>
108
 * <li><strong>Resource management</strong>: Caller responsible for shutdown of custom thread pools</li>
109
 * </ul>
110
 * 
111
 * @see EASystem
112
 * @see EAConfiguration
113
 * @see EAConfigurationBulkAsync
114
 * @see EAExecutionContext
115
 * @see FitnessEvaluator
116
 */
117
public class EASystemFactory {
118
119
	/**
120
	 * Prevents instantiation since it's a bunch of static methods
121
	 */
122
	private EASystemFactory() {
123
	}
124
125
	/**
126
	 * Creates an {@link EASystem} with a custom fitness evaluator and explicit thread pool.
127
	 * 
128
	 * <p>This is the most flexible factory method that allows complete control over all components of the evolutionary
129
	 * algorithm system. It assembles and wires all necessary components including selection strategies, mutation
130
	 * operators, chromosome combinators, and replacement strategies.
131
	 * 
132
	 * <p>This method is primarily used internally by other factory methods, but can be used directly when you need to
133
	 * provide a custom {@link FitnessEvaluator} implementation such as cached, distributed, or specialized evaluation
134
	 * strategies.
135
	 * 
136
	 * @param <T>                the type of fitness values, must be comparable for selection operations
137
	 * @param eaConfiguration    the evolutionary algorithm configuration specifying genetic operators and strategies
138
	 * @param eaExecutionContext the execution context containing population parameters and fitness functions
139
	 * @param fitnessEvaluator   the fitness evaluator implementation to use for population evaluation
140
	 * @return a fully configured {@link EASystem} ready for evolution execution
141
	 * @throws IllegalArgumentException if any parameter is null
142
	 * @throws IllegalStateException    if no suitable replacement strategy handler can be found
143
	 */
144
	public static <T extends Comparable<T>> EASystem<T> from(final AbstractEAConfiguration<T> eaConfiguration,
145
			final AbstractEAExecutionContext<T> eaExecutionContext, final FitnessEvaluator<T> fitnessEvaluator) {
146
		Objects.requireNonNull(eaConfiguration);
147
		Objects.requireNonNull(eaExecutionContext);
148
		Objects.requireNonNull(fitnessEvaluator);
149
150 1 1. from : removed call to net/bmahe/genetics4j/core/selection/SelectionPolicyHandlerResolver::<init> → KILLED
		final var selectionPolicyHandlerResolver = new SelectionPolicyHandlerResolver<T>(eaExecutionContext);
151
152
		final var parentSelectionPolicyHandler = selectionPolicyHandlerResolver
153 2 1. from : removed call to net/bmahe/genetics4j/core/spec/AbstractEAConfiguration::parentSelectionPolicy → KILLED
2. from : removed call to net/bmahe/genetics4j/core/selection/SelectionPolicyHandlerResolver::resolve → KILLED
				.resolve(eaConfiguration.parentSelectionPolicy());
154
155 1 1. from : removed call to net/bmahe/genetics4j/core/selection/SelectionPolicyHandler::resolve → KILLED
		final var parentSelector = parentSelectionPolicyHandler.resolve(eaExecutionContext,
156
				eaConfiguration,
157
				selectionPolicyHandlerResolver,
158 1 1. from : removed call to net/bmahe/genetics4j/core/spec/AbstractEAConfiguration::parentSelectionPolicy → KILLED
				eaConfiguration.parentSelectionPolicy());
159
160 1 1. from : removed call to net/bmahe/genetics4j/core/mutation/MutationPolicyHandlerResolver::<init> → KILLED
		final var mutationPolicyHandlerResolver = new MutationPolicyHandlerResolver<T>(eaExecutionContext);
161
162 1 1. from : removed call to net/bmahe/genetics4j/core/combination/ChromosomeCombinatorResolver::<init> → KILLED
		final var chromosomeCombinatorResolver = new ChromosomeCombinatorResolver<T>(eaExecutionContext);
163
164 1 1. from : removed call to net/bmahe/genetics4j/core/spec/AbstractEAConfiguration::combinationPolicy → KILLED
		final CombinationPolicy combinationPolicy = eaConfiguration.combinationPolicy();
165 1 1. from : removed call to net/bmahe/genetics4j/core/spec/AbstractEAConfiguration::chromosomeSpecs → KILLED
		final List<ChromosomeCombinator<T>> chromosomeCombinators = eaConfiguration.chromosomeSpecs()
166 1 1. from : removed call to java/util/List::stream → KILLED
				.stream()
167 2 1. from : removed call to java/util/stream/Stream::map → KILLED
2. from : replaced call to java/util/stream/Stream::map with receiver → KILLED
				.map((chromosome) -> {
168 2 1. lambda$from$0 : replaced return value with null for net/bmahe/genetics4j/core/EASystemFactory::lambda$from$0 → KILLED
2. lambda$from$0 : removed call to net/bmahe/genetics4j/core/combination/ChromosomeCombinatorResolver::resolve → KILLED
					return chromosomeCombinatorResolver.resolve(combinationPolicy, chromosome);
169
				})
170 2 1. from : removed call to java/util/stream/Stream::collect → KILLED
2. from : removed call to java/util/stream/Collectors::toList → KILLED
				.collect(Collectors.toList());
171
172 1 1. from : removed call to java/util/ArrayList::<init> → KILLED
		final List<Mutator> mutators = new ArrayList<>();
173 1 1. from : removed call to net/bmahe/genetics4j/core/spec/AbstractEAConfiguration::mutationPolicies → KILLED
		final List<MutationPolicy> mutationPolicies = eaConfiguration.mutationPolicies();
174 6 1. from : removed call to java/util/List::size → SURVIVED
2. from : negated conditional → SURVIVED
3. from : Substituted 0 with 1 → SURVIVED
4. from : removed conditional - replaced comparison check with false → SURVIVED
5. from : removed conditional - replaced comparison check with true → KILLED
6. from : changed conditional boundary → KILLED
		for (int i = 0; i < mutationPolicies.size(); i++) {
175 1 1. from : removed call to java/util/List::get → KILLED
			final var mutationPolicy = mutationPolicies.get(i);
176
177 1 1. from : removed call to net/bmahe/genetics4j/core/mutation/MutationPolicyHandlerResolver::resolve → KILLED
			final var mutationPolicyHandler = mutationPolicyHandlerResolver.resolve(mutationPolicy);
178
			final var mutator = mutationPolicyHandler
179 1 1. from : removed call to net/bmahe/genetics4j/core/mutation/MutationPolicyHandler::createMutator → KILLED
					.createMutator(eaExecutionContext, eaConfiguration, mutationPolicyHandlerResolver, mutationPolicy);
180
181 1 1. from : removed call to java/util/List::add → SURVIVED
			mutators.add(mutator);
182
183
		}
184
185 1 1. from : removed call to net/bmahe/genetics4j/core/spec/AbstractEAExecutionContext::replacementStrategyHandlers → KILLED
		final var replacementStrategyHandlers = eaExecutionContext.replacementStrategyHandlers();
186 1 1. from : removed call to net/bmahe/genetics4j/core/spec/AbstractEAConfiguration::replacementStrategy → KILLED
		final var replacementStrategy = eaConfiguration.replacementStrategy();
187
188 1 1. from : removed call to java/util/List::stream → KILLED
		final Optional<ReplacementStrategyHandler<T>> replacementStrategyHandlerOpt = replacementStrategyHandlers.stream()
189 5 1. lambda$from$1 : replaced boolean return with true for net/bmahe/genetics4j/core/EASystemFactory::lambda$from$1 → SURVIVED
2. from : replaced call to java/util/stream/Stream::filter with receiver → SURVIVED
3. lambda$from$1 : replaced boolean return with false for net/bmahe/genetics4j/core/EASystemFactory::lambda$from$1 → KILLED
4. lambda$from$1 : removed call to net/bmahe/genetics4j/core/replacement/ReplacementStrategyHandler::canHandle → KILLED
5. from : removed call to java/util/stream/Stream::filter → KILLED
				.filter(replacementStrategyHandler -> replacementStrategyHandler.canHandle(replacementStrategy))
190 1 1. from : removed call to java/util/stream/Stream::findFirst → KILLED
				.findFirst();
191
192
		final ReplacementStrategyHandler<T> replacementStrategyHandler = replacementStrategyHandlerOpt
193 4 1. lambda$from$2 : removed call to java/lang/String::valueOf → NO_COVERAGE
2. lambda$from$2 : replaced return value with null for net/bmahe/genetics4j/core/EASystemFactory::lambda$from$2 → NO_COVERAGE
3. lambda$from$2 : removed call to java/lang/IllegalStateException::<init> → NO_COVERAGE
4. from : removed call to java/util/Optional::orElseThrow → KILLED
				.orElseThrow(() -> new IllegalStateException(
194
						"Could not find an implementation to handle the replacement strategy " + replacementStrategy));
195
		final var replacementStrategyImplementor = replacementStrategyHandler
196 1 1. from : removed call to net/bmahe/genetics4j/core/replacement/ReplacementStrategyHandler::resolve → KILLED
				.resolve(eaExecutionContext, eaConfiguration, selectionPolicyHandlerResolver, replacementStrategy);
197
198 1 1. from : removed call to net/bmahe/genetics4j/core/spec/AbstractEAExecutionContext::populationSize → KILLED
		final long populationSize = eaExecutionContext.populationSize();
199
200 1 1. from : replaced return value with null for net/bmahe/genetics4j/core/EASystemFactory::from → KILLED
		return new EASystem<>(eaConfiguration,
201
				populationSize,
202
				chromosomeCombinators,
203 2 1. from : removed call to net/bmahe/genetics4j/core/EASystem::<init> → KILLED
2. from : removed call to net/bmahe/genetics4j/core/spec/AbstractEAConfiguration::offspringGeneratedRatio → KILLED
				eaConfiguration.offspringGeneratedRatio(),
204
				parentSelector,
205
				mutators,
206
				replacementStrategyImplementor,
207
				eaExecutionContext,
208
				fitnessEvaluator);
209
	}
210
211
	/**
212
	 * Creates an {@link EASystem} with synchronous fitness evaluation and explicit thread pool.
213
	 * 
214
	 * <p>This method is ideal for scenarios where fitness computation is relatively fast and can benefit from parallel
215
	 * evaluation across multiple threads. The fitness function defined in the configuration will be called synchronously
216
	 * for each individual or in parallel depending on the evaluator implementation.
217
	 * 
218
	 * <p>Use this method when:
219
	 * <ul>
220
	 * <li>Fitness computation is CPU-bound and relatively fast (&lt; 100ms per evaluation)</li>
221
	 * <li>You want control over the thread pool used for parallel evaluation</li>
222
	 * <li>You need deterministic thread pool behavior for testing or resource management</li>
223
	 * </ul>
224
	 * 
225
	 * @param <T>                 the type of fitness values, must be comparable for selection operations
226
	 * @param eaConfigurationSync the synchronous EA configuration with a simple fitness function
227
	 * @param eaExecutionContext  the execution context containing population and termination parameters
228
	 * @param executorService     the thread pool for parallel fitness evaluation (caller responsible for shutdown)
229
	 * @return a configured {@link EASystem} using synchronous fitness evaluation
230
	 * @throws IllegalArgumentException if any parameter is null
231
	 */
232
	public static <T extends Comparable<T>> EASystem<T> from(final EAConfiguration<T> eaConfigurationSync,
233
			final EAExecutionContext<T> eaExecutionContext, final ExecutorService executorService) {
234
235 1 1. from : removed call to net/bmahe/genetics4j/core/evaluation/FitnessEvaluatorSync::<init> → KILLED
		final var fitnessEvaluator = new FitnessEvaluatorSync<>(eaExecutionContext, eaConfigurationSync, executorService);
236 2 1. from : replaced return value with null for net/bmahe/genetics4j/core/EASystemFactory::from → KILLED
2. from : removed call to net/bmahe/genetics4j/core/EASystemFactory::from → KILLED
		return from(eaConfigurationSync, eaExecutionContext, fitnessEvaluator);
237
	}
238
239
	/**
240
	 * Creates an {@link EASystem} with synchronous fitness evaluation using the common thread pool.
241
	 * 
242
	 * <p>This is the most convenient method for creating evolutionary algorithms with simple fitness functions. It uses
243
	 * {@link ForkJoinPool#commonPool()} for automatic parallelization without requiring explicit thread pool management.
244
	 * 
245
	 * <p>This method is ideal for:
246
	 * <ul>
247
	 * <li>Quick prototyping and experimentation</li>
248
	 * <li>Applications where thread pool management is not critical</li>
249
	 * <li>Fast fitness functions that can benefit from automatic parallelization</li>
250
	 * <li>Educational purposes and simple examples</li>
251
	 * </ul>
252
	 * 
253
	 * @param <T>                 the type of fitness values, must be comparable for selection operations
254
	 * @param eaConfigurationSync the synchronous EA configuration with a simple fitness function
255
	 * @param eaExecutionContext  the execution context containing population and termination parameters
256
	 * @return a configured {@link EASystem} using synchronous fitness evaluation with common thread pool
257
	 * @throws IllegalArgumentException if any parameter is null
258
	 */
259
	public static <T extends Comparable<T>> EASystem<T> from(final EAConfiguration<T> eaConfigurationSync,
260
			final EAExecutionContext<T> eaExecutionContext) {
261 1 1. from : removed call to java/util/concurrent/ForkJoinPool::commonPool → KILLED
		final ExecutorService executorService = ForkJoinPool.commonPool();
262 2 1. from : replaced return value with null for net/bmahe/genetics4j/core/EASystemFactory::from → KILLED
2. from : removed call to net/bmahe/genetics4j/core/EASystemFactory::from → KILLED
		return from(eaConfigurationSync, eaExecutionContext, executorService);
263
	}
264
265
	/**
266
	 * Creates an {@link EASystem} with bulk asynchronous fitness evaluation and explicit thread pool.
267
	 * 
268
	 * <p>This method is designed for expensive fitness functions that can benefit from batch processing or asynchronous
269
	 * evaluation. The bulk async evaluator can process entire populations at once, enabling optimization strategies like
270
	 * GPU acceleration, external service calls, or database batch operations.
271
	 * 
272
	 * <p>Use this method when:
273
	 * <ul>
274
	 * <li>Fitness computation involves external resources (databases, web services, files)</li>
275
	 * <li>Evaluation can be accelerated through batch processing (GPU, vectorized operations)</li>
276
	 * <li>Fitness computation is expensive (&gt; 100ms per evaluation)</li>
277
	 * <li>You need to optimize I/O operations through batching</li>
278
	 * </ul>
279
	 * 
280
	 * @param <T>                      the type of fitness values, must be comparable for selection operations
281
	 * @param eaConfigurationBulkAsync the bulk async EA configuration with batch fitness evaluation
282
	 * @param eaExecutionContext       the execution context containing population and termination parameters
283
	 * @param executorService          the thread pool for managing asynchronous operations (caller responsible for
284
	 *                                 shutdown)
285
	 * @return a configured {@link EASystem} using bulk asynchronous fitness evaluation
286
	 * @throws IllegalArgumentException if any parameter is null
287
	 */
288
	public static <T extends Comparable<T>> EASystem<T> from(final EAConfigurationBulkAsync<T> eaConfigurationBulkAsync,
289
			final EAExecutionContext<T> eaExecutionContext, final ExecutorService executorService) {
290
291 1 1. from : removed call to net/bmahe/genetics4j/core/evaluation/FitnessEvaluatorBulkAsync::<init> → NO_COVERAGE
		final var fitnessEvaluator = new FitnessEvaluatorBulkAsync<>(eaConfigurationBulkAsync, executorService);
292 2 1. from : removed call to net/bmahe/genetics4j/core/EASystemFactory::from → NO_COVERAGE
2. from : replaced return value with null for net/bmahe/genetics4j/core/EASystemFactory::from → NO_COVERAGE
		return from(eaConfigurationBulkAsync, eaExecutionContext, fitnessEvaluator);
293
	}
294
295
	/**
296
	 * Creates an {@link EASystem} with bulk asynchronous fitness evaluation using the common thread pool.
297
	 * 
298
	 * <p>This convenience method provides the benefits of bulk asynchronous evaluation without requiring explicit thread
299
	 * pool management. It automatically uses {@link ForkJoinPool#commonPool()} for managing asynchronous operations.
300
	 * 
301
	 * <p>This method combines the convenience of automatic thread pool management with the power of bulk asynchronous
302
	 * evaluation, making it ideal for:
303
	 * <ul>
304
	 * <li>Expensive fitness functions in research and experimentation</li>
305
	 * <li>Applications requiring external resource access without complex thread management</li>
306
	 * <li>GPU-accelerated fitness evaluation with simple setup</li>
307
	 * <li>Prototype development with advanced evaluation strategies</li>
308
	 * </ul>
309
	 * 
310
	 * @param <T>                      the type of fitness values, must be comparable for selection operations
311
	 * @param eaConfigurationBulkAsync the bulk async EA configuration with batch fitness evaluation
312
	 * @param eaExecutionContext       the execution context containing population and termination parameters
313
	 * @return a configured {@link EASystem} using bulk asynchronous fitness evaluation with common thread pool
314
	 * @throws IllegalArgumentException if any parameter is null
315
	 */
316
	public static <T extends Comparable<T>> EASystem<T> from(final EAConfigurationBulkAsync<T> eaConfigurationBulkAsync,
317
			final EAExecutionContext<T> eaExecutionContext) {
318 1 1. from : removed call to java/util/concurrent/ForkJoinPool::commonPool → NO_COVERAGE
		final ExecutorService executorService = ForkJoinPool.commonPool();
319 2 1. from : removed call to net/bmahe/genetics4j/core/EASystemFactory::from → NO_COVERAGE
2. from : replaced return value with null for net/bmahe/genetics4j/core/EASystemFactory::from → NO_COVERAGE
		return from(eaConfigurationBulkAsync, eaExecutionContext, executorService);
320
	}
321
322
	/**
323
	 * Creates an {@link EASystem} with virtual thread-based fitness evaluation.
324
	 *
325
	 * <p>This method leverages Java 21+ virtual threads to provide massive parallelism for fitness evaluation without
326
	 * the overhead of traditional platform threads. Each genotype gets its own virtual thread, making this approach
327
	 * ideal for I/O-bound fitness functions and large populations.
328
	 *
329
	 * <p>Virtual threads excel in scenarios involving:
330
	 * <ul>
331
	 * <li><strong>I/O-bound fitness functions</strong>: Database queries, web service calls, file operations</li>
332
	 * <li><strong>Large populations</strong>: Thousands of individuals without thread pool limitations</li>
333
	 * <li><strong>Complex simulations</strong>: Long-running evaluations that benefit from massive parallelism</li>
334
	 * <li><strong>External service integration</strong>: Fitness evaluations requiring network calls</li>
335
	 * </ul>
336
	 *
337
	 * <p>Performance characteristics:
338
	 * <ul>
339
	 * <li><strong>Memory overhead</strong>: ~200 bytes per virtual thread vs ~2MB per platform thread</li>
340
	 * <li><strong>Creation cost</strong>: Nearly zero compared to platform threads</li>
341
	 * <li><strong>Blocking behavior</strong>: Virtual threads don't block carrier threads during I/O</li>
342
	 * <li><strong>Scalability</strong>: Can handle millions of concurrent virtual threads</li>
343
	 * </ul>
344
	 *
345
	 * <p><strong>Requirements:</strong> Java 21+ with virtual threads enabled
346
	 *
347
	 * @param <T>                 the type of fitness values, must be comparable for selection operations
348
	 * @param eaConfigurationSync the synchronous EA configuration with a simple fitness function
349
	 * @param eaExecutionContext  the execution context containing population and termination parameters
350
	 * @return a configured {@link EASystem} using virtual thread-based fitness evaluation
351
	 * @throws IllegalArgumentException      if any parameter is null
352
	 * @throws UnsupportedOperationException if virtual threads are not available in current JVM
353
	 */
354
	public static <T extends Comparable<T>> EASystem<T> fromWithVirtualThreads(
355
			final EAConfiguration<T> eaConfigurationSync, final EAExecutionContext<T> eaExecutionContext) {
356
357 1 1. fromWithVirtualThreads : removed call to net/bmahe/genetics4j/core/evaluation/FitnessEvaluatorVirtualThread::<init> → KILLED
		final var fitnessEvaluator = new FitnessEvaluatorVirtualThread<>(eaExecutionContext, eaConfigurationSync);
358 2 1. fromWithVirtualThreads : removed call to net/bmahe/genetics4j/core/EASystemFactory::from → KILLED
2. fromWithVirtualThreads : replaced return value with null for net/bmahe/genetics4j/core/EASystemFactory::fromWithVirtualThreads → KILLED
		return from(eaConfigurationSync, eaExecutionContext, fitnessEvaluator);
359
	}
360
}

Mutations

150

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to net/bmahe/genetics4j/core/selection/SelectionPolicyHandlerResolver::<init> → KILLED

153

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to net/bmahe/genetics4j/core/spec/AbstractEAConfiguration::parentSelectionPolicy → KILLED

2.2
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to net/bmahe/genetics4j/core/selection/SelectionPolicyHandlerResolver::resolve → KILLED

155

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to net/bmahe/genetics4j/core/selection/SelectionPolicyHandler::resolve → KILLED

158

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to net/bmahe/genetics4j/core/spec/AbstractEAConfiguration::parentSelectionPolicy → KILLED

160

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to net/bmahe/genetics4j/core/mutation/MutationPolicyHandlerResolver::<init> → KILLED

162

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to net/bmahe/genetics4j/core/combination/ChromosomeCombinatorResolver::<init> → KILLED

164

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to net/bmahe/genetics4j/core/spec/AbstractEAConfiguration::combinationPolicy → KILLED

165

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to net/bmahe/genetics4j/core/spec/AbstractEAConfiguration::chromosomeSpecs → KILLED

166

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to java/util/List::stream → KILLED

167

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to java/util/stream/Stream::map → KILLED

2.2
Location : from
Killed by : net.bmahe.genetics4j.core.EASystemTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.EASystemTest]/[method:testEvolveWithIntChromosome()]
replaced call to java/util/stream/Stream::map with receiver → KILLED

168

1.1
Location : lambda$from$0
Killed by : net.bmahe.genetics4j.core.EASystemTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.EASystemTest]/[method:testEvolveWithIntChromosome()]
replaced return value with null for net/bmahe/genetics4j/core/EASystemFactory::lambda$from$0 → KILLED

2.2
Location : lambda$from$0
Killed by : net.bmahe.genetics4j.core.EASystemTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.EASystemTest]/[method:testEvolveWithIntChromosome()]
removed call to net/bmahe/genetics4j/core/combination/ChromosomeCombinatorResolver::resolve → KILLED

170

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to java/util/stream/Stream::collect → KILLED

2.2
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to java/util/stream/Collectors::toList → KILLED

172

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to java/util/ArrayList::<init> → KILLED

173

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to net/bmahe/genetics4j/core/spec/AbstractEAConfiguration::mutationPolicies → KILLED

174

1.1
Location : from
Killed by : none
removed call to java/util/List::size → SURVIVED
Covering tests

2.2
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed conditional - replaced comparison check with true → KILLED

3.3
Location : from
Killed by : none
negated conditional → SURVIVED Covering tests

4.4
Location : from
Killed by : none
Substituted 0 with 1 → SURVIVED Covering tests

5.5
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
changed conditional boundary → KILLED

6.6
Location : from
Killed by : none
removed conditional - replaced comparison check with false → SURVIVED Covering tests

175

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to java/util/List::get → KILLED

177

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to net/bmahe/genetics4j/core/mutation/MutationPolicyHandlerResolver::resolve → KILLED

179

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.EASystemTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.EASystemTest]/[method:testEvolveWithIntChromosome()]
removed call to net/bmahe/genetics4j/core/mutation/MutationPolicyHandler::createMutator → KILLED

181

1.1
Location : from
Killed by : none
removed call to java/util/List::add → SURVIVED
Covering tests

185

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to net/bmahe/genetics4j/core/spec/AbstractEAExecutionContext::replacementStrategyHandlers → KILLED

186

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to net/bmahe/genetics4j/core/spec/AbstractEAConfiguration::replacementStrategy → KILLED

188

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to java/util/List::stream → KILLED

189

1.1
Location : lambda$from$1
Killed by : none
replaced boolean return with true for net/bmahe/genetics4j/core/EASystemFactory::lambda$from$1 → SURVIVED
Covering tests

2.2
Location : lambda$from$1
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
replaced boolean return with false for net/bmahe/genetics4j/core/EASystemFactory::lambda$from$1 → KILLED

3.3
Location : from
Killed by : none
replaced call to java/util/stream/Stream::filter with receiver → SURVIVED Covering tests

4.4
Location : lambda$from$1
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to net/bmahe/genetics4j/core/replacement/ReplacementStrategyHandler::canHandle → KILLED

5.5
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to java/util/stream/Stream::filter → KILLED

190

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to java/util/stream/Stream::findFirst → KILLED

193

1.1
Location : lambda$from$2
Killed by : none
removed call to java/lang/String::valueOf → NO_COVERAGE

2.2
Location : lambda$from$2
Killed by : none
replaced return value with null for net/bmahe/genetics4j/core/EASystemFactory::lambda$from$2 → NO_COVERAGE

3.3
Location : lambda$from$2
Killed by : none
removed call to java/lang/IllegalStateException::<init> → NO_COVERAGE

4.4
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to java/util/Optional::orElseThrow → KILLED

196

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to net/bmahe/genetics4j/core/replacement/ReplacementStrategyHandler::resolve → KILLED

198

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to net/bmahe/genetics4j/core/spec/AbstractEAExecutionContext::populationSize → KILLED

200

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
replaced return value with null for net/bmahe/genetics4j/core/EASystemFactory::from → KILLED

203

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to net/bmahe/genetics4j/core/EASystem::<init> → KILLED

2.2
Location : from
Killed by : net.bmahe.genetics4j.core.EASystemTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.EASystemTest]/[method:testEvolveWithIntChromosome()]
removed call to net/bmahe/genetics4j/core/spec/AbstractEAConfiguration::offspringGeneratedRatio → KILLED

235

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.EASystemTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.EASystemTest]/[method:testSystemConstruction()]
removed call to net/bmahe/genetics4j/core/evaluation/FitnessEvaluatorSync::<init> → KILLED

236

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.EASystemTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.EASystemTest]/[method:testSystemConstruction()]
replaced return value with null for net/bmahe/genetics4j/core/EASystemFactory::from → KILLED

2.2
Location : from
Killed by : net.bmahe.genetics4j.core.EASystemTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.EASystemTest]/[method:testSystemConstruction()]
removed call to net/bmahe/genetics4j/core/EASystemFactory::from → KILLED

261

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.EASystemTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.EASystemTest]/[method:testSystemConstruction()]
removed call to java/util/concurrent/ForkJoinPool::commonPool → KILLED

262

1.1
Location : from
Killed by : net.bmahe.genetics4j.core.EASystemTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.EASystemTest]/[method:testSystemConstruction()]
replaced return value with null for net/bmahe/genetics4j/core/EASystemFactory::from → KILLED

2.2
Location : from
Killed by : net.bmahe.genetics4j.core.EASystemTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.EASystemTest]/[method:testSystemConstruction()]
removed call to net/bmahe/genetics4j/core/EASystemFactory::from → KILLED

291

1.1
Location : from
Killed by : none
removed call to net/bmahe/genetics4j/core/evaluation/FitnessEvaluatorBulkAsync::<init> → NO_COVERAGE

292

1.1
Location : from
Killed by : none
removed call to net/bmahe/genetics4j/core/EASystemFactory::from → NO_COVERAGE

2.2
Location : from
Killed by : none
replaced return value with null for net/bmahe/genetics4j/core/EASystemFactory::from → NO_COVERAGE

318

1.1
Location : from
Killed by : none
removed call to java/util/concurrent/ForkJoinPool::commonPool → NO_COVERAGE

319

1.1
Location : from
Killed by : none
removed call to net/bmahe/genetics4j/core/EASystemFactory::from → NO_COVERAGE

2.2
Location : from
Killed by : none
replaced return value with null for net/bmahe/genetics4j/core/EASystemFactory::from → NO_COVERAGE

357

1.1
Location : fromWithVirtualThreads
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to net/bmahe/genetics4j/core/evaluation/FitnessEvaluatorVirtualThread::<init> → KILLED

358

1.1
Location : fromWithVirtualThreads
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
removed call to net/bmahe/genetics4j/core/EASystemFactory::from → KILLED

2.2
Location : fromWithVirtualThreads
Killed by : net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest.[engine:junit-jupiter]/[class:net.bmahe.genetics4j.core.evaluation.FitnessEvaluatorVirtualThreadTest]/[method:testVirtualThreadFactory()]
replaced return value with null for net/bmahe/genetics4j/core/EASystemFactory::fromWithVirtualThreads → KILLED

Active mutators

Tests examined


Report generated by PIT 1.20.3