MATH-1618: Make "stopping condition" a "BiPredicate".
Second argument is the generation count (as determined by the caller).
This commit is contained in:
parent
f0fe9ab8eb
commit
383256f8cf
|
@ -23,7 +23,7 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.ToDoubleFunction;
|
import java.util.function.ToDoubleFunction;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.BiPredicate;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
@ -100,7 +100,7 @@ public final class MathFunctionOptimizer2 {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Stopping condition (not thread-safe).
|
// Stopping condition (not thread-safe).
|
||||||
final Predicate<Population<Chromosome, Coordinates>> stop =
|
final BiPredicate<Population<Chromosome, Coordinates>, Integer> stop =
|
||||||
new UnchangedFitness(UnchangedFitness.Type.BEST,
|
new UnchangedFitness(UnchangedFitness.Type.BEST,
|
||||||
numGeneration);
|
numGeneration);
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.BiPredicate;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.apache.commons.rng.simple.RandomSource;
|
import org.apache.commons.rng.simple.RandomSource;
|
||||||
|
@ -43,7 +43,7 @@ public final class GeneticAlgorithmFactory<G, P> implements Callable<Population<
|
||||||
/** Genotype to phenotype converter. */
|
/** Genotype to phenotype converter. */
|
||||||
private final Function<G, P> decoder;
|
private final Function<G, P> decoder;
|
||||||
/** Criterion for stopping the evolution. */
|
/** Criterion for stopping the evolution. */
|
||||||
private final Predicate<Population<G, P>> stop;
|
private final BiPredicate<Population<G, P>, Integer> stop;
|
||||||
/** Fitness calculator. */
|
/** Fitness calculator. */
|
||||||
private final FitnessService<G, P> fitness;
|
private final FitnessService<G, P> fitness;
|
||||||
/** Chromosome selector. */
|
/** Chromosome selector. */
|
||||||
|
@ -71,7 +71,7 @@ public final class GeneticAlgorithmFactory<G, P> implements Callable<Population<
|
||||||
*/
|
*/
|
||||||
private GeneticAlgorithmFactory(Collection<G> init,
|
private GeneticAlgorithmFactory(Collection<G> init,
|
||||||
Function<G, P> decoder,
|
Function<G, P> decoder,
|
||||||
Predicate<Population<G, P>> stop,
|
BiPredicate<Population<G, P>, Integer> stop,
|
||||||
FitnessService<G, P> fitness,
|
FitnessService<G, P> fitness,
|
||||||
Selection<G, P> selection,
|
Selection<G, P> selection,
|
||||||
Map<GeneticOperator<G>, ApplicationRate> operators,
|
Map<GeneticOperator<G>, ApplicationRate> operators,
|
||||||
|
@ -107,7 +107,7 @@ public final class GeneticAlgorithmFactory<G, P> implements Callable<Population<
|
||||||
*/
|
*/
|
||||||
public static <G, P> Callable<Population<G, P>> create(Collection<G> init,
|
public static <G, P> Callable<Population<G, P>> create(Collection<G> init,
|
||||||
Function<G, P> decoder,
|
Function<G, P> decoder,
|
||||||
Predicate<Population<G, P>> stop,
|
BiPredicate<Population<G, P>, Integer> stop,
|
||||||
FitnessService<G, P> fitness,
|
FitnessService<G, P> fitness,
|
||||||
Selection<G, P> selection,
|
Selection<G, P> selection,
|
||||||
Map<GeneticOperator<G>, ApplicationRate> operators,
|
Map<GeneticOperator<G>, ApplicationRate> operators,
|
||||||
|
@ -147,7 +147,7 @@ public final class GeneticAlgorithmFactory<G, P> implements Callable<Population<
|
||||||
ChromosomeFactory<G> initFactory,
|
ChromosomeFactory<G> initFactory,
|
||||||
int populationSize,
|
int populationSize,
|
||||||
Function<G, P> decoder,
|
Function<G, P> decoder,
|
||||||
Predicate<Population<G, P>> stop,
|
BiPredicate<Population<G, P>, Integer> stop,
|
||||||
FitnessService<G, P> fitness,
|
FitnessService<G, P> fitness,
|
||||||
Selection<G, P> selection,
|
Selection<G, P> selection,
|
||||||
Map<GeneticOperator<G>, ApplicationRate> operators,
|
Map<GeneticOperator<G>, ApplicationRate> operators,
|
||||||
|
@ -181,8 +181,7 @@ public final class GeneticAlgorithmFactory<G, P> implements Callable<Population<
|
||||||
currentGen.add(init);
|
currentGen.add(init);
|
||||||
final UniformRandomProvider rng = random.create();
|
final UniformRandomProvider rng = random.create();
|
||||||
|
|
||||||
while (!stop.test(currentGen)) {
|
while (!stop.test(currentGen, ++generation)) {
|
||||||
++generation;
|
|
||||||
final Population<G, P> nextGen = new Population<>(popSize, decoder, fitness);
|
final Population<G, P> nextGen = new Population<>(popSize, decoder, fitness);
|
||||||
|
|
||||||
applyElitism(currentGen, nextGen);
|
applyElitism(currentGen, nextGen);
|
||||||
|
|
|
@ -18,25 +18,30 @@ package org.apache.commons.math4.ga2.stop;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.function.ToDoubleFunction;
|
import java.util.function.ToDoubleFunction;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.BiPredicate;
|
||||||
import org.apache.commons.math4.ga2.Population;
|
import org.apache.commons.math4.ga2.Population;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Criterion for asserting convergence of a population.
|
* Criterion for asserting convergence of a population.
|
||||||
* Note: Class is <em>not</em> thread-safe.
|
* Notes:
|
||||||
|
* <ul>
|
||||||
|
* <li>Class is <em>not</em> thread-safe.</li>
|
||||||
|
* <li>A <em>new</em> instance must created for each GA run (otherwise
|
||||||
|
* an {@link IllegalStateException} will be thrown).</li>
|
||||||
|
* </ul>
|
||||||
*
|
*
|
||||||
* @param <G> Genotype.
|
* @param <G> Genotype.
|
||||||
* @param <P> Phenotype.
|
* @param <P> Phenotype.
|
||||||
*/
|
*/
|
||||||
public class UnchangedFitness<G, P> implements Predicate<Population<G, P>> {
|
public class UnchangedFitness<G, P> implements BiPredicate<Population<G, P>, Integer> {
|
||||||
/** Function that computes the reference value. */
|
/** Function that computes the reference value. */
|
||||||
private final ToDoubleFunction<Population<G, P>> calculator;
|
private final ToDoubleFunction<Population<G, P>> calculator;
|
||||||
/** Number of generations during which no change has happened. */
|
/** Number of generations during which no change has happened. */
|
||||||
private final int maxGenerations;
|
private final int maxGenerations;
|
||||||
/** Value for previous population. */
|
/** Value for previous population. */
|
||||||
private double previousFitness = Double.NaN;
|
private double previousFitness = Double.NaN;
|
||||||
/** Number of generations without changes. */
|
/** Generation at which the last change has occurred. */
|
||||||
private int generations = 0;
|
private int updatedGeneration = 0;
|
||||||
|
|
||||||
/** What needs to be unchanged. */
|
/** What needs to be unchanged. */
|
||||||
public enum Type {
|
public enum Type {
|
||||||
|
@ -71,14 +76,20 @@ public class UnchangedFitness<G, P> implements Predicate<Population<G, P>> {
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public boolean test(Population<G, P> population) {
|
public boolean test(Population<G, P> population,
|
||||||
|
Integer generationCounter) {
|
||||||
|
final int genDiff = generationCounter - updatedGeneration;
|
||||||
|
if (genDiff < 0) {
|
||||||
|
throw new IllegalStateException("Incorrect usage");
|
||||||
|
}
|
||||||
|
|
||||||
final double fitness = calculator.applyAsDouble(population);
|
final double fitness = calculator.applyAsDouble(population);
|
||||||
if (fitness == previousFitness) {
|
if (fitness == previousFitness) {
|
||||||
if (++generations > maxGenerations) {
|
if (genDiff > maxGenerations) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
generations = 0;
|
updatedGeneration = generationCounter;
|
||||||
previousFitness = fitness;
|
previousFitness = fitness;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue