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