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