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