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