0001 /*
0002 * Java Genetic Algorithm Library (jenetics-3.8.0).
0003 * Copyright (c) 2007-2017 Franz Wilhelmstötter
0004 *
0005 * Licensed under the Apache License, Version 2.0 (the "License");
0006 * you may not use this file except in compliance with the License.
0007 * You may obtain a copy of the License at
0008 *
0009 * http://www.apache.org/licenses/LICENSE-2.0
0010 *
0011 * Unless required by applicable law or agreed to in writing, software
0012 * distributed under the License is distributed on an "AS IS" BASIS,
0013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014 * See the License for the specific language governing permissions and
0015 * limitations under the License.
0016 *
0017 * Author:
0018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
0019 */
0020 package org.jenetics.engine;
0021
0022 import static java.lang.Math.round;
0023 import static java.lang.String.format;
0024 import static java.util.Objects.requireNonNull;
0025 import static org.jenetics.Population.toPopulation;
0026 import static org.jenetics.internal.util.require.probability;
0027
0028 import java.time.Clock;
0029 import java.util.Iterator;
0030 import java.util.Objects;
0031 import java.util.concurrent.CompletableFuture;
0032 import java.util.concurrent.Executor;
0033 import java.util.concurrent.ForkJoinPool;
0034 import java.util.function.Function;
0035 import java.util.function.Predicate;
0036 import java.util.stream.Stream;
0037 import java.util.stream.StreamSupport;
0038
0039 import org.jenetics.internal.util.Concurrency;
0040 import org.jenetics.internal.util.require;
0041
0042 import org.jenetics.Alterer;
0043 import org.jenetics.Chromosome;
0044 import org.jenetics.Gene;
0045 import org.jenetics.Genotype;
0046 import org.jenetics.Mutator;
0047 import org.jenetics.Optimize;
0048 import org.jenetics.Phenotype;
0049 import org.jenetics.Population;
0050 import org.jenetics.Selector;
0051 import org.jenetics.SinglePointCrossover;
0052 import org.jenetics.TournamentSelector;
0053 import org.jenetics.util.Copyable;
0054 import org.jenetics.util.Factory;
0055 import org.jenetics.util.NanoClock;
0056
0057 /**
0058 * Genetic algorithm <em>engine</em> which is the main class. The following
0059 * example shows the main steps in initializing and executing the GA.
0060 *
0061 * <pre>{@code
0062 * public class RealFunction {
0063 * // Definition of the fitness function.
0064 * private static Double eval(final Genotype<DoubleGene> gt) {
0065 * final double x = gt.getGene().doubleValue();
0066 * return cos(0.5 + sin(x))*cos(x);
0067 * }
0068 *
0069 * public static void main(String[] args) {
0070 * // Create/configuring the engine via its builder.
0071 * final Engine<DoubleGene, Double> engine = Engine
0072 * .builder(
0073 * RealFunction::eval,
0074 * DoubleChromosome.of(0.0, 2.0*PI))
0075 * .populationSize(500)
0076 * .optimize(Optimize.MINIMUM)
0077 * .alterers(
0078 * new Mutator<>(0.03),
0079 * new MeanAlterer<>(0.6))
0080 * .build();
0081 *
0082 * // Execute the GA (engine).
0083 * final Phenotype<DoubleGene, Double> result = engine.stream()
0084 * // Truncate the evolution stream if no better individual could
0085 * // be found after 5 consecutive generations.
0086 * .limit(bySteadyFitness(5))
0087 * // Terminate the evolution after maximal 100 generations.
0088 * .limit(100)
0089 * .collect(toBestPhenotype());
0090 * }
0091 * }
0092 * }</pre>
0093 *
0094 * The architecture allows to decouple the configuration of the engine from the
0095 * execution. The {@code Engine} is configured via the {@code Engine.Builder}
0096 * class and can't be changed after creation. The actual <i>evolution</i> is
0097 * performed by the {@link EvolutionStream}, which is created by the
0098 * {@code Engine}.
0099 * <p>
0100 * <em>
0101 * <b>This class is thread safe:</b>
0102 * No mutable state is maintained by the engine. Therefore it is save to
0103 * create multiple evolution streams with one engine, which may be actually
0104 * used in different threads.
0105 * </em>
0106 *
0107 * @see Engine.Builder
0108 * @see EvolutionStart
0109 * @see EvolutionResult
0110 * @see EvolutionStream
0111 * @see EvolutionStatistics
0112 * @see Codec
0113 *
0114 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
0115 * @since 3.0
0116 * @version 3.7
0117 */
0118 public final class Engine<
0119 G extends Gene<?, G>,
0120 C extends Comparable<? super C>
0121 >
0122 implements Function<EvolutionStart<G, C>, EvolutionResult<G, C>>
0123 {
0124
0125 // Needed context for population evolving.
0126 private final Function<? super Genotype<G>, ? extends C> _fitnessFunction;
0127 private final Function<? super C, ? extends C> _fitnessScaler;
0128 private final Factory<Genotype<G>> _genotypeFactory;
0129 private final Selector<G, C> _survivorsSelector;
0130 private final Selector<G, C> _offspringSelector;
0131 private final Alterer<G, C> _alterer;
0132 private final Predicate<? super Phenotype<G, C>> _validator;
0133 private final Optimize _optimize;
0134 private final int _offspringCount;
0135 private final int _survivorsCount;
0136 private final long _maximalPhenotypeAge;
0137
0138 // Execution context for concurrent execution of evolving steps.
0139 private final TimedExecutor _executor;
0140 private final Clock _clock;
0141
0142 // Additional parameters.
0143 private final int _individualCreationRetries;
0144
0145
0146 /**
0147 * Create a new GA engine with the given parameters.
0148 *
0149 * @param genotypeFactory the genotype factory this GA is working with.
0150 * @param fitnessFunction the fitness function this GA is using.
0151 * @param fitnessScaler the fitness scaler this GA is using.
0152 * @param survivorsSelector the selector used for selecting the survivors
0153 * @param offspringSelector the selector used for selecting the offspring
0154 * @param alterer the alterer used for altering the offspring
0155 * @param validator phenotype validator which can override the default
0156 * implementation the {@link Phenotype#isValid()} method.
0157 * @param optimize the kind of optimization (minimize or maximize)
0158 * @param offspringCount the number of the offspring individuals
0159 * @param survivorsCount the number of the survivor individuals
0160 * @param maximalPhenotypeAge the maximal age of an individual
0161 * @param executor the executor used for executing the single evolve steps
0162 * @param clock the clock used for calculating the timing results
0163 * @param individualCreationRetries the maximal number of attempts for
0164 * creating a valid individual.
0165 * @throws NullPointerException if one of the arguments is {@code null}
0166 * @throws IllegalArgumentException if the given integer values are smaller
0167 * than one.
0168 */
0169 Engine(
0170 final Function<? super Genotype<G>, ? extends C> fitnessFunction,
0171 final Function<? super C, ? extends C> fitnessScaler,
0172 final Factory<Genotype<G>> genotypeFactory,
0173 final Selector<G, C> survivorsSelector,
0174 final Selector<G, C> offspringSelector,
0175 final Alterer<G, C> alterer,
0176 final Predicate<? super Phenotype<G, C>> validator,
0177 final Optimize optimize,
0178 final int offspringCount,
0179 final int survivorsCount,
0180 final long maximalPhenotypeAge,
0181 final Executor executor,
0182 final Clock clock,
0183 final int individualCreationRetries
0184 ) {
0185 _fitnessFunction = requireNonNull(fitnessFunction);
0186 _fitnessScaler = requireNonNull(fitnessScaler);
0187 _genotypeFactory = requireNonNull(genotypeFactory);
0188 _survivorsSelector = requireNonNull(survivorsSelector);
0189 _offspringSelector = requireNonNull(offspringSelector);
0190 _alterer = requireNonNull(alterer);
0191 _validator = requireNonNull(validator);
0192 _optimize = requireNonNull(optimize);
0193
0194 _offspringCount = require.nonNegative(offspringCount);
0195 _survivorsCount = require.nonNegative(survivorsCount);
0196 _maximalPhenotypeAge = require.positive(maximalPhenotypeAge);
0197
0198 _executor = new TimedExecutor(requireNonNull(executor));
0199 _clock = requireNonNull(clock);
0200
0201 if (individualCreationRetries < 0) {
0202 throw new IllegalArgumentException(format(
0203 "Retry count must not be negative: %d",
0204 individualCreationRetries
0205 ));
0206 }
0207 _individualCreationRetries = individualCreationRetries;
0208 }
0209
0210 /**
0211 * Perform one evolution step with the given {@code population} and
0212 * {@code generation}. New phenotypes are created with the fitness function
0213 * and fitness scaler defined by this <em>engine</em>
0214 * <p>
0215 * <em>This method is thread-safe.</em>
0216 *
0217 * @see #evolve(EvolutionStart)
0218 *
0219 * @param population the population to evolve
0220 * @param generation the current generation; used for calculating the
0221 * phenotype age.
0222 * @return the evolution result
0223 * @throws java.lang.NullPointerException if the given {@code population} is
0224 * {@code null}
0225 * @throws IllegalArgumentException if the given {@code generation} is
0226 * smaller then one
0227 */
0228 public EvolutionResult<G, C> evolve(
0229 final Population<G, C> population,
0230 final long generation
0231 ) {
0232 return evolve(EvolutionStart.of(population, generation));
0233 }
0234
0235 /**
0236 * Perform one evolution step with the given evolution {@code start} object
0237 * New phenotypes are created with the fitness function and fitness scaler
0238 * defined by this <em>engine</em>
0239 * <p>
0240 * <em>This method is thread-safe.</em>
0241 *
0242 * @since 3.1
0243 * @see #evolve(org.jenetics.Population, long)
0244 *
0245 * @param start the evolution start object
0246 * @return the evolution result
0247 * @throws java.lang.NullPointerException if the given evolution
0248 * {@code start} is {@code null}
0249 */
0250 public EvolutionResult<G, C> evolve(final EvolutionStart<G, C> start) {
0251 final Timer timer = Timer.of().start();
0252
0253 final Population<G, C> startPopulation = start.getPopulation();
0254
0255 // Initial evaluation of the population.
0256 final Timer evaluateTimer = Timer.of(_clock).start();
0257 evaluate(startPopulation);
0258 evaluateTimer.stop();
0259
0260 // Select the offspring population.
0261 final CompletableFuture<TimedResult<Population<G, C>>> offspring =
0262 _executor.async(() ->
0263 selectOffspring(startPopulation),
0264 _clock
0265 );
0266
0267 // Select the survivor population.
0268 final CompletableFuture<TimedResult<Population<G, C>>> survivors =
0269 _executor.async(() ->
0270 selectSurvivors(startPopulation),
0271 _clock
0272 );
0273
0274 // Altering the offspring population.
0275 final CompletableFuture<TimedResult<AlterResult<G, C>>> alteredOffspring =
0276 _executor.thenApply(offspring, p ->
0277 alter(p.result, start.getGeneration()),
0278 _clock
0279 );
0280
0281 // Filter and replace invalid and to old survivor individuals.
0282 final CompletableFuture<TimedResult<FilterResult<G, C>>> filteredSurvivors =
0283 _executor.thenApply(survivors, pop ->
0284 filter(pop.result, start.getGeneration()),
0285 _clock
0286 );
0287
0288 // Filter and replace invalid and to old offspring individuals.
0289 final CompletableFuture<TimedResult<FilterResult<G, C>>> filteredOffspring =
0290 _executor.thenApply(alteredOffspring, pop ->
0291 filter(pop.result.population, start.getGeneration()),
0292 _clock
0293 );
0294
0295 // Combining survivors and offspring to the new population.
0296 final CompletableFuture<Population<G, C>> population =
0297 filteredSurvivors.thenCombineAsync(filteredOffspring, (s, o) -> {
0298 final Population<G, C> pop = s.result.population;
0299 pop.addAll(o.result.population);
0300 return pop;
0301 },
0302 _executor.get()
0303 );
0304
0305 // Evaluate the fitness-function and wait for result.
0306 final Population<G, C> pop = population.join();
0307 final TimedResult<Population<G, C>> result = TimedResult
0308 .of(() -> evaluate(pop), _clock)
0309 .get();
0310
0311
0312 final EvolutionDurations durations = EvolutionDurations.of(
0313 offspring.join().duration,
0314 survivors.join().duration,
0315 alteredOffspring.join().duration,
0316 filteredOffspring.join().duration,
0317 filteredSurvivors.join().duration,
0318 result.duration.plus(evaluateTimer.getTime()),
0319 timer.stop().getTime()
0320 );
0321
0322 final int killCount =
0323 filteredOffspring.join().result.killCount +
0324 filteredSurvivors.join().result.killCount;
0325
0326 final int invalidCount =
0327 filteredOffspring.join().result.invalidCount +
0328 filteredSurvivors.join().result.invalidCount;
0329
0330 return EvolutionResult.of(
0331 _optimize,
0332 result.result,
0333 start.getGeneration(),
0334 durations,
0335 killCount,
0336 invalidCount,
0337 alteredOffspring.join().result.alterCount
0338 );
0339 }
0340
0341 /**
0342 * This method is an <i>alias</i> for the {@link #evolve(EvolutionStart)}
0343 * method.
0344 *
0345 * @since 3.1
0346 */
0347 @Override
0348 public EvolutionResult<G, C> apply(final EvolutionStart<G, C> start) {
0349 return evolve(start);
0350 }
0351
0352 // Selects the survivors population. A new population object is returned.
0353 private Population<G, C> selectSurvivors(final Population<G, C> population) {
0354 return _survivorsCount > 0
0355 ?_survivorsSelector.select(population, _survivorsCount, _optimize)
0356 : Population.empty();
0357 }
0358
0359 // Selects the offspring population. A new population object is returned.
0360 private Population<G, C> selectOffspring(final Population<G, C> population) {
0361 return _offspringCount > 0
0362 ? _offspringSelector.select(population, _offspringCount, _optimize)
0363 : Population.empty();
0364 }
0365
0366 // Filters out invalid and to old individuals. Filtering is done in place.
0367 private FilterResult<G, C> filter(
0368 final Population<G, C> population,
0369 final long generation
0370 ) {
0371 int killCount = 0;
0372 int invalidCount = 0;
0373
0374 for (int i = 0, n = population.size(); i < n; ++i) {
0375 final Phenotype<G, C> individual = population.get(i);
0376
0377 if (!_validator.test(individual)) {
0378 population.set(i, newPhenotype(generation));
0379 ++invalidCount;
0380 } else if (individual.getAge(generation) > _maximalPhenotypeAge) {
0381 population.set(i, newPhenotype(generation));
0382 ++killCount;
0383 }
0384 }
0385
0386 return new FilterResult<>(population, killCount, invalidCount);
0387 }
0388
0389 // Create a new and valid phenotype
0390 private Phenotype<G, C> newPhenotype(final long generation) {
0391 int count = 0;
0392 Phenotype<G, C> phenotype;
0393 do {
0394 phenotype = Phenotype.of(
0395 _genotypeFactory.newInstance(),
0396 generation,
0397 _fitnessFunction,
0398 _fitnessScaler
0399 );
0400 } while (++count < _individualCreationRetries &&
0401 !_validator.test(phenotype));
0402
0403 return phenotype;
0404 }
0405
0406 // Alters the given population. The altering is done in place.
0407 private AlterResult<G, C> alter(
0408 final Population<G,C> population,
0409 final long generation
0410 ) {
0411 return new AlterResult<>(
0412 population,
0413 _alterer.alter(population, generation)
0414 );
0415 }
0416
0417 // Evaluates the fitness function of the give population concurrently.
0418 private Population<G, C> evaluate(final Population<G, C> population) {
0419 try (Concurrency c = Concurrency.with(_executor.get())) {
0420 c.execute(population);
0421 }
0422 return population;
0423 }
0424
0425
0426 /* *************************************************************************
0427 * Evolution Stream/Iterator creation.
0428 **************************************************************************/
0429
0430 /**
0431 * Create a new <b>infinite</b> evolution iterator with a newly created
0432 * population. This is an alternative way for evolution. It lets the user
0433 * start, stop and resume the evolution process whenever desired.
0434 *
0435 * @return a new <b>infinite</b> evolution iterator
0436 */
0437 public Iterator<EvolutionResult<G, C>> iterator() {
0438 return new EvolutionIterator<>(
0439 this::evolutionStart,
0440 this::evolve
0441 );
0442 }
0443
0444 /**
0445 * Create a new <b>infinite</b> evolution stream with a newly created
0446 * population.
0447 *
0448 * @return a new evolution stream.
0449 */
0450 public EvolutionStream<G, C> stream() {
0451 return EvolutionStream.of(this::evolutionStart, this::evolve);
0452 }
0453
0454 private EvolutionStart<G, C> evolutionStart() {
0455 final int generation = 1;
0456 final int size = _offspringCount + _survivorsCount;
0457
0458 final Population<G, C> population = new Population<G, C>(size)
0459 .fill(() -> newPhenotype(generation), size);
0460
0461 return EvolutionStart.of(population, generation);
0462 }
0463
0464 /**
0465 * Create a new <b>infinite</b> evolution iterator with the given initial
0466 * individuals. If an empty {@code Iterable} is given, the engines genotype
0467 * factory is used for creating the population.
0468 *
0469 * @param genotypes the initial individuals used for the evolution iterator.
0470 * Missing individuals are created and individuals not needed are
0471 * skipped.
0472 * @return a new <b>infinite</b> evolution iterator
0473 * @throws java.lang.NullPointerException if the given {@code genotypes} is
0474 * {@code null}.
0475 */
0476 public Iterator<EvolutionResult<G, C>> iterator(
0477 final Iterable<Genotype<G>> genotypes
0478 ) {
0479 requireNonNull(genotypes);
0480
0481 return new EvolutionIterator<>(
0482 () -> evolutionStart(genotypes, 1),
0483 this::evolve
0484 );
0485 }
0486
0487 /**
0488 * Create a new <b>infinite</b> evolution stream with the given initial
0489 * individuals. If an empty {@code Iterable} is given, the engines genotype
0490 * factory is used for creating the population.
0491 *
0492 * @since 3.7
0493 *
0494 * @param genotypes the initial individuals used for the evolution stream.
0495 * Missing individuals are created and individuals not needed are
0496 * skipped.
0497 * @return a new evolution stream.
0498 * @throws java.lang.NullPointerException if the given {@code genotypes} is
0499 * {@code null}.
0500 */
0501 public EvolutionStream<G, C> stream(final Iterable<Genotype<G>> genotypes) {
0502 requireNonNull(genotypes);
0503
0504 return EvolutionStream.of(
0505 () -> evolutionStart(genotypes, 1),
0506 this::evolve
0507 );
0508 }
0509
0510 private EvolutionStart<G, C> evolutionStart(
0511 final Iterable<Genotype<G>> genotypes,
0512 final long generation
0513 ) {
0514 final Stream<Phenotype<G, C>> stream = Stream.concat(
0515 StreamSupport.stream(genotypes.spliterator(), false)
0516 .map(gt -> Phenotype.of(
0517 gt, generation, _fitnessFunction, _fitnessScaler)),
0518 Stream.generate(() -> newPhenotype(generation))
0519 );
0520
0521 final Population<G, C> population = stream
0522 .limit(getPopulationSize())
0523 .collect(toPopulation());
0524
0525 return EvolutionStart.of(population, generation);
0526 }
0527
0528 /**
0529 * Create a new <b>infinite</b> evolution iterator with the given initial
0530 * individuals. If an empty {@code Iterable} is given, the engines genotype
0531 * factory is used for creating the population.
0532 *
0533 * @since 3.7
0534 *
0535 * @param genotypes the initial individuals used for the evolution iterator.
0536 * Missing individuals are created and individuals not needed are
0537 * skipped.
0538 * @param generation the generation the stream starts from; must be greater
0539 * than zero.
0540 * @return a new <b>infinite</b> evolution iterator
0541 * @throws java.lang.NullPointerException if the given {@code genotypes} is
0542 * {@code null}.
0543 * @throws IllegalArgumentException if the given {@code generation} is
0544 * smaller then one
0545 */
0546 public Iterator<EvolutionResult<G, C>> iterator(
0547 final Iterable<Genotype<G>> genotypes,
0548 final long generation
0549 ) {
0550 requireNonNull(genotypes);
0551 require.positive(generation);
0552
0553 return new EvolutionIterator<>(
0554 () -> evolutionStart(genotypes, generation),
0555 this::evolve
0556 );
0557 }
0558
0559 /**
0560 * Create a new <b>infinite</b> evolution stream with the given initial
0561 * individuals. If an empty {@code Iterable} is given, the engines genotype
0562 * factory is used for creating the population.
0563 *
0564 * @since 3.7
0565 *
0566 * @param genotypes the initial individuals used for the evolution stream.
0567 * Missing individuals are created and individuals not needed are
0568 * skipped.
0569 * @param generation the generation the stream starts from; must be greater
0570 * than zero.
0571 * @return a new evolution stream.
0572 * @throws java.lang.NullPointerException if the given {@code genotypes} is
0573 * {@code null}.
0574 * @throws IllegalArgumentException if the given {@code generation} is
0575 * smaller then one
0576 */
0577 public EvolutionStream<G, C> stream(
0578 final Iterable<Genotype<G>> genotypes,
0579 final long generation
0580 ) {
0581 requireNonNull(genotypes);
0582
0583 return EvolutionStream.of(
0584 () -> evolutionStart(genotypes, generation),
0585 this::evolve
0586 );
0587 }
0588
0589 /**
0590 * Create a new <b>infinite</b> evolution iterator with the given initial
0591 * population. If an empty {@code Population} is given, the engines genotype
0592 * factory is used for creating the population. The given population might
0593 * be the result of an other engine and this method allows to start the
0594 * evolution with the outcome of an different engine. The fitness function
0595 * and the fitness scaler are replaced by the one defined for this engine.
0596 *
0597 * @since 3.7
0598 *
0599 * @param population the initial individuals used for the evolution iterator.
0600 * Missing individuals are created and individuals not needed are
0601 * skipped.
0602 * @return a new <b>infinite</b> evolution iterator
0603 * @throws java.lang.NullPointerException if the given {@code population} is
0604 * {@code null}.
0605 */
0606 public Iterator<EvolutionResult<G, C>> iterator(
0607 final Population<G, C> population
0608 ) {
0609 requireNonNull(population);
0610
0611 return new EvolutionIterator<>(
0612 () -> evolutionStart(population, 1),
0613 this::evolve
0614 );
0615 }
0616
0617 /**
0618 * Create a new <b>infinite</b> evolution stream with the given initial
0619 * population. If an empty {@code Population} is given, the engines genotype
0620 * factory is used for creating the population. The given population might
0621 * be the result of an other engine and this method allows to start the
0622 * evolution with the outcome of an different engine. The fitness function
0623 * and the fitness scaler are replaced by the one defined for this engine.
0624 *
0625 * @param population the initial individuals used for the evolution stream.
0626 * Missing individuals are created and individuals not needed are
0627 * skipped.
0628 * @return a new evolution stream.
0629 * @throws java.lang.NullPointerException if the given {@code population} is
0630 * {@code null}.
0631 */
0632 public EvolutionStream<G, C> stream(
0633 final Population<G, C> population
0634 ) {
0635 requireNonNull(population);
0636
0637 return EvolutionStream.of(
0638 () -> evolutionStart(population, 1),
0639 this::evolve
0640 );
0641 }
0642
0643 private EvolutionStart<G, C> evolutionStart(
0644 final Population<G, C> population,
0645 final long generation
0646 ) {
0647 final Stream<Phenotype<G, C>> stream = Stream.concat(
0648 population.stream()
0649 .map(p -> p.newInstance(
0650 p.getGeneration(),
0651 _fitnessFunction,
0652 _fitnessScaler)),
0653 Stream.generate(() -> newPhenotype(generation))
0654 );
0655
0656 final Population<G, C> pop = stream
0657 .limit(getPopulationSize())
0658 .collect(toPopulation());
0659
0660 return EvolutionStart.of(pop, generation);
0661 }
0662
0663 /**
0664 * Create a new <b>infinite</b> evolution iterator with the given initial
0665 * population. If an empty {@code Population} is given, the engines genotype
0666 * factory is used for creating the population. The given population might
0667 * be the result of an other engine and this method allows to start the
0668 * evolution with the outcome of an different engine. The fitness function
0669 * and the fitness scaler are replaced by the one defined for this engine.
0670 *
0671 * @param population the initial individuals used for the evolution iterator.
0672 * Missing individuals are created and individuals not needed are
0673 * skipped.
0674 * @param generation the generation the iterator starts from; must be greater
0675 * than zero.
0676 * @return a new <b>infinite</b> evolution iterator
0677 * @throws java.lang.NullPointerException if the given {@code population} is
0678 * {@code null}.
0679 * @throws IllegalArgumentException if the given {@code generation} is smaller
0680 * then one
0681 */
0682 public Iterator<EvolutionResult<G, C>> iterator(
0683 final Population<G, C> population,
0684 final long generation
0685 ) {
0686 requireNonNull(population);
0687 require.positive(generation);
0688
0689 return new EvolutionIterator<>(
0690 () -> evolutionStart(population, generation),
0691 this::evolve
0692 );
0693 }
0694
0695 /**
0696 * Create a new <b>infinite</b> evolution stream with the given initial
0697 * population. If an empty {@code Population} is given, the engines genotype
0698 * factory is used for creating the population. The given population might
0699 * be the result of an other engine and this method allows to start the
0700 * evolution with the outcome of an different engine. The fitness function
0701 * and the fitness scaler are replaced by the one defined for this engine.
0702 *
0703 * @param population the initial individuals used for the evolution stream.
0704 * Missing individuals are created and individuals not needed are
0705 * skipped.
0706 * @param generation the generation the stream starts from; must be greater
0707 * than zero.
0708 * @return a new evolution stream.
0709 * @throws java.lang.NullPointerException if the given {@code population} is
0710 * {@code null}.
0711 * @throws IllegalArgumentException if the given {@code generation} is
0712 * smaller then one
0713 */
0714 public EvolutionStream<G, C> stream(
0715 final Population<G, C> population,
0716 final long generation
0717 ) {
0718 requireNonNull(population);
0719 require.positive(generation);
0720
0721 return EvolutionStream.of(
0722 () -> evolutionStart(population, generation),
0723 this::evolve
0724 );
0725 }
0726
0727 /**
0728 * Create a new <b>infinite</b> evolution iterator starting with a
0729 * previously evolved {@link EvolutionResult}. The iterator is initialized
0730 * with the population of the given {@code result} and its total generation
0731 * {@link EvolutionResult#getTotalGenerations()}.
0732 *
0733 * @since 3.7
0734 *
0735 * @param result the previously evolved {@code EvolutionResult}
0736 * @return a new evolution stream, which continues a previous one
0737 * @throws NullPointerException if the given evolution {@code result} is
0738 * {@code null}
0739 */
0740 public Iterator<EvolutionResult<G, C>> iterator(
0741 final EvolutionResult<G, C> result
0742 ) {
0743 return iterator(result.getPopulation(), result.getTotalGenerations());
0744 }
0745
0746 /**
0747 * Create a new {@code EvolutionStream} starting with a previously evolved
0748 * {@link EvolutionResult}. The stream is initialized with the population
0749 * of the given {@code result} and its total generation
0750 * {@link EvolutionResult#getTotalGenerations()}.
0751 *
0752 * <pre>{@code
0753 * private static final Problem<Double, DoubleGene, Double>
0754 * PROBLEM = Problem.of(
0755 * x -> cos(0.5 + sin(x))*cos(x),
0756 * codecs.ofScalar(DoubleRange.of(0.0, 2.0*PI))
0757 * );
0758 *
0759 * private static final Engine<DoubleGene, Double>
0760 * ENGINE = Engine.builder(PROBLEM)
0761 * .optimize(Optimize.MINIMUM)
0762 * .offspringSelector(new RouletteWheelSelector<>())
0763 * .build();
0764 *
0765 * public static void main(final String[] args) throws IOException {
0766 * // Result of the first evolution run.
0767 * final EvolutionResult<DoubleGene, Double> rescue = ENGINE.stream()
0768 * .limit(limit.bySteadyFitness(10))
0769 * .collect(EvolutionResult.toBestEvolutionResult());
0770 *
0771 * // Save the result of the first run into a file.
0772 * final Path path = Paths.get("result.bin");
0773 * IO.object.write(rescue, path);
0774 *
0775 * // Load the previous result and continue evolution.
0776 * \@SuppressWarnings("unchecked")
0777 * final EvolutionResult<DoubleGene, Double> result = ENGINE
0778 * .stream((EvolutionResult<DoubleGene, Double>)IO.object.read(path))
0779 * .limit(limit.bySteadyFitness(20))
0780 * .collect(EvolutionResult.toBestEvolutionResult());
0781 *
0782 * System.out.println(result.getBestPhenotype());
0783 * }
0784 * }</pre>
0785 *
0786 * The example above shows how to save an {@link EvolutionResult} from a
0787 * first run, save it to disk and continue the evolution.
0788 *
0789 * @since 3.7
0790 *
0791 * @param result the previously evolved {@code EvolutionResult}
0792 * @return a new evolution stream, which continues a previous one
0793 * @throws NullPointerException if the given evolution {@code result} is
0794 * {@code null}
0795 */
0796 public EvolutionStream<G, C> stream(final EvolutionResult<G, C> result) {
0797 return stream(result.getPopulation(), result.getTotalGenerations());
0798 }
0799
0800
0801 /* *************************************************************************
0802 * Property access methods.
0803 **************************************************************************/
0804
0805 /**
0806 * Return the fitness function of the GA engine.
0807 *
0808 * @return the fitness function
0809 */
0810 public Function<? super Genotype<G>, ? extends C> getFitnessFunction() {
0811 return _fitnessFunction;
0812 }
0813
0814 /**
0815 * Return the fitness scaler of the GA engine.
0816 *
0817 * @return the fitness scaler
0818 */
0819 public Function<? super C, ? extends C> getFitnessScaler() {
0820 return _fitnessScaler;
0821 }
0822
0823 /**
0824 * Return the used genotype {@link Factory} of the GA. The genotype factory
0825 * is used for creating the initial population and new, random individuals
0826 * when needed (as replacement for invalid and/or died genotypes).
0827 *
0828 * @return the used genotype {@link Factory} of the GA.
0829 */
0830 public Factory<Genotype<G>> getGenotypeFactory() {
0831 return _genotypeFactory;
0832 }
0833
0834 /**
0835 * Return the used survivor {@link Selector} of the GA.
0836 *
0837 * @return the used survivor {@link Selector} of the GA.
0838 */
0839 public Selector<G, C> getSurvivorsSelector() {
0840 return _survivorsSelector;
0841 }
0842
0843 /**
0844 * Return the used offspring {@link Selector} of the GA.
0845 *
0846 * @return the used offspring {@link Selector} of the GA.
0847 */
0848 public Selector<G, C> getOffspringSelector() {
0849 return _offspringSelector;
0850 }
0851
0852 /**
0853 * Return the used {@link Alterer} of the GA.
0854 *
0855 * @return the used {@link Alterer} of the GA.
0856 */
0857 public Alterer<G, C> getAlterer() {
0858 return _alterer;
0859 }
0860
0861 /**
0862 * Return the number of selected offsprings.
0863 *
0864 * @return the number of selected offsprings
0865 */
0866 public int getOffspringCount() {
0867 return _offspringCount;
0868 }
0869
0870 /**
0871 * The number of selected survivors.
0872 *
0873 * @return the number of selected survivors
0874 */
0875 public int getSurvivorsCount() {
0876 return _survivorsCount;
0877 }
0878
0879 /**
0880 * Return the number of individuals of a population.
0881 *
0882 * @return the number of individuals of a population
0883 */
0884 public int getPopulationSize() {
0885 return _offspringCount + _survivorsCount;
0886 }
0887
0888 /**
0889 * Return the maximal allowed phenotype age.
0890 *
0891 * @return the maximal allowed phenotype age
0892 */
0893 public long getMaximalPhenotypeAge() {
0894 return _maximalPhenotypeAge;
0895 }
0896
0897 /**
0898 * Return the optimization strategy.
0899 *
0900 * @return the optimization strategy
0901 */
0902 public Optimize getOptimize() {
0903 return _optimize;
0904 }
0905
0906 /**
0907 * Return the {@link Clock} the engine is using for measuring the execution
0908 * time.
0909 *
0910 * @return the clock used for measuring the execution time
0911 */
0912 public Clock getClock() {
0913 return _clock;
0914 }
0915
0916 /**
0917 * Return the {@link Executor} the engine is using for executing the
0918 * evolution steps.
0919 *
0920 * @return the executor used for performing the evolution steps
0921 */
0922 public Executor getExecutor() {
0923 return _executor.get();
0924 }
0925
0926
0927 /* *************************************************************************
0928 * Builder methods.
0929 **************************************************************************/
0930
0931 /**
0932 * Create a new evolution {@code Engine.Builder} initialized with the values
0933 * of the current evolution {@code Engine}. With this method, the evolution
0934 * engine can serve as a template for a new one.
0935 *
0936 * @return a new engine builder
0937 */
0938 public Builder<G, C> builder() {
0939 return new Builder<G, C>(_genotypeFactory, _fitnessFunction)
0940 .alterers(_alterer)
0941 .clock(_clock)
0942 .executor(_executor.get())
0943 .fitnessScaler(_fitnessScaler)
0944 .maximalPhenotypeAge(_maximalPhenotypeAge)
0945 .offspringFraction((double)_offspringCount/(double)getPopulationSize())
0946 .offspringSelector(_offspringSelector)
0947 .optimize(_optimize)
0948 .phenotypeValidator(_validator)
0949 .populationSize(getPopulationSize())
0950 .survivorsSelector(_survivorsSelector)
0951 .individualCreationRetries(_individualCreationRetries);
0952 }
0953
0954 /**
0955 * Create a new evolution {@code Engine.Builder} for the given
0956 * {@link Problem}.
0957 *
0958 * @since 3.4
0959 *
0960 * @param problem the problem to be solved by the evolution {@code Engine}
0961 * @param <T> the (<i>native</i>) argument type of the problem fitness function
0962 * @param <G> the gene type the evolution engine is working with
0963 * @param <C> the result type of the fitness function
0964 * @return Create a new evolution {@code Engine.Builder}
0965 */
0966 public static <T, G extends Gene<?, G>, C extends Comparable<? super C>>
0967 Builder<G, C> builder(final Problem<T, G, C> problem) {
0968 return builder(problem.fitness(), problem.codec());
0969 }
0970
0971 /**
0972 * Create a new evolution {@code Engine.Builder} with the given fitness
0973 * function and genotype factory.
0974 *
0975 * @param ff the fitness function
0976 * @param genotypeFactory the genotype factory
0977 * @param <G> the gene type
0978 * @param <C> the fitness function result type
0979 * @return a new engine builder
0980 * @throws java.lang.NullPointerException if one of the arguments is
0981 * {@code null}.
0982 */
0983 public static <G extends Gene<?, G>, C extends Comparable<? super C>>
0984 Builder<G, C> builder(
0985 final Function<? super Genotype<G>, ? extends C> ff,
0986 final Factory<Genotype<G>> genotypeFactory
0987 ) {
0988 return new Builder<>(genotypeFactory, ff);
0989 }
0990
0991 /**
0992 * Create a new evolution {@code Engine.Builder} with the given fitness
0993 * function and chromosome templates.
0994 *
0995 * @param ff the fitness function
0996 * @param chromosome the first chromosome
0997 * @param chromosomes the chromosome templates
0998 * @param <G> the gene type
0999 * @param <C> the fitness function result type
1000 * @return a new engine builder
1001 * @throws java.lang.NullPointerException if one of the arguments is
1002 * {@code null}.
1003 */
1004 @SafeVarargs
1005 public static <G extends Gene<?, G>, C extends Comparable<? super C>>
1006 Builder<G, C> builder(
1007 final Function<? super Genotype<G>, ? extends C> ff,
1008 final Chromosome<G> chromosome,
1009 final Chromosome<G>... chromosomes
1010 ) {
1011 return new Builder<>(Genotype.of(chromosome, chromosomes), ff);
1012 }
1013
1014 /**
1015 * Create a new evolution {@code Engine.Builder} with the given fitness
1016 * function and problem {@code codec}.
1017 *
1018 * @since 3.2
1019 *
1020 * @param ff the fitness function
1021 * @param codec the problem codec
1022 * @param <T> the fitness function input type
1023 * @param <C> the fitness function result type
1024 * @param <G> the gene type
1025 * @return a new engine builder
1026 * @throws java.lang.NullPointerException if one of the arguments is
1027 * {@code null}.
1028 */
1029 public static <T, G extends Gene<?, G>, C extends Comparable<? super C>>
1030 Builder<G, C> builder(
1031 final Function<? super T, ? extends C> ff,
1032 final Codec<T, G> codec
1033 ) {
1034 return builder(ff.compose(codec.decoder()), codec.encoding());
1035 }
1036
1037
1038 /* *************************************************************************
1039 * Inner classes
1040 **************************************************************************/
1041
1042 /**
1043 * Builder class for building GA {@code Engine} instances.
1044 *
1045 * @see Engine
1046 *
1047 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
1048 * @since 3.0
1049 * @version 3.8
1050 */
1051 public static final class Builder<
1052 G extends Gene<?, G>,
1053 C extends Comparable<? super C>
1054 >
1055 implements Copyable<Builder<G, C>>
1056 {
1057
1058 // No default values for this properties.
1059 private Function<? super Genotype<G>, ? extends C> _fitnessFunction;
1060 private Factory<Genotype<G>> _genotypeFactory;
1061
1062 // This are the properties which default values.
1063 private Function<? super C, ? extends C> _fitnessScaler = a -> a;
1064 private Selector<G, C> _survivorsSelector = new TournamentSelector<>(3);
1065 private Selector<G, C> _offspringSelector = new TournamentSelector<>(3);
1066 private Alterer<G, C> _alterer = Alterer.of(
1067 new SinglePointCrossover<G, C>(0.2),
1068 new Mutator<>(0.15)
1069 );
1070 private Predicate<? super Phenotype<G, C>> _validator = Phenotype::isValid;
1071 private Optimize _optimize = Optimize.MAXIMUM;
1072 private double _offspringFraction = 0.6;
1073 private int _populationSize = 50;
1074 private long _maximalPhenotypeAge = 70;
1075
1076 // Engine execution environment.
1077 private Executor _executor = ForkJoinPool.commonPool();
1078 private Clock _clock = NanoClock.systemUTC();
1079
1080 private int _individualCreationRetries = 10;
1081
1082 private Builder(
1083 final Factory<Genotype<G>> genotypeFactory,
1084 final Function<? super Genotype<G>, ? extends C> fitnessFunction
1085 ) {
1086 _genotypeFactory = requireNonNull(genotypeFactory);
1087 _fitnessFunction = requireNonNull(fitnessFunction);
1088 }
1089
1090 /**
1091 * Set the fitness function of the evolution {@code Engine}.
1092 *
1093 * @param function the fitness function to use in the GA {@code Engine}
1094 * @return {@code this} builder, for command chaining
1095 */
1096 public Builder<G, C> fitnessFunction(
1097 Function<? super Genotype<G>, ? extends C> function
1098 ) {
1099 _fitnessFunction = requireNonNull(function);
1100 return this;
1101 }
1102
1103 /**
1104 * Set the fitness scaler of the evolution {@code Engine}. <i>Default
1105 * value is set to the identity function.</i>
1106 *
1107 * @param scaler the fitness scale to use in the GA {@code Engine}
1108 * @return {@code this} builder, for command chaining
1109 */
1110 public Builder<G, C> fitnessScaler(
1111 final Function<? super C, ? extends C> scaler
1112 ) {
1113 _fitnessScaler = requireNonNull(scaler);
1114 return this;
1115 }
1116
1117 /**
1118 * The genotype factory used for creating new individuals.
1119 *
1120 * @param genotypeFactory the genotype factory for creating new
1121 * individuals.
1122 * @return {@code this} builder, for command chaining
1123 */
1124 public Builder<G, C> genotypeFactory(
1125 final Factory<Genotype<G>> genotypeFactory
1126 ) {
1127 _genotypeFactory = requireNonNull(genotypeFactory);
1128 return this;
1129 }
1130
1131 /**
1132 * The selector used for selecting the offspring population. <i>Default
1133 * values is set to {@code TournamentSelector<>(3)}.</i>
1134 *
1135 * @param selector used for selecting the offspring population
1136 * @return {@code this} builder, for command chaining
1137 */
1138 public Builder<G, C> offspringSelector(
1139 final Selector<G, C> selector
1140 ) {
1141 _offspringSelector = requireNonNull(selector);
1142 return this;
1143 }
1144
1145 /**
1146 * The selector used for selecting the survivors population. <i>Default
1147 * values is set to {@code TournamentSelector<>(3)}.</i>
1148 *
1149 * @param selector used for selecting survivors population
1150 * @return {@code this} builder, for command chaining
1151 */
1152 public Builder<G, C> survivorsSelector(
1153 final Selector<G, C> selector
1154 ) {
1155 _survivorsSelector = requireNonNull(selector);
1156 return this;
1157 }
1158
1159 /**
1160 * The selector used for selecting the survivors and offspring
1161 * population. <i>Default values is set to
1162 * {@code TournamentSelector<>(3)}.</i>
1163 *
1164 * @param selector used for selecting survivors and offspring population
1165 * @return {@code this} builder, for command chaining
1166 */
1167 public Builder<G, C> selector(final Selector<G, C> selector) {
1168 _offspringSelector = requireNonNull(selector);
1169 _survivorsSelector = requireNonNull(selector);
1170 return this;
1171 }
1172
1173 /**
1174 * The alterers used for alter the offspring population. <i>Default
1175 * values is set to {@code new SinglePointCrossover<>(0.2)} followed by
1176 * {@code new Mutator<>(0.15)}.</i>
1177 *
1178 * @param first the first alterer used for alter the offspring
1179 * population
1180 * @param rest the rest of the alterers used for alter the offspring
1181 * population
1182 * @return {@code this} builder, for command chaining
1183 * @throws java.lang.NullPointerException if one of the alterers is
1184 * {@code null}.
1185 */
1186 @SafeVarargs
1187 public final Builder<G, C> alterers(
1188 final Alterer<G, C> first,
1189 final Alterer<G, C>... rest
1190 ) {
1191 requireNonNull(first);
1192 Stream.of(rest).forEach(Objects::requireNonNull);
1193
1194 _alterer = rest.length == 0 ?
1195 first :
1196 Alterer.of(rest).compose(first);
1197
1198 return this;
1199 }
1200
1201 /**
1202 * The phenotype validator used for detecting invalid individuals.
1203 * Alternatively it is also possible to set the genotype validator with
1204 * {@link #genotypeFactory(Factory)}, which will replace any
1205 * previously set phenotype validators.
1206 *
1207 * <p><i>Default value is set to {@code Phenotype::isValid}.</i></p>
1208 *
1209 * @since 3.1
1210 *
1211 * @see #genotypeValidator(Predicate)
1212 *
1213 * @param validator the {@code validator} used for validating the
1214 * individuals (phenotypes).
1215 * @return {@code this} builder, for command chaining
1216 * @throws java.lang.NullPointerException if the {@code validator} is
1217 * {@code null}.
1218 */
1219 public Builder<G, C> phenotypeValidator(
1220 final Predicate<? super Phenotype<G, C>> validator
1221 ) {
1222 _validator = requireNonNull(validator);
1223 return this;
1224 }
1225
1226 /**
1227 * The genotype validator used for detecting invalid individuals.
1228 * Alternatively it is also possible to set the phenotype validator with
1229 * {@link #phenotypeValidator(Predicate)}, which will replace any
1230 * previously set genotype validators.
1231 *
1232 * <p><i>Default value is set to {@code Genotype::isValid}.</i></p>
1233 *
1234 * @since 3.1
1235 *
1236 * @see #phenotypeValidator(Predicate)
1237 *
1238 * @param validator the {@code validator} used for validating the
1239 * individuals (genotypes).
1240 * @return {@code this} builder, for command chaining
1241 * @throws java.lang.NullPointerException if the {@code validator} is
1242 * {@code null}.
1243 */
1244 public Builder<G, C> genotypeValidator(
1245 final Predicate<? super Genotype<G>> validator
1246 ) {
1247 requireNonNull(validator);
1248
1249 _validator = pt -> validator.test(pt.getGenotype());
1250 return this;
1251 }
1252
1253 /**
1254 * The optimization strategy used by the engine. <i>Default values is
1255 * set to {@code Optimize.MAXIMUM}.</i>
1256 *
1257 * @param optimize the optimization strategy used by the engine
1258 * @return {@code this} builder, for command chaining
1259 */
1260 public Builder<G, C> optimize(final Optimize optimize) {
1261 _optimize = requireNonNull(optimize);
1262 return this;
1263 }
1264
1265 /**
1266 * Set to a fitness maximizing strategy.
1267 *
1268 * @since 3.4
1269 *
1270 * @return {@code this} builder, for command chaining
1271 */
1272 public Builder<G, C> maximizing() {
1273 return optimize(Optimize.MAXIMUM);
1274 }
1275
1276 /**
1277 * Set to a fitness minimizing strategy.
1278 *
1279 * @since 3.4
1280 *
1281 * @return {@code this} builder, for command chaining
1282 */
1283 public Builder<G, C> minimizing() {
1284 return optimize(Optimize.MINIMUM);
1285 }
1286
1287 /**
1288 * The offspring fraction. <i>Default values is set to {@code 0.6}.</i>
1289 * This method call is equivalent to
1290 * {@code survivorsFraction(1 - offspringFraction)} and will override
1291 * any previously set survivors-fraction.
1292 *
1293 * @see #survivorsFraction(double)
1294 *
1295 * @param fraction the offspring fraction
1296 * @return {@code this} builder, for command chaining
1297 * @throws java.lang.IllegalArgumentException if the fraction is not
1298 * within the range [0, 1].
1299 */
1300 public Builder<G, C> offspringFraction(final double fraction) {
1301 _offspringFraction = probability(fraction);
1302 return this;
1303 }
1304
1305 /**
1306 * The survivors fraction. <i>Default values is set to {@code 0.4}.</i>
1307 * This method call is equivalent to
1308 * {@code offspringFraction(1 - survivorsFraction)} and will override
1309 * any previously set offspring-fraction.
1310 *
1311 * @since 3.8
1312 *
1313 * @see #offspringFraction(double)
1314 *
1315 * @param fraction the survivors fraction
1316 * @return {@code this} builder, for command chaining
1317 * @throws java.lang.IllegalArgumentException if the fraction is not
1318 * within the range [0, 1].
1319 */
1320 public Builder<G, C> survivorsFraction(final double fraction) {
1321 _offspringFraction = 1.0 - probability(fraction);
1322 return this;
1323 }
1324
1325 /**
1326 * The number of offspring individuals.
1327 *
1328 * @since 3.8
1329 *
1330 * @param size the number of offspring individuals.
1331 * @return {@code this} builder, for command chaining
1332 * @throws java.lang.IllegalArgumentException if the size is not
1333 * within the range [0, population-size].
1334 */
1335 public Builder<G, C> offspringSize(final int size) {
1336 if (size < 0) {
1337 throw new IllegalArgumentException(format(
1338 "Offspring size must be greater or equal zero, but was %s.",
1339 size
1340 ));
1341 }
1342
1343 return offspringFraction((double)size/(double)_populationSize);
1344 }
1345
1346 /**
1347 * The number of survivors.
1348 *
1349 * @since 3.8
1350 *
1351 * @param size the number of survivors.
1352 * @return {@code this} builder, for command chaining
1353 * @throws java.lang.IllegalArgumentException if the size is not
1354 * within the range [0, population-size].
1355 */
1356 public Builder<G, C> survivorsSize(final int size) {
1357 if (size < 0) {
1358 throw new IllegalArgumentException(format(
1359 "Survivors must be greater or equal zero, but was %s.",
1360 size
1361 ));
1362 }
1363
1364 return survivorsFraction((double)size/(double)_populationSize);
1365 }
1366
1367 /**
1368 * The number of individuals which form the population. <i>Default
1369 * values is set to {@code 50}.</i>
1370 *
1371 * @param size the number of individuals of a population
1372 * @return {@code this} builder, for command chaining
1373 * @throws java.lang.IllegalArgumentException if {@code size < 1}
1374 */
1375 public Builder<G, C> populationSize(final int size) {
1376 if (size < 1) {
1377 throw new IllegalArgumentException(format(
1378 "Population size must be greater than zero, but was %s.",
1379 size
1380 ));
1381 }
1382 _populationSize = size;
1383 return this;
1384 }
1385
1386 /**
1387 * The maximal allowed age of a phenotype. <i>Default values is set to
1388 * {@code 70}.</i>
1389 *
1390 * @param age the maximal phenotype age
1391 * @return {@code this} builder, for command chaining
1392 * @throws java.lang.IllegalArgumentException if {@code age < 1}
1393 */
1394 public Builder<G, C> maximalPhenotypeAge(final long age) {
1395 if (age < 1) {
1396 throw new IllegalArgumentException(format(
1397 "Phenotype age must be greater than one, but was %s.", age
1398 ));
1399 }
1400 _maximalPhenotypeAge = age;
1401 return this;
1402 }
1403
1404 /**
1405 * The executor used by the engine.
1406 *
1407 * @param executor the executor used by the engine
1408 * @return {@code this} builder, for command chaining
1409 */
1410 public Builder<G, C> executor(final Executor executor) {
1411 _executor = requireNonNull(executor);
1412 return this;
1413 }
1414
1415 /**
1416 * The clock used for calculating the execution durations.
1417 *
1418 * @param clock the clock used for calculating the execution durations
1419 * @return {@code this} builder, for command chaining
1420 */
1421 public Builder<G, C> clock(final Clock clock) {
1422 _clock = requireNonNull(clock);
1423 return this;
1424 }
1425
1426 /**
1427 * The maximal number of attempt before the {@code Engine} gives up
1428 * creating a valid individual ({@code Phenotype}). <i>Default values is
1429 * set to {@code 10}.</i>
1430 *
1431 * @since 3.1
1432 *
1433 * @param retries the maximal retry count
1434 * @throws IllegalArgumentException if the given retry {@code count} is
1435 * smaller than zero.
1436 * @return {@code this} builder, for command chaining
1437 */
1438 public Builder<G, C> individualCreationRetries(final int retries) {
1439 if (retries < 0) {
1440 throw new IllegalArgumentException(format(
1441 "Retry count must not be negative: %d",
1442 retries
1443 ));
1444 }
1445 _individualCreationRetries = retries;
1446 return this;
1447 }
1448
1449 /**
1450 * Builds an new {@code Engine} instance from the set properties.
1451 *
1452 * @return an new {@code Engine} instance from the set properties
1453 */
1454 public Engine<G, C> build() {
1455 return new Engine<>(
1456 _fitnessFunction,
1457 _fitnessScaler,
1458 _genotypeFactory,
1459 _survivorsSelector,
1460 _offspringSelector,
1461 _alterer,
1462 _validator,
1463 _optimize,
1464 getOffspringCount(),
1465 getSurvivorsCount(),
1466 _maximalPhenotypeAge,
1467 _executor,
1468 _clock,
1469 _individualCreationRetries
1470 );
1471 }
1472
1473 private int getSurvivorsCount() {
1474 return _populationSize - getOffspringCount();
1475 }
1476
1477 private int getOffspringCount() {
1478 return (int)round(_offspringFraction*_populationSize);
1479 }
1480
1481 /**
1482 * Return the used {@link Alterer} of the GA.
1483 *
1484 * @return the used {@link Alterer} of the GA.
1485 */
1486 public Alterer<G, C> getAlterers() {
1487 return _alterer;
1488 }
1489
1490 /**
1491 * Return the {@link Clock} the engine is using for measuring the execution
1492 * time.
1493 *
1494 * @since 3.1
1495 *
1496 * @return the clock used for measuring the execution time
1497 */
1498 public Clock getClock() {
1499 return _clock;
1500 }
1501
1502 /**
1503 * Return the {@link Executor} the engine is using for executing the
1504 * evolution steps.
1505 *
1506 * @since 3.1
1507 *
1508 * @return the executor used for performing the evolution steps
1509 */
1510 public Executor getExecutor() {
1511 return _executor;
1512 }
1513
1514 /**
1515 * Return the fitness function of the GA engine.
1516 *
1517 * @since 3.1
1518 *
1519 * @return the fitness function
1520 */
1521 public Function<? super Genotype<G>, ? extends C> getFitnessFunction() {
1522 return _fitnessFunction;
1523 }
1524
1525 /**
1526 * Return the fitness scaler of the GA engine.
1527 *
1528 * @since 3.1
1529 *
1530 * @return the fitness scaler
1531 */
1532 public Function<? super C, ? extends C> getFitnessScaler() {
1533 return _fitnessScaler;
1534 }
1535
1536 /**
1537 * Return the used genotype {@link Factory} of the GA. The genotype factory
1538 * is used for creating the initial population and new, random individuals
1539 * when needed (as replacement for invalid and/or died genotypes).
1540 *
1541 * @since 3.1
1542 *
1543 * @return the used genotype {@link Factory} of the GA.
1544 */
1545 public Factory<Genotype<G>> getGenotypeFactory() {
1546 return _genotypeFactory;
1547 }
1548
1549 /**
1550 * Return the maximal allowed phenotype age.
1551 *
1552 * @since 3.1
1553 *
1554 * @return the maximal allowed phenotype age
1555 */
1556 public long getMaximalPhenotypeAge() {
1557 return _maximalPhenotypeAge;
1558 }
1559
1560 /**
1561 * Return the offspring fraction.
1562 *
1563 * @return the offspring fraction.
1564 */
1565 public double getOffspringFraction() {
1566 return _offspringFraction;
1567 }
1568
1569 /**
1570 * Return the used offspring {@link Selector} of the GA.
1571 *
1572 * @since 3.1
1573 *
1574 * @return the used offspring {@link Selector} of the GA.
1575 */
1576 public Selector<G, C> getOffspringSelector() {
1577 return _offspringSelector;
1578 }
1579
1580 /**
1581 * Return the used survivor {@link Selector} of the GA.
1582 *
1583 * @since 3.1
1584 *
1585 * @return the used survivor {@link Selector} of the GA.
1586 */
1587 public Selector<G, C> getSurvivorsSelector() {
1588 return _survivorsSelector;
1589 }
1590
1591 /**
1592 * Return the optimization strategy.
1593 *
1594 * @since 3.1
1595 *
1596 * @return the optimization strategy
1597 */
1598 public Optimize getOptimize() {
1599 return _optimize;
1600 }
1601
1602 /**
1603 * Return the number of individuals of a population.
1604 *
1605 * @since 3.1
1606 *
1607 * @return the number of individuals of a population
1608 */
1609 public int getPopulationSize() {
1610 return _populationSize;
1611 }
1612
1613 /**
1614 * Return the maximal number of attempt before the {@code Engine} gives
1615 * up creating a valid individual ({@code Phenotype}).
1616 *
1617 * @since 3.1
1618 *
1619 * @return the maximal number of {@code Phenotype} creation attempts
1620 */
1621 public int getIndividualCreationRetries() {
1622 return _individualCreationRetries;
1623 }
1624
1625 /**
1626 * Create a new builder, with the current configuration.
1627 *
1628 * @since 3.1
1629 *
1630 * @return a new builder, with the current configuration
1631 */
1632 @Override
1633 public Builder<G, C> copy() {
1634 return new Builder<G, C>(_genotypeFactory, _fitnessFunction)
1635 .alterers(_alterer)
1636 .clock(_clock)
1637 .executor(_executor)
1638 .fitnessScaler(_fitnessScaler)
1639 .maximalPhenotypeAge(_maximalPhenotypeAge)
1640 .offspringFraction(_offspringFraction)
1641 .offspringSelector(_offspringSelector)
1642 .phenotypeValidator(_validator)
1643 .optimize(_optimize)
1644 .populationSize(_populationSize)
1645 .survivorsSelector(_survivorsSelector)
1646 .individualCreationRetries(_individualCreationRetries);
1647 }
1648
1649 }
1650 }
|