001/*
002 * Java Genetic Algorithm Library (jenetics-4.2.0).
003 * Copyright (c) 2007-2018 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
019 */
020package io.jenetics.engine;
021
022import static java.lang.Math.round;
023import static java.lang.String.format;
024import static java.util.Objects.requireNonNull;
025import static io.jenetics.internal.util.require.probability;
026
027import java.time.Clock;
028import java.util.Iterator;
029import java.util.Objects;
030import java.util.concurrent.CompletableFuture;
031import java.util.concurrent.Executor;
032import java.util.concurrent.ForkJoinPool;
033import java.util.function.Function;
034import java.util.function.Predicate;
035import java.util.function.Supplier;
036import java.util.function.UnaryOperator;
037import java.util.stream.Stream;
038
039import io.jenetics.Alterer;
040import io.jenetics.AltererResult;
041import io.jenetics.Chromosome;
042import io.jenetics.Gene;
043import io.jenetics.Genotype;
044import io.jenetics.Mutator;
045import io.jenetics.Optimize;
046import io.jenetics.Phenotype;
047import io.jenetics.Selector;
048import io.jenetics.SinglePointCrossover;
049import io.jenetics.TournamentSelector;
050import io.jenetics.internal.util.require;
051import io.jenetics.util.Copyable;
052import io.jenetics.util.Factory;
053import io.jenetics.util.ISeq;
054import io.jenetics.util.MSeq;
055import io.jenetics.util.NanoClock;
056import io.jenetics.util.Seq;
057
058/**
059 * Genetic algorithm <em>engine</em> which is the main class. The following
060 * example shows the main steps in initializing and executing the GA.
061 *
062 * <pre>{@code
063 * public class RealFunction {
064 *    // Definition of the fitness function.
065 *    private static Double eval(final Genotype<DoubleGene> gt) {
066 *        final double x = gt.getGene().doubleValue();
067 *        return cos(0.5 + sin(x))*cos(x);
068 *    }
069 *
070 *    public static void main(String[] args) {
071 *        // Create/configuring the engine via its builder.
072 *        final Engine<DoubleGene, Double> engine = Engine
073 *            .builder(
074 *                RealFunction::eval,
075 *                DoubleChromosome.of(0.0, 2.0*PI))
076 *            .populationSize(500)
077 *            .optimize(Optimize.MINIMUM)
078 *            .alterers(
079 *                new Mutator<>(0.03),
080 *                new MeanAlterer<>(0.6))
081 *            .build();
082 *
083 *        // Execute the GA (engine).
084 *        final Phenotype<DoubleGene, Double> result = engine.stream()
085 *             // Truncate the evolution stream if no better individual could
086 *             // be found after 5 consecutive generations.
087 *            .limit(bySteadyFitness(5))
088 *             // Terminate the evolution after maximal 100 generations.
089 *            .limit(100)
090 *            .collect(toBestPhenotype());
091 *     }
092 * }
093 * }</pre>
094 *
095 * The architecture allows to decouple the configuration of the engine from the
096 * execution. The {@code Engine} is configured via the {@code Engine.Builder}
097 * class and can't be changed after creation. The actual <i>evolution</i> is
098 * performed by the {@link EvolutionStream}, which is created by the
099 * {@code Engine}.
100 *
101 * @implNote
102 *     This class is thread safe:
103 *     No mutable state is maintained by the engine. Therefore it is save to
104 *     create multiple evolution streams with one engine, which may be actually
105 *     used in different threads.
106 *
107 * @see Engine.Builder
108 * @see EvolutionStart
109 * @see EvolutionResult
110 * @see EvolutionStream
111 * @see EvolutionStatistics
112 * @see Codec
113 *
114 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
115 * @since 3.0
116 * @version 4.1
117 */
118@SuppressWarnings("deprecation")
119public final class Engine<
120        G extends Gene<?, G>,
121        C extends Comparable<? super C>
122>
123        implements
124                Function<EvolutionStart<G, C>, EvolutionResult<G, C>>,
125                EvolutionStreamable<G, C>,
126                EvolutionIterable<G, C>
127{
128
129        // Problem definition.
130        private final Function<? super Genotype<G>, ? extends C> _fitnessFunction;
131        private final Factory<Genotype<G>> _genotypeFactory;
132
133        // Evolution parameters.
134        private final Function<? super C, ? extends C> _fitnessScaler;
135        private final Selector<G, C> _survivorsSelector;
136        private final Selector<G, C> _offspringSelector;
137        private final Alterer<G, C> _alterer;
138        private final Predicate<? super Phenotype<G, C>> _validator;
139        private final Optimize _optimize;
140        private final int _offspringCount;
141        private final int _survivorsCount;
142        private final long _maximalPhenotypeAge;
143
144        // Execution context for concurrent execution of evolving steps.
145        private final TimedExecutor _executor;
146        private final Evaluator<G, C> _evaluator;
147        private final Clock _clock;
148
149        // Additional parameters.
150        private final int _individualCreationRetries;
151        private final UnaryOperator<EvolutionResult<G, C>> _mapper;
152
153
154        /**
155         * Create a new GA engine with the given parameters.
156         *
157         * @param fitnessFunction the fitness function this GA is using.
158         * @param genotypeFactory the genotype factory this GA is working with.
159         * @param fitnessScaler the fitness scaler this GA is using.
160         * @param survivorsSelector the selector used for selecting the survivors
161         * @param offspringSelector the selector used for selecting the offspring
162         * @param alterer the alterer used for altering the offspring
163         * @param validator phenotype validator which can override the default
164         *        implementation the {@link Phenotype#isValid()} method.
165         * @param optimize the kind of optimization (minimize or maximize)
166         * @param offspringCount the number of the offspring individuals
167         * @param survivorsCount the number of the survivor individuals
168         * @param maximalPhenotypeAge the maximal age of an individual
169         * @param executor the executor used for executing the single evolve steps
170         * @param evaluator the population fitness evaluator
171         * @param clock the clock used for calculating the timing results
172         * @param individualCreationRetries the maximal number of attempts for
173         *        creating a valid individual.
174         * @throws NullPointerException if one of the arguments is {@code null}
175         * @throws IllegalArgumentException if the given integer values are smaller
176         *         than one.
177         */
178        Engine(
179                final Function<? super Genotype<G>, ? extends C> fitnessFunction,
180                final Factory<Genotype<G>> genotypeFactory,
181                final Function<? super C, ? extends C> fitnessScaler,
182                final Selector<G, C> survivorsSelector,
183                final Selector<G, C> offspringSelector,
184                final Alterer<G, C> alterer,
185                final Predicate<? super Phenotype<G, C>> validator,
186                final Optimize optimize,
187                final int offspringCount,
188                final int survivorsCount,
189                final long maximalPhenotypeAge,
190                final Executor executor,
191                final Evaluator<G, C> evaluator,
192                final Clock clock,
193                final int individualCreationRetries,
194                final UnaryOperator<EvolutionResult<G, C>> mapper
195        ) {
196                _fitnessFunction = requireNonNull(fitnessFunction);
197                _fitnessScaler = requireNonNull(fitnessScaler);
198                _genotypeFactory = requireNonNull(genotypeFactory);
199                _survivorsSelector = requireNonNull(survivorsSelector);
200                _offspringSelector = requireNonNull(offspringSelector);
201                _alterer = requireNonNull(alterer);
202                _validator = requireNonNull(validator);
203                _optimize = requireNonNull(optimize);
204
205                _offspringCount = require.nonNegative(offspringCount);
206                _survivorsCount = require.nonNegative(survivorsCount);
207                _maximalPhenotypeAge = require.positive(maximalPhenotypeAge);
208
209                _executor = new TimedExecutor(requireNonNull(executor));
210                _evaluator = requireNonNull(evaluator);
211                _clock = requireNonNull(clock);
212
213                if (individualCreationRetries < 0) {
214                        throw new IllegalArgumentException(format(
215                                "Retry count must not be negative: %d",
216                                individualCreationRetries
217                        ));
218                }
219                _individualCreationRetries = individualCreationRetries;
220                _mapper = requireNonNull(mapper);
221        }
222
223        /**
224         * Perform one evolution step with the given {@code population} and
225         * {@code generation}. New phenotypes are created with the fitness function
226         * and fitness scaler defined by this <em>engine</em>
227         * <p>
228         * <em>This method is thread-safe.</em>
229         *
230         * @see #evolve(EvolutionStart)
231         *
232         * @param population the population to evolve
233         * @param generation the current generation; used for calculating the
234         *        phenotype age.
235         * @return the evolution result
236         * @throws java.lang.NullPointerException if the given {@code population} is
237         *         {@code null}
238         * @throws IllegalArgumentException if the given {@code generation} is
239         *         smaller then one
240         */
241        public EvolutionResult<G, C> evolve(
242                final ISeq<Phenotype<G, C>> population,
243                final long generation
244        ) {
245                return evolve(EvolutionStart.of(population, generation));
246        }
247
248        /**
249         * Perform one evolution step with the given evolution {@code start} object
250         * New phenotypes are created with the fitness function and fitness scaler
251         * defined by this <em>engine</em>
252         * <p>
253         * <em>This method is thread-safe.</em>
254         *
255         * @since 3.1
256         * @see #evolve(ISeq, long)
257         *
258         * @param start the evolution start object
259         * @return the evolution result
260         * @throws java.lang.NullPointerException if the given evolution
261         *         {@code start} is {@code null}
262         */
263        public EvolutionResult<G, C> evolve(final EvolutionStart<G, C> start) {
264                final Timer timer = Timer.of(_clock).start();
265
266                // Initial evaluation of the population.
267                final Timer evaluateTimer = Timer.of(_clock).start();
268                final ISeq<Phenotype<G, C>> evalPop =
269                        _evaluator.evaluate(start.getPopulation());
270
271                if (start.getPopulation().size() != evalPop.size()) {
272                        throw new IllegalStateException(format(
273                                "Expected %d individuals, but got %d. " +
274                                "Check your evaluator function.",
275                                start.getPopulation().size(), evalPop.size()
276                        ));
277                }
278
279                evaluateTimer.stop();
280
281                // Select the offspring population.
282                final CompletableFuture<TimedResult<ISeq<Phenotype<G, C>>>> offspring =
283                        _executor.async(() ->
284                                selectOffspring(evalPop),
285                                _clock
286                        );
287
288                // Select the survivor population.
289                final CompletableFuture<TimedResult<ISeq<Phenotype<G, C>>>> survivors =
290                        _executor.async(() ->
291                                selectSurvivors(evalPop),
292                                _clock
293                        );
294
295                // Altering the offspring population.
296                final CompletableFuture<TimedResult<AltererResult<G, C>>> alteredOffspring =
297                        _executor.thenApply(offspring, p ->
298                                _alterer.alter(p.result, start.getGeneration()),
299                                _clock
300                        );
301
302                // Filter and replace invalid and old survivor individuals.
303                final CompletableFuture<TimedResult<FilterResult<G, C>>> filteredSurvivors =
304                        _executor.thenApply(survivors, pop ->
305                                filter(pop.result, start.getGeneration()),
306                                _clock
307                        );
308
309                // Filter and replace invalid and old offspring individuals.
310                final CompletableFuture<TimedResult<FilterResult<G, C>>> filteredOffspring =
311                        _executor.thenApply(alteredOffspring, pop ->
312                                filter(pop.result.getPopulation(), start.getGeneration()),
313                                _clock
314                        );
315
316                // Combining survivors and offspring to the new population.
317                final CompletableFuture<ISeq<Phenotype<G, C>>> population =
318                        filteredSurvivors.thenCombineAsync(filteredOffspring, (s, o) ->
319                                        ISeq.of(s.result.population.append(o.result.population)),
320                                _executor.get()
321                        );
322
323                // Evaluate the fitness-function and wait for result.
324                final ISeq<Phenotype<G, C>> pop = population.join();
325                final TimedResult<ISeq<Phenotype<G, C>>> result = TimedResult
326                        .of(() -> _evaluator.evaluate(pop), _clock)
327                        .get();
328
329
330                final EvolutionDurations durations = EvolutionDurations.of(
331                        offspring.join().duration,
332                        survivors.join().duration,
333                        alteredOffspring.join().duration,
334                        filteredOffspring.join().duration,
335                        filteredSurvivors.join().duration,
336                        result.duration.plus(evaluateTimer.getTime()),
337                        timer.stop().getTime()
338                );
339
340                final int killCount =
341                        filteredOffspring.join().result.killCount +
342                        filteredSurvivors.join().result.killCount;
343
344                final int invalidCount =
345                        filteredOffspring.join().result.invalidCount +
346                        filteredSurvivors.join().result.invalidCount;
347
348                return _mapper.apply(
349                        EvolutionResult.of(
350                                _optimize,
351                                result.result,
352                                start.getGeneration(),
353                                durations,
354                                killCount,
355                                invalidCount,
356                                alteredOffspring.join().result.getAlterations()
357                        )
358                );
359        }
360
361        /**
362         * This method is an <i>alias</i> for the {@link #evolve(EvolutionStart)}
363         * method.
364         *
365         * @since 3.1
366         */
367        @Override
368        public EvolutionResult<G, C> apply(final EvolutionStart<G, C> start) {
369                return evolve(start);
370        }
371
372        // Selects the survivors population. A new population object is returned.
373        private ISeq<Phenotype<G, C>>
374        selectSurvivors(final ISeq<Phenotype<G, C>> population) {
375                return _survivorsCount > 0
376                        ?_survivorsSelector.select(population, _survivorsCount, _optimize)
377                        : ISeq.empty();
378        }
379
380        // Selects the offspring population. A new population object is returned.
381        private ISeq<Phenotype<G, C>>
382        selectOffspring(final ISeq<Phenotype<G, C>> population) {
383                return _offspringCount > 0
384                        ? _offspringSelector.select(population, _offspringCount, _optimize)
385                        : ISeq.empty();
386        }
387
388        // Filters out invalid and old individuals. Filtering is done in place.
389        private FilterResult<G, C> filter(
390                final Seq<Phenotype<G, C>> population,
391                final long generation
392        ) {
393                int killCount = 0;
394                int invalidCount = 0;
395
396                final MSeq<Phenotype<G, C>> pop = MSeq.of(population);
397                for (int i = 0, n = pop.size(); i < n; ++i) {
398                        final Phenotype<G, C> individual = pop.get(i);
399
400                        if (!_validator.test(individual)) {
401                                pop.set(i, newPhenotype(generation));
402                                ++invalidCount;
403                        } else if (individual.getAge(generation) > _maximalPhenotypeAge) {
404                                pop.set(i, newPhenotype(generation));
405                                ++killCount;
406                        }
407                }
408
409                return new FilterResult<>(pop.toISeq(), killCount, invalidCount);
410        }
411
412        // Create a new and valid phenotype
413        private Phenotype<G, C> newPhenotype(final long generation) {
414                int count = 0;
415                Phenotype<G, C> phenotype;
416                do {
417                        phenotype = Phenotype.of(
418                                _genotypeFactory.newInstance(),
419                                generation,
420                                _fitnessFunction,
421                                _fitnessScaler
422                        );
423                } while (++count < _individualCreationRetries &&
424                                !_validator.test(phenotype));
425
426                return phenotype;
427        }
428
429
430        /* *************************************************************************
431         * Evolution Stream/Iterator creation.
432         **************************************************************************/
433
434        @Deprecated
435        @Override
436        public Iterator<EvolutionResult<G, C>>
437        iterator(final Supplier<EvolutionStart<G, C>> start) {
438                return new EvolutionIterator<>(evolutionStart(start), this::evolve);
439        }
440
441        @Deprecated
442        @Override
443        public Iterator<EvolutionResult<G, C>> iterator(final EvolutionInit<G> init) {
444                return iterator(evolutionStart(init));
445        }
446
447        @Override
448        public EvolutionStream<G, C>
449        stream(final Supplier<EvolutionStart<G, C>> start) {
450                return EvolutionStream.of(evolutionStart(start), this::evolve);
451        }
452
453        @Override
454        public EvolutionStream<G, C> stream(final EvolutionInit<G> init) {
455                return stream(evolutionStart(init));
456        }
457
458        private Supplier<EvolutionStart<G, C>>
459        evolutionStart(final Supplier<EvolutionStart<G, C>> start) {
460                return () -> {
461                        final EvolutionStart<G, C> es = start.get();
462                        final ISeq<Phenotype<G, C>> population = es.getPopulation();
463                        final long generation = es.getGeneration();
464
465                        final Stream<Phenotype<G, C>> stream = Stream.concat(
466                                population.stream().map(this::toFixedPhenotype),
467                                Stream.generate(() -> newPhenotype(generation))
468                        );
469
470                        final ISeq<Phenotype<G, C>> pop = stream
471                                .limit(getPopulationSize())
472                                .collect(ISeq.toISeq());
473
474                        return EvolutionStart.of(pop, generation);
475                };
476        }
477
478        private Phenotype<G, C> toFixedPhenotype(final Phenotype<G, C> pt) {
479                return
480                        pt.getFitnessFunction() == _fitnessFunction &&
481                        pt.getFitnessScaler() == _fitnessScaler
482                                ? pt
483                                : pt.newInstance(
484                                        pt.getGeneration(),
485                                        _fitnessFunction,
486                                        _fitnessScaler
487                                );
488        }
489
490        private Supplier<EvolutionStart<G, C>>
491        evolutionStart(final EvolutionInit<G> init) {
492                return evolutionStart(() -> EvolutionStart.of(
493                        init.getPopulation()
494                                .map(gt -> Phenotype.of(
495                                        gt,
496                                        init.getGeneration(),
497                                        _fitnessFunction,
498                                        _fitnessScaler)
499                                ),
500                        init.getGeneration())
501                );
502        }
503
504        /* *************************************************************************
505         * Property access methods.
506         **************************************************************************/
507
508        /**
509         * Return the fitness function of the GA engine.
510         *
511         * @return the fitness function
512         */
513        public Function<? super Genotype<G>, ? extends C> getFitnessFunction() {
514                return _fitnessFunction;
515        }
516
517        /**
518         * Return the fitness scaler of the GA engine.
519         *
520         * @return the fitness scaler
521         */
522        public Function<? super C, ? extends C> getFitnessScaler() {
523                return _fitnessScaler;
524        }
525
526        /**
527         * Return the used genotype {@link Factory} of the GA. The genotype factory
528         * is used for creating the initial population and new, random individuals
529         * when needed (as replacement for invalid and/or died genotypes).
530         *
531         * @return the used genotype {@link Factory} of the GA.
532         */
533        public Factory<Genotype<G>> getGenotypeFactory() {
534                return _genotypeFactory;
535        }
536
537        /**
538         * Return the used survivor {@link Selector} of the GA.
539         *
540         * @return the used survivor {@link Selector} of the GA.
541         */
542        public Selector<G, C> getSurvivorsSelector() {
543                return _survivorsSelector;
544        }
545
546        /**
547         * Return the used offspring {@link Selector} of the GA.
548         *
549         * @return the used offspring {@link Selector} of the GA.
550         */
551        public Selector<G, C> getOffspringSelector() {
552                return _offspringSelector;
553        }
554
555        /**
556         * Return the used {@link Alterer} of the GA.
557         *
558         * @return the used {@link Alterer} of the GA.
559         */
560        public Alterer<G, C> getAlterer() {
561                return _alterer;
562        }
563
564        /**
565         * Return the number of selected offsprings.
566         *
567         * @return the number of selected offsprings
568         */
569        public int getOffspringCount() {
570                return _offspringCount;
571        }
572
573        /**
574         * The number of selected survivors.
575         *
576         * @return the number of selected survivors
577         */
578        public int getSurvivorsCount() {
579                return _survivorsCount;
580        }
581
582        /**
583         * Return the number of individuals of a population.
584         *
585         * @return the number of individuals of a population
586         */
587        public int getPopulationSize() {
588                return _offspringCount + _survivorsCount;
589        }
590
591        /**
592         * Return the maximal allowed phenotype age.
593         *
594         * @return the maximal allowed phenotype age
595         */
596        public long getMaximalPhenotypeAge() {
597                return _maximalPhenotypeAge;
598        }
599
600        /**
601         * Return the optimization strategy.
602         *
603         * @return the optimization strategy
604         */
605        public Optimize getOptimize() {
606                return _optimize;
607        }
608
609        /**
610         * Return the {@link Clock} the engine is using for measuring the execution
611         * time.
612         *
613         * @return the clock used for measuring the execution time
614         */
615        public Clock getClock() {
616                return _clock;
617        }
618
619        /**
620         * Return the {@link Executor} the engine is using for executing the
621         * evolution steps.
622         *
623         * @return the executor used for performing the evolution steps
624         */
625        public Executor getExecutor() {
626                return _executor.get();
627        }
628
629
630        /**
631         * Return the maximal number of attempt before the {@code Engine} gives
632         * up creating a valid individual ({@code Phenotype}).
633         *
634         * @since 4.0
635         *
636         * @return the maximal number of {@code Phenotype} creation attempts
637         */
638        public int getIndividualCreationRetries() {
639                return _individualCreationRetries;
640        }
641
642        /**
643         * Return the evolution result mapper.
644         *
645         * @since 4.0
646         *
647         * @return the evolution result mapper
648         */
649        public UnaryOperator<EvolutionResult<G, C>> getMapper() {
650                return _mapper;
651        }
652
653        /* *************************************************************************
654         * Builder methods.
655         **************************************************************************/
656
657        /**
658         * Create a new evolution {@code Engine.Builder} initialized with the values
659         * of the current evolution {@code Engine}. With this method, the evolution
660         * engine can serve as a template for a new one.
661         *
662         * @return a new engine builder
663         */
664        public Builder<G, C> builder() {
665                return new Builder<G, C>(_genotypeFactory, _fitnessFunction)
666                        .alterers(_alterer)
667                        .clock(_clock)
668                        .evaluator(_evaluator)
669                        .executor(_executor.get())
670                        .fitnessScaler(_fitnessScaler)
671                        .maximalPhenotypeAge(_maximalPhenotypeAge)
672                        .offspringFraction((double)_offspringCount/(double)getPopulationSize())
673                        .offspringSelector(_offspringSelector)
674                        .optimize(_optimize)
675                        .phenotypeValidator(_validator)
676                        .populationSize(getPopulationSize())
677                        .survivorsSelector(_survivorsSelector)
678                        .individualCreationRetries(_individualCreationRetries)
679                        .mapping(_mapper);
680        }
681
682        /**
683         * Create a new evolution {@code Engine.Builder} for the given
684         * {@link Problem}.
685         *
686         * @since 3.4
687         *
688         * @param problem the problem to be solved by the evolution {@code Engine}
689         * @param <T> the (<i>native</i>) argument type of the problem fitness function
690         * @param <G> the gene type the evolution engine is working with
691         * @param <C> the result type of the fitness function
692         * @return Create a new evolution {@code Engine.Builder}
693         */
694        public static <T, G extends Gene<?, G>, C extends Comparable<? super C>>
695        Builder<G, C> builder(final Problem<T, G, C> problem) {
696                return builder(problem.fitness(), problem.codec());
697        }
698
699        /**
700         * Create a new evolution {@code Engine.Builder} with the given fitness
701         * function and genotype factory.
702         *
703         * @param ff the fitness function
704         * @param genotypeFactory the genotype factory
705         * @param <G> the gene type
706         * @param <C> the fitness function result type
707         * @return a new engine builder
708         * @throws java.lang.NullPointerException if one of the arguments is
709         *         {@code null}.
710         */
711        public static <G extends Gene<?, G>, C extends Comparable<? super C>>
712        Builder<G, C> builder(
713                final Function<? super Genotype<G>, ? extends C> ff,
714                final Factory<Genotype<G>> genotypeFactory
715        ) {
716                return new Builder<>(genotypeFactory, ff);
717        }
718
719        /**
720         * Create a new evolution {@code Engine.Builder} with the given fitness
721         * function and chromosome templates.
722         *
723         * @param ff the fitness function
724         * @param chromosome the first chromosome
725         * @param chromosomes the chromosome templates
726         * @param <G> the gene type
727         * @param <C> the fitness function result type
728         * @return a new engine builder
729         * @throws java.lang.NullPointerException if one of the arguments is
730         *         {@code null}.
731         */
732        @SafeVarargs
733        public static <G extends Gene<?, G>, C extends Comparable<? super C>>
734        Builder<G, C> builder(
735                final Function<? super Genotype<G>, ? extends C> ff,
736                final Chromosome<G> chromosome,
737                final Chromosome<G>... chromosomes
738        ) {
739                return new Builder<>(Genotype.of(chromosome, chromosomes), ff);
740        }
741
742        /**
743         * Create a new evolution {@code Engine.Builder} with the given fitness
744         * function and problem {@code codec}.
745         *
746         * @since 3.2
747         *
748         * @param ff the fitness function
749         * @param codec the problem codec
750         * @param <T> the fitness function input type
751         * @param <C> the fitness function result type
752         * @param <G> the gene type
753         * @return a new engine builder
754         * @throws java.lang.NullPointerException if one of the arguments is
755         *         {@code null}.
756         */
757        public static <T, G extends Gene<?, G>, C extends Comparable<? super C>>
758        Builder<G, C> builder(
759                final Function<? super T, ? extends C> ff,
760                final Codec<T, G> codec
761        ) {
762                return builder(ff.compose(codec.decoder()), codec.encoding());
763        }
764
765
766        /* *************************************************************************
767         * Inner classes
768         **************************************************************************/
769
770
771        /**
772         * This interface allows to define different strategies for evaluating the
773         * fitness functions of a given population. <em>Normally</em>, there is no
774         * need for <em>overriding</em> the default evaluation strategy, but it might
775         * be necessary if you have performance problems and a <em>batched</em>
776         * fitness evaluation would solve the problem.
777         * <p>
778         * The implementer is free to do the evaluation <em>in place</em>, or create
779         * new {@link Phenotype} instance and return the newly created one. A simple
780         * serial evaluator can easily implemented:
781         *
782         * <pre>{@code
783         * final Evaluator<G, C> evaluator = population -> {
784         *     population.forEach(Phenotype::evaluate);
785         *     return population.asISeq();
786         * };
787         * }</pre>
788         *
789         * @implSpec
790         * The size of the returned, evaluated, phenotype sequence must be exactly
791         * the size of the input phenotype sequence. It is allowed to return the
792         * input sequence, after evaluation, as well a newly created one.
793         *
794         * @apiNote
795         * This interface is an <em>advanced</em> {@code Engine} configuration
796         * feature, which should be only used when there is a performance gain from
797         * implementing a different evaluation strategy. Another use case is, when
798         * the fitness value of an individual also depends on the current composition
799         * of the population.
800         *
801         * @see GenotypeEvaluator
802         * @see Engine.Builder#evaluator(Engine.Evaluator)
803         *
804         * @param <G> the gene type
805         * @param <C> the fitness result type
806         *
807         * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
808         * @version 4.2
809         * @since 4.2
810         */
811        @FunctionalInterface
812        public static interface Evaluator<
813                G extends Gene<?, G>,
814                C extends Comparable<? super C>
815        > {
816
817                /**
818                 * Evaluates the fitness values of the given {@code population}. The
819                 * given {@code population} might contain already evaluated individuals.
820                 * It is the responsibility of the implementer to filter out already
821                 * evaluated individuals, if desired.
822                 *
823                 * @param population the population to evaluate
824                 * @return the evaluated population. Implementers are free to return the
825                 *         the input population or a newly created one.
826                 */
827                public ISeq<Phenotype<G, C>> evaluate(final Seq<Phenotype<G, C>> population);
828
829                /**
830                 * Create a new phenotype evaluator from a given genotype {@code evaluator}.
831                 *
832                 * @implNote
833                 * The returned {@link Evaluator} will only forward <em>un</em>-evaluated
834                 * individuals to the given genotype {@code evaluator}. This means, that
835                 * already evaluated individuals are filtered from the population, which
836                 * is then forwarded to the underlying genotype {@code evaluator}.
837                 *
838                 * @param evaluator the genotype evaluator
839                 * @param <G> the gene type
840                 * @param <C> the fitness result type
841                 * @return a <em>normal</em> phenotype evaluator from the given genotype
842                 *         evaluator
843                 * @throws NullPointerException if the given {@code evaluator} is
844                 *         {@code null}
845                 */
846                public static <G extends Gene<?, G>, C extends Comparable<? super C>>
847                Evaluator<G, C> of(final GenotypeEvaluator<G, C> evaluator) {
848                        requireNonNull(evaluator);
849
850                        return population -> {
851                                final ISeq<Genotype<G>> genotypes = population.stream()
852                                        .filter(pt -> !pt.isEvaluated())
853                                        .map(Phenotype::getGenotype)
854                                        .collect(ISeq.toISeq());
855
856                                if (genotypes.nonEmpty()) {
857                                        final ISeq<C> results = evaluator.evaluate(
858                                                genotypes,
859                                                population.get(0).getFitnessFunction()
860                                        );
861
862                                        if (genotypes.size() != results.size()) {
863                                                throw new IllegalStateException(format(
864                                                        "Expected %d results, but got %d. " +
865                                                        "Check your evaluator function.",
866                                                        genotypes.size(), results.size()
867                                                ));
868                                        }
869
870                                        final MSeq<Phenotype<G, C>> evaluated = population.asMSeq();
871                                        for (int i = 0, j = 0; i < evaluated.length(); ++i) {
872                                                if (!population.get(i).isEvaluated()) {
873                                                        evaluated.set(
874                                                                i,
875                                                                population.get(i).withFitness(results.get(j++))
876                                                        );
877                                                }
878                                        }
879
880                                        return evaluated.toISeq();
881                                } else {
882                                        return population.asISeq();
883                                }
884                        };
885                }
886
887        }
888
889        /**
890         * This interface gives a different possibility in evaluating the fitness
891         * values of a population. Sometimes it is necessary (mostly for performance
892         * reason) to calculate the fitness for the whole population at once. This
893         * interface allows you to do so. A simple serial evaluator can easily
894         * implemented:
895         *
896         * <pre>{@code
897         * final GenotypeEvaluator<G, C> gte = (g, f) -> g.map(f).asISeq()
898         * final Evaluator<G, C> evaluator = Evaluator.of(gte);
899         * }</pre>
900         *
901         * @implSpec
902         * The size of the returned result sequence must be exactly the size of the
903         * input genotype sequence.
904         *
905         * @apiNote
906         * This interface is an <em>advanced</em> {@code Engine} configuration
907         * feature, which should be only used when there is a performance gain from
908         * implementing a different evaluation strategy.
909         *
910         * @see Evaluator
911         * @see Engine.Builder#evaluator(Engine.GenotypeEvaluator)
912         *
913         * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
914         * @version 4.2
915         * @since 4.2
916         */
917        @FunctionalInterface
918        public static interface GenotypeEvaluator<
919                G extends Gene<?, G>,
920                C extends Comparable<? super C>
921        > {
922
923                /**
924                 * Calculate the fitness values for the given sequence of genotypes.
925                 *
926                 * @see Engine.Evaluator#of(Engine.GenotypeEvaluator)
927                 *
928                 * @param genotypes the genotypes to evaluate the fitness value for
929                 * @param function the fitness function
930                 * @return the fitness values for the given {@code genotypes} The length
931                 *         of the fitness result sequence must match with the size of
932                 *         the given {@code genotypes}.
933                 */
934                public ISeq<C> evaluate(
935                        final Seq<Genotype<G>> genotypes,
936                        final Function<? super Genotype<G>, ? extends C> function
937                );
938
939        }
940
941
942        /**
943         * Builder class for building GA {@code Engine} instances.
944         *
945         * @see Engine
946         *
947         * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
948         * @since 3.0
949         * @version 4.0
950         */
951        public static final class Builder<
952                G extends Gene<?, G>,
953                C extends Comparable<? super C>
954        >
955                implements Copyable<Builder<G, C>>
956        {
957
958                // No default values for this properties.
959                private Function<? super Genotype<G>, ? extends C> _fitnessFunction;
960                private Factory<Genotype<G>> _genotypeFactory;
961
962                // This are the properties which default values.
963                private Function<? super C, ? extends C> _fitnessScaler = a -> a;
964                private Selector<G, C> _survivorsSelector = new TournamentSelector<>(3);
965                private Selector<G, C> _offspringSelector = new TournamentSelector<>(3);
966                private Alterer<G, C> _alterer = Alterer.of(
967                        new SinglePointCrossover<G, C>(0.2),
968                        new Mutator<>(0.15)
969                );
970                private Predicate<? super Phenotype<G, C>> _validator = Phenotype::isValid;
971                private Optimize _optimize = Optimize.MAXIMUM;
972                private double _offspringFraction = 0.6;
973                private int _populationSize = 50;
974                private long _maximalPhenotypeAge = 70;
975
976                // Engine execution environment.
977                private Executor _executor = ForkJoinPool.commonPool();
978                private Clock _clock = NanoClock.systemUTC();
979                private Evaluator<G, C> _evaluator;
980
981                private int _individualCreationRetries = 10;
982                private UnaryOperator<EvolutionResult<G, C>> _mapper = r -> r;
983
984                private Builder(
985                        final Factory<Genotype<G>> genotypeFactory,
986                        final Function<? super Genotype<G>, ? extends C> fitnessFunction
987                ) {
988                        _genotypeFactory = requireNonNull(genotypeFactory);
989                        _fitnessFunction = requireNonNull(fitnessFunction);
990                }
991
992                /**
993                 * Set the fitness function of the evolution {@code Engine}.
994                 *
995                 * @param function the fitness function to use in the GA {@code Engine}
996                 * @return {@code this} builder, for command chaining
997                 */
998                public Builder<G, C> fitnessFunction(
999                        final Function<? super Genotype<G>, ? extends C> function
1000                ) {
1001                        _fitnessFunction = requireNonNull(function);
1002                        return this;
1003                }
1004
1005                /**
1006                 * Set the fitness scaler of the evolution {@code Engine}. <i>Default
1007                 * value is set to the identity function.</i>
1008                 *
1009                 * @param scaler the fitness scale to use in the GA {@code Engine}
1010                 * @return {@code this} builder, for command chaining
1011                 */
1012                public Builder<G, C> fitnessScaler(
1013                        final Function<? super C, ? extends C> scaler
1014                ) {
1015                        _fitnessScaler = requireNonNull(scaler);
1016                        return this;
1017                }
1018
1019                /**
1020                 * The genotype factory used for creating new individuals.
1021                 *
1022                 * @param genotypeFactory the genotype factory for creating new
1023                 *        individuals.
1024                 * @return {@code this} builder, for command chaining
1025                 */
1026                public Builder<G, C> genotypeFactory(
1027                        final Factory<Genotype<G>> genotypeFactory
1028                ) {
1029                        _genotypeFactory = requireNonNull(genotypeFactory);
1030                        return this;
1031                }
1032
1033                /**
1034                 * The selector used for selecting the offspring population. <i>Default
1035                 * values is set to {@code TournamentSelector<>(3)}.</i>
1036                 *
1037                 * @param selector used for selecting the offspring population
1038                 * @return {@code this} builder, for command chaining
1039                 */
1040                public Builder<G, C> offspringSelector(
1041                        final Selector<G, C> selector
1042                ) {
1043                        _offspringSelector = requireNonNull(selector);
1044                        return this;
1045                }
1046
1047                /**
1048                 * The selector used for selecting the survivors population. <i>Default
1049                 * values is set to {@code TournamentSelector<>(3)}.</i>
1050                 *
1051                 * @param selector used for selecting survivors population
1052                 * @return {@code this} builder, for command chaining
1053                 */
1054                public Builder<G, C> survivorsSelector(
1055                        final Selector<G, C> selector
1056                ) {
1057                        _survivorsSelector = requireNonNull(selector);
1058                        return this;
1059                }
1060
1061                /**
1062                 * The selector used for selecting the survivors and offspring
1063                 * population. <i>Default values is set to
1064                 * {@code TournamentSelector<>(3)}.</i>
1065                 *
1066                 * @param selector used for selecting survivors and offspring population
1067                 * @return {@code this} builder, for command chaining
1068                 */
1069                public Builder<G, C> selector(final Selector<G, C> selector) {
1070                        _offspringSelector = requireNonNull(selector);
1071                        _survivorsSelector = requireNonNull(selector);
1072                        return this;
1073                }
1074
1075                /**
1076                 * The alterers used for alter the offspring population. <i>Default
1077                 * values is set to {@code new SinglePointCrossover<>(0.2)} followed by
1078                 * {@code new Mutator<>(0.15)}.</i>
1079                 *
1080                 * @param first the first alterer used for alter the offspring
1081                 *        population
1082                 * @param rest the rest of the alterers used for alter the offspring
1083                 *        population
1084                 * @return {@code this} builder, for command chaining
1085                 * @throws java.lang.NullPointerException if one of the alterers is
1086                 *         {@code null}.
1087                 */
1088                @SafeVarargs
1089                public final Builder<G, C> alterers(
1090                        final Alterer<G, C> first,
1091                        final Alterer<G, C>... rest
1092                ) {
1093                        requireNonNull(first);
1094                        Stream.of(rest).forEach(Objects::requireNonNull);
1095
1096                        _alterer = rest.length == 0
1097                                ? first
1098                                : Alterer.of(rest).compose(first);
1099
1100                        return this;
1101                }
1102
1103                /**
1104                 * The phenotype validator used for detecting invalid individuals.
1105                 * Alternatively it is also possible to set the genotype validator with
1106                 * {@link #genotypeFactory(Factory)}, which will replace any
1107                 * previously set phenotype validators.
1108                 *
1109                 * <p><i>Default value is set to {@code Phenotype::isValid}.</i></p>
1110                 *
1111                 * @since 3.1
1112                 *
1113                 * @see #genotypeValidator(Predicate)
1114                 *
1115                 * @param validator the {@code validator} used for validating the
1116                 *        individuals (phenotypes).
1117                 * @return {@code this} builder, for command chaining
1118                 * @throws java.lang.NullPointerException if the {@code validator} is
1119                 *         {@code null}.
1120                 */
1121                public Builder<G, C> phenotypeValidator(
1122                        final Predicate<? super Phenotype<G, C>> validator
1123                ) {
1124                        _validator = requireNonNull(validator);
1125                        return this;
1126                }
1127
1128                /**
1129                 * The genotype validator used for detecting invalid individuals.
1130                 * Alternatively it is also possible to set the phenotype validator with
1131                 * {@link #phenotypeValidator(Predicate)}, which will replace any
1132                 * previously set genotype validators.
1133                 *
1134                 * <p><i>Default value is set to {@code Genotype::isValid}.</i></p>
1135                 *
1136                 * @since 3.1
1137                 *
1138                 * @see #phenotypeValidator(Predicate)
1139                 *
1140                 * @param validator the {@code validator} used for validating the
1141                 *        individuals (genotypes).
1142                 * @return {@code this} builder, for command chaining
1143                 * @throws java.lang.NullPointerException if the {@code validator} is
1144                 *         {@code null}.
1145                 */
1146                public Builder<G, C> genotypeValidator(
1147                        final Predicate<? super Genotype<G>> validator
1148                ) {
1149                        requireNonNull(validator);
1150
1151                        _validator = pt -> validator.test(pt.getGenotype());
1152                        return this;
1153                }
1154
1155                /**
1156                 * The optimization strategy used by the engine. <i>Default values is
1157                 * set to {@code Optimize.MAXIMUM}.</i>
1158                 *
1159                 * @param optimize the optimization strategy used by the engine
1160                 * @return {@code this} builder, for command chaining
1161                 */
1162                public Builder<G, C> optimize(final Optimize optimize) {
1163                        _optimize = requireNonNull(optimize);
1164                        return this;
1165                }
1166
1167                /**
1168                 * Set to a fitness maximizing strategy.
1169                 *
1170                 * @since 3.4
1171                 *
1172                 * @return {@code this} builder, for command chaining
1173                 */
1174                public Builder<G, C> maximizing() {
1175                        return optimize(Optimize.MAXIMUM);
1176                }
1177
1178                /**
1179                 * Set to a fitness minimizing strategy.
1180                 *
1181                 * @since 3.4
1182                 *
1183                 * @return {@code this} builder, for command chaining
1184                 */
1185                public Builder<G, C> minimizing() {
1186                        return optimize(Optimize.MINIMUM);
1187                }
1188
1189                /**
1190                 * The offspring fraction. <i>Default values is set to {@code 0.6}.</i>
1191                 * This method call is equivalent to
1192                 * {@code survivorsFraction(1 - offspringFraction)} and will override
1193                 * any previously set survivors-fraction.
1194                 *
1195                 * @see #survivorsFraction(double)
1196                 *
1197                 * @param fraction the offspring fraction
1198                 * @return {@code this} builder, for command chaining
1199                 * @throws java.lang.IllegalArgumentException if the fraction is not
1200                 *         within the range [0, 1].
1201                 */
1202                public Builder<G, C> offspringFraction(final double fraction) {
1203                        _offspringFraction = probability(fraction);
1204                        return this;
1205                }
1206
1207                /**
1208                 * The survivors fraction. <i>Default values is set to {@code 0.4}.</i>
1209                 * This method call is equivalent to
1210                 * {@code offspringFraction(1 - survivorsFraction)} and will override
1211                 * any previously set offspring-fraction.
1212                 *
1213                 * @since 3.8
1214                 *
1215                 * @see #offspringFraction(double)
1216                 *
1217                 * @param fraction the survivors fraction
1218                 * @return {@code this} builder, for command chaining
1219                 * @throws java.lang.IllegalArgumentException if the fraction is not
1220                 *         within the range [0, 1].
1221                 */
1222                public Builder<G, C> survivorsFraction(final double fraction) {
1223                        _offspringFraction = 1.0 - probability(fraction);
1224                        return this;
1225                }
1226
1227                /**
1228                 * The number of offspring individuals.
1229                 *
1230                 * @since 3.8
1231                 *
1232                 * @param size the number of offspring individuals.
1233                 * @return {@code this} builder, for command chaining
1234                 * @throws java.lang.IllegalArgumentException if the size is not
1235                 *         within the range [0, population-size].
1236                 */
1237                public Builder<G, C> offspringSize(final int size) {
1238                        if (size < 0) {
1239                                throw new IllegalArgumentException(format(
1240                                        "Offspring size must be greater or equal zero, but was %s.",
1241                                        size
1242                                ));
1243                        }
1244
1245                        return offspringFraction((double)size/(double)_populationSize);
1246                }
1247
1248                /**
1249                 * The number of survivors.
1250                 *
1251                 * @since 3.8
1252                 *
1253                 * @param size the number of survivors.
1254                 * @return {@code this} builder, for command chaining
1255                 * @throws java.lang.IllegalArgumentException if the size is not
1256                 *         within the range [0, population-size].
1257                 */
1258                public Builder<G, C> survivorsSize(final int size) {
1259                        if (size < 0) {
1260                                throw new IllegalArgumentException(format(
1261                                        "Survivors must be greater or equal zero, but was %s.",
1262                                        size
1263                                ));
1264                        }
1265
1266                        return survivorsFraction((double)size/(double)_populationSize);
1267                }
1268
1269                /**
1270                 * The number of individuals which form the population. <i>Default
1271                 * values is set to {@code 50}.</i>
1272                 *
1273                 * @param size the number of individuals of a population
1274                 * @return {@code this} builder, for command chaining
1275                 * @throws java.lang.IllegalArgumentException if {@code size < 1}
1276                 */
1277                public Builder<G, C> populationSize(final int size) {
1278                        if (size < 1) {
1279                                throw new IllegalArgumentException(format(
1280                                        "Population size must be greater than zero, but was %s.",
1281                                        size
1282                                ));
1283                        }
1284                        _populationSize = size;
1285                        return this;
1286                }
1287
1288                /**
1289                 * The maximal allowed age of a phenotype. <i>Default values is set to
1290                 * {@code 70}.</i>
1291                 *
1292                 * @param age the maximal phenotype age
1293                 * @return {@code this} builder, for command chaining
1294                 * @throws java.lang.IllegalArgumentException if {@code age < 1}
1295                 */
1296                public Builder<G, C> maximalPhenotypeAge(final long age) {
1297                        if (age < 1) {
1298                                throw new IllegalArgumentException(format(
1299                                        "Phenotype age must be greater than one, but was %s.", age
1300                                ));
1301                        }
1302                        _maximalPhenotypeAge = age;
1303                        return this;
1304                }
1305
1306                /**
1307                 * The executor used by the engine.
1308                 *
1309                 * @param executor the executor used by the engine
1310                 * @return {@code this} builder, for command chaining
1311                 */
1312                public Builder<G, C> executor(final Executor executor) {
1313                        _executor = requireNonNull(executor);
1314                        return this;
1315                }
1316
1317                /**
1318                 * The clock used for calculating the execution durations.
1319                 *
1320                 * @param clock the clock used for calculating the execution durations
1321                 * @return {@code this} builder, for command chaining
1322                 */
1323                public Builder<G, C> clock(final Clock clock) {
1324                        _clock = requireNonNull(clock);
1325                        return this;
1326                }
1327
1328                /**
1329                 * The phenotype evaluator allows to change the evaluation strategy.
1330                 * By default, the population is evaluated concurrently using the
1331                 * defined {@link Executor} implementation.
1332                 *
1333                 * @apiNote
1334                 * This is an <em>advanced</em> {@code Engine} configuration feature,
1335                 * which should be only used when there is a performance gain from
1336                 * implementing a different evaluation strategy.
1337                 *
1338                 * @since 4.2
1339                 *
1340                 * @param evaluator the population evaluation strategy
1341                 * @return {@code this} builder, for command chaining
1342                 */
1343                public Builder<G, C> evaluator(final Evaluator<G, C> evaluator) {
1344                        _evaluator = requireNonNull(evaluator);
1345                        return this;
1346                }
1347
1348                /**
1349                 * Setting the <em>genotype</em> evaluator used for evaluating the
1350                 * fitness function of the population.
1351                 *
1352                 * @apiNote
1353                 * This is an <em>advanced</em> {@code Engine} configuration feature,
1354                 * which should be only used when there is a performance gain from
1355                 * implementing a different evaluation strategy.
1356                 *
1357                 * @since 4.2
1358                 *
1359                 * @param evaluator the genotype evaluator
1360                 * @return {@code this} builder, for command chaining
1361                 */
1362                public Builder<G, C> evaluator(final GenotypeEvaluator<G, C> evaluator) {
1363                        _evaluator = Evaluator.of(evaluator);
1364                        return this;
1365                }
1366
1367                /**
1368                 * The maximal number of attempt before the {@code Engine} gives up
1369                 * creating a valid individual ({@code Phenotype}). <i>Default values is
1370                 * set to {@code 10}.</i>
1371                 *
1372                 * @since 3.1
1373                 *
1374                 * @param retries the maximal retry count
1375                 * @throws IllegalArgumentException if the given retry {@code count} is
1376                 *         smaller than zero.
1377                 * @return {@code this} builder, for command chaining
1378                 */
1379                public Builder<G, C> individualCreationRetries(final int retries) {
1380                        if (retries < 0) {
1381                                throw new IllegalArgumentException(format(
1382                                        "Retry count must not be negative: %d",
1383                                        retries
1384                                ));
1385                        }
1386                        _individualCreationRetries = retries;
1387                        return this;
1388                }
1389
1390                /**
1391                 * The result mapper, which allows to change the evolution result after
1392                 * each generation.
1393                 *
1394                 * @since 4.0
1395                 * @see EvolutionResult#toUniquePopulation()
1396                 *
1397                 * @param mapper the evolution result mapper
1398                 * @return {@code this} builder, for command chaining
1399                 * @throws NullPointerException if the given {@code resultMapper} is
1400                 *         {@code null}
1401                 */
1402                public Builder<G, C> mapping(
1403                        final Function<
1404                                ? super EvolutionResult<G, C>,
1405                                EvolutionResult<G, C>
1406                        > mapper
1407                ) {
1408                        _mapper = requireNonNull(mapper::apply);
1409                        return this;
1410                }
1411
1412                /**
1413                 * Builds an new {@code Engine} instance from the set properties.
1414                 *
1415                 * @return an new {@code Engine} instance from the set properties
1416                 */
1417                public Engine<G, C> build() {
1418                        return new Engine<>(
1419                                _fitnessFunction,
1420                                _genotypeFactory,
1421                                _fitnessScaler,
1422                                _survivorsSelector,
1423                                _offspringSelector,
1424                                _alterer,
1425                                _validator,
1426                                _optimize,
1427                                getOffspringCount(),
1428                                getSurvivorsCount(),
1429                                _maximalPhenotypeAge,
1430                                _executor,
1431                                _evaluator != null
1432                                        ? _evaluator
1433                                        : new ConcurrentEvaluator<>(_executor),
1434                                _clock,
1435                                _individualCreationRetries,
1436                                _mapper
1437                        );
1438                }
1439
1440                private int getSurvivorsCount() {
1441                        return _populationSize - getOffspringCount();
1442                }
1443
1444                private int getOffspringCount() {
1445                        return (int)round(_offspringFraction*_populationSize);
1446                }
1447
1448                /**
1449                 * Return the used {@link Alterer} of the GA.
1450                 *
1451                 * @return the used {@link Alterer} of the GA.
1452                 */
1453                public Alterer<G, C> getAlterers() {
1454                        return _alterer;
1455                }
1456
1457                /**
1458                 * Return the {@link Clock} the engine is using for measuring the execution
1459                 * time.
1460                 *
1461                 * @since 3.1
1462                 *
1463                 * @return the clock used for measuring the execution time
1464                 */
1465                public Clock getClock() {
1466                        return _clock;
1467                }
1468
1469                /**
1470                 * Return the {@link Executor} the engine is using for executing the
1471                 * evolution steps.
1472                 *
1473                 * @since 3.1
1474                 *
1475                 * @return the executor used for performing the evolution steps
1476                 */
1477                public Executor getExecutor() {
1478                        return _executor;
1479                }
1480
1481                /**
1482                 * Return the fitness function of the GA engine.
1483                 *
1484                 * @since 3.1
1485                 *
1486                 * @return the fitness function
1487                 */
1488                public Function<? super Genotype<G>, ? extends C> getFitnessFunction() {
1489                        return _fitnessFunction;
1490                }
1491
1492                /**
1493                 * Return the fitness scaler of the GA engine.
1494                 *
1495                 * @since 3.1
1496                 *
1497                 * @return the fitness scaler
1498                 */
1499                public Function<? super C, ? extends C> getFitnessScaler() {
1500                        return _fitnessScaler;
1501                }
1502
1503                /**
1504                 * Return the used genotype {@link Factory} of the GA. The genotype factory
1505                 * is used for creating the initial population and new, random individuals
1506                 * when needed (as replacement for invalid and/or died genotypes).
1507                 *
1508                 * @since 3.1
1509                 *
1510                 * @return the used genotype {@link Factory} of the GA.
1511                 */
1512                public Factory<Genotype<G>> getGenotypeFactory() {
1513                        return _genotypeFactory;
1514                }
1515
1516                /**
1517                 * Return the maximal allowed phenotype age.
1518                 *
1519                 * @since 3.1
1520                 *
1521                 * @return the maximal allowed phenotype age
1522                 */
1523                public long getMaximalPhenotypeAge() {
1524                        return _maximalPhenotypeAge;
1525                }
1526
1527                /**
1528                 * Return the offspring fraction.
1529                 *
1530                 * @return the offspring fraction.
1531                 */
1532                public double getOffspringFraction() {
1533                        return _offspringFraction;
1534                }
1535
1536                /**
1537                 * Return the used offspring {@link Selector} of the GA.
1538                 *
1539                 * @since 3.1
1540                 *
1541                 * @return the used offspring {@link Selector} of the GA.
1542                 */
1543                public Selector<G, C> getOffspringSelector() {
1544                        return _offspringSelector;
1545                }
1546
1547                /**
1548                 * Return the used survivor {@link Selector} of the GA.
1549                 *
1550                 * @since 3.1
1551                 *
1552                 * @return the used survivor {@link Selector} of the GA.
1553                 */
1554                public Selector<G, C> getSurvivorsSelector() {
1555                        return _survivorsSelector;
1556                }
1557
1558                /**
1559                 * Return the optimization strategy.
1560                 *
1561                 * @since 3.1
1562                 *
1563                 * @return the optimization strategy
1564                 */
1565                public Optimize getOptimize() {
1566                        return _optimize;
1567                }
1568
1569                /**
1570                 * Return the number of individuals of a population.
1571                 *
1572                 * @since 3.1
1573                 *
1574                 * @return the number of individuals of a population
1575                 */
1576                public int getPopulationSize() {
1577                        return _populationSize;
1578                }
1579
1580                /**
1581                 * Return the maximal number of attempt before the {@code Engine} gives
1582                 * up creating a valid individual ({@code Phenotype}).
1583                 *
1584                 * @since 3.1
1585                 *
1586                 * @return the maximal number of {@code Phenotype} creation attempts
1587                 */
1588                public int getIndividualCreationRetries() {
1589                        return _individualCreationRetries;
1590                }
1591
1592                /**
1593                 * Return the evolution result mapper.
1594                 *
1595                 * @since 4.0
1596                 *
1597                 * @return the evolution result mapper
1598                 */
1599                public UnaryOperator<EvolutionResult<G, C>> getMapper() {
1600                        return _mapper;
1601                }
1602
1603                /**
1604                 * Create a new builder, with the current configuration.
1605                 *
1606                 * @since 3.1
1607                 *
1608                 * @return a new builder, with the current configuration
1609                 */
1610                @Override
1611                public Builder<G, C> copy() {
1612                        return new Builder<G, C>(_genotypeFactory, _fitnessFunction)
1613                                .alterers(_alterer)
1614                                .clock(_clock)
1615                                .executor(_executor)
1616                                .evaluator(_evaluator)
1617                                .fitnessScaler(_fitnessScaler)
1618                                .maximalPhenotypeAge(_maximalPhenotypeAge)
1619                                .offspringFraction(_offspringFraction)
1620                                .offspringSelector(_offspringSelector)
1621                                .phenotypeValidator(_validator)
1622                                .optimize(_optimize)
1623                                .populationSize(_populationSize)
1624                                .survivorsSelector(_survivorsSelector)
1625                                .individualCreationRetries(_individualCreationRetries)
1626                                .mapping(_mapper);
1627                }
1628
1629        }
1630
1631}