io.jenetics.engine.FutureEvaluator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jenetics Show documentation
Show all versions of jenetics Show documentation
Jenetics - Java Genetic Algorithm Library
/*
* Java Genetic Algorithm Library (jenetics-7.1.2).
* Copyright (c) 2007-2023 Franz Wilhelmstötter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Author:
* Franz Wilhelmstötter ([email protected])
*/
package io.jenetics.engine;
import static java.util.Objects.requireNonNull;
import java.util.Iterator;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletionException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.function.Function;
import io.jenetics.Gene;
import io.jenetics.Genotype;
import io.jenetics.Phenotype;
import io.jenetics.util.ISeq;
import io.jenetics.util.MSeq;
import io.jenetics.util.Seq;
/**
* Example of an {@code Engine.Evaluator} where the fitness function returns
* a {@link Future} of the fitness value instead the value itself.
*
* @author Franz Wilhelmstötter
* @version 5.0
* @since 5.0
*/
final class FutureEvaluator<
G extends Gene, G>,
C extends Comparable super C>
>
implements Evaluator
{
private final Function super Genotype, ? extends Future> _fitness;
FutureEvaluator(
final Function super Genotype, ? extends Future> fitness
) {
_fitness = requireNonNull(fitness);
}
@Override
public ISeq> eval(final Seq> population) {
final ISeq> evaluate = population.stream()
.filter(Phenotype::nonEvaluated)
.map(pt -> _fitness.apply(pt.genotype()))
.collect(ISeq.toISeq());
final ISeq> evaluated = population.stream()
.filter(Phenotype::isEvaluated)
.collect(ISeq.toISeq());
join(evaluate);
return evaluated.append(map(population, evaluate));
}
private static void join(final Iterable extends Future>> futures) {
final Iterator extends Future>> it = futures.iterator();
Exception exception = null;
Future> future = null;
try {
while (it.hasNext()) {
future = it.next();
future.get();
}
future = null;
} catch (InterruptedException |
ExecutionException |
CancellationException e)
{
exception = e;
}
if (future != null) {
future.cancel(true);
while (it.hasNext()) {
it.next().cancel(true);
}
}
if (exception instanceof InterruptedException ie) {
Thread.currentThread().interrupt();
final var ce = new CancellationException(ie.getMessage());
ce.initCause(ie);
throw ce;
} else if (exception instanceof CancellationException e) {
throw e;
} else if (exception != null) {
throw new CompletionException(exception);
}
}
private ISeq> map(
final Seq> population,
final Seq> fitnesses
) {
final ISeq> phenotypes = population.stream()
.filter(Phenotype::nonEvaluated)
.collect(ISeq.toISeq());
assert phenotypes.length() == fitnesses.length();
final MSeq> result = MSeq.ofLength(phenotypes.size());
for (int i = 0; i < fitnesses.length(); ++i) {
result.set(i, phenotypes.get(i).withFitness(get(fitnesses.get(i))));
}
return result.asISeq();
}
private static T get(final Future future) {
try {
return future.get();
} catch (InterruptedException|ExecutionException e) {
throw new AssertionError(e);
}
}
}