001/*
002 * Java Genetic Algorithm Library (jenetics-7.2.0).
003 * Copyright (c) 2007-2023 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.String.format;
023import static java.util.Objects.requireNonNull;
024import static java.util.concurrent.CompletableFuture.supplyAsync;
025import static java.util.concurrent.ForkJoinPool.commonPool;
026
027import java.time.InstantSource;
028import java.util.concurrent.CompletableFuture;
029import java.util.concurrent.Executor;
030import java.util.function.Function;
031import java.util.function.Supplier;
032import java.util.stream.Stream;
033
034import io.jenetics.Alterer;
035import io.jenetics.AltererResult;
036import io.jenetics.Chromosome;
037import io.jenetics.Gene;
038import io.jenetics.Genotype;
039import io.jenetics.Optimize;
040import io.jenetics.Phenotype;
041import io.jenetics.Selector;
042import io.jenetics.util.Copyable;
043import io.jenetics.util.Factory;
044import io.jenetics.util.ISeq;
045import io.jenetics.util.MSeq;
046import io.jenetics.util.NanoClock;
047import io.jenetics.util.Seq;
048
049/**
050 * Genetic algorithm <em>engine</em> which is the main class. The following
051 * example shows the main steps in initializing and executing the GA.
052 *
053 * <pre>{@code
054 * public class RealFunction {
055 *    // Definition of the fitness function.
056 *    private static Double eval(final Genotype<DoubleGene> gt) {
057 *        final double x = gt.gene().doubleValue();
058 *        return cos(0.5 + sin(x))*cos(x);
059 *    }
060 *
061 *    public static void main(String[] args) {
062 *        // Create/configuring the engine via its builder.
063 *        final Engine<DoubleGene, Double> engine = Engine
064 *            .builder(
065 *                RealFunction::eval,
066 *                DoubleChromosome.of(0.0, 2.0*PI))
067 *            .populationSize(500)
068 *            .optimize(Optimize.MINIMUM)
069 *            .alterers(
070 *                new Mutator<>(0.03),
071 *                new MeanAlterer<>(0.6))
072 *            .build();
073 *
074 *        // Execute the GA (engine).
075 *        final Phenotype<DoubleGene, Double> result = engine.stream()
076 *             // Truncate the evolution stream if no better individual could
077 *             // be found after 5 consecutive generations.
078 *            .limit(bySteadyFitness(5))
079 *             // Terminate the evolution after maximal 100 generations.
080 *            .limit(100)
081 *            .collect(toBestPhenotype());
082 *     }
083 * }
084 * }</pre>
085 *
086 * The architecture allows to decouple the configuration of the engine from the
087 * execution. The {@code Engine} is configured via the {@code Engine.Builder}
088 * class and can't be changed after creation. The actual <i>evolution</i> is
089 * performed by the {@link EvolutionStream}, which is created by the
090 * {@code Engine}.
091 *
092 * @implNote
093 *     This class is thread safe: The engine maintains no mutable state.
094 *     Therefore, it is safe to create multiple evolution streams with one
095 *     engine, which may be actually used in different threads.
096 *
097 * @see Engine.Builder
098 * @see EvolutionStart
099 * @see EvolutionResult
100 * @see EvolutionStream
101 * @see EvolutionStatistics
102 * @see Codec
103 * @see Constraint
104 *
105 * @param <G> the gene type
106 * @param <C> the fitness result type
107 *
108 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
109 * @since 3.0
110 * @version 7.0
111 */
112public final class Engine<
113        G extends Gene<?, G>,
114        C extends Comparable<? super C>
115>
116        implements
117                Evolution<G, C>,
118                EvolutionStreamable<G, C>,
119                Evaluator<G, C>
120{
121
122        // Problem definition.
123        private final Evaluator<G, C> _evaluator;
124        private final Factory<Genotype<G>> _genotypeFactory;
125        private final Constraint<G, C> _constraint;
126        private final Optimize _optimize;
127
128        // Evolution parameters.
129        private final EvolutionParams<G, C> _evolutionParams;
130
131        // Execution context for concurrent execution of evolving steps.
132        private final Executor _executor;
133        private final InstantSource _clock;
134        private final EvolutionInterceptor<G, C> _interceptor;
135
136
137        /**
138         * Create a new GA engine with the given parameters.
139         *
140         * @param evaluator the population fitness evaluator
141         * @param genotypeFactory the genotype factory this GA is working with.
142         * @param constraint phenotype constraint which can override the default
143         *        implementation the {@link Phenotype#isValid()} method and repairs
144         *        invalid phenotypes when needed.
145         * @param optimize the kind of optimization (minimize or maximize)
146         * @param evolutionParams the evolution parameters, which influences the
147         *        evolution process
148         * @param executor the executor used for executing the single evolved steps
149         * @param clock the clock used for calculating the timing results
150         * @param interceptor the evolution interceptor, which gives additional
151         *        possibilities to influence the actual evolution
152         * @throws NullPointerException if one of the arguments is {@code null}
153         * @throws IllegalArgumentException if the given integer values are smaller
154         *         than one.
155         */
156        Engine(
157                final Evaluator<G, C> evaluator,
158                final Factory<Genotype<G>> genotypeFactory,
159                final Constraint<G, C> constraint,
160                final Optimize optimize,
161                final EvolutionParams<G, C> evolutionParams,
162                final Executor executor,
163                final InstantSource clock,
164                final EvolutionInterceptor<G, C> interceptor
165        ) {
166                _evaluator = requireNonNull(evaluator);
167                _genotypeFactory = requireNonNull(genotypeFactory);
168                _constraint = requireNonNull(constraint);
169                _optimize = requireNonNull(optimize);
170                _evolutionParams = requireNonNull(evolutionParams);
171                _executor = requireNonNull(executor);
172                _clock = requireNonNull(clock);
173                _interceptor = requireNonNull(interceptor);
174        }
175
176        @Override
177        public EvolutionResult<G, C> evolve(final EvolutionStart<G, C> start) {
178                final EvolutionTiming timing = new EvolutionTiming(_clock);
179                timing.evolve.start();
180
181                final EvolutionStart<G, C> interceptedStart = _interceptor.before(start);
182
183                // Create initial population if `start` is empty.
184                final EvolutionStart<G, C> es = interceptedStart.population().isEmpty()
185                        ? evolutionStart(interceptedStart)
186                        : interceptedStart;
187
188                // Initial evaluation of the population.
189                final ISeq<Phenotype<G, C>> population = es.isDirty()
190                        ? timing.evaluation.timing(() -> eval(es.population()))
191                        : es.population();
192
193                // Select the offspring population.
194                final CompletableFuture<ISeq<Phenotype<G, C>>> offspring =
195                        supplyAsync(() ->
196                                timing.offspringSelection.timing(() ->
197                                        selectOffspring(population)
198                                ),
199                                _executor
200                        );
201
202                // Select the survivor population.
203                final CompletableFuture<ISeq<Phenotype<G, C>>> survivors =
204                        supplyAsync(() ->
205                                timing.survivorsSelection.timing(() ->
206                                        selectSurvivors(population)
207                                ),
208                                _executor
209                        );
210
211                // Altering the offspring population.
212                final CompletableFuture<AltererResult<G, C>> alteredOffspring =
213                        offspring.thenApplyAsync(off ->
214                                timing.offspringAlter.timing(() ->
215                                        _evolutionParams.alterer().alter(off, es.generation())
216                                ),
217                                _executor
218                        );
219
220                // Filter and replace invalid and old survivor individuals.
221                final CompletableFuture<FilterResult<G, C>> filteredSurvivors =
222                        survivors.thenApplyAsync(sur ->
223                                timing.survivorFilter.timing(() ->
224                                        filter(sur, es.generation())
225                                ),
226                                _executor
227                        );
228
229                // Filter and replace invalid and old offspring individuals.
230                final CompletableFuture<FilterResult<G, C>> filteredOffspring =
231                        alteredOffspring.thenApplyAsync(off ->
232                                timing.offspringFilter.timing(() ->
233                                        filter(off.population(), es.generation())
234                                ),
235                                _executor
236                        );
237
238                // Combining survivors and offspring to the new population.
239                final CompletableFuture<ISeq<Phenotype<G, C>>> nextPopulation =
240                        filteredSurvivors.thenCombineAsync(
241                                filteredOffspring,
242                                (s, o) -> ISeq.of(s.population().append(o.population())),
243                                _executor
244                        );
245
246                // Evaluate the fitness-function and wait for a result.
247                final ISeq<Phenotype<G, C>> pop = nextPopulation.join();
248                final ISeq<Phenotype<G, C>> result = timing.evaluation.timing(() ->
249                        eval(pop)
250                );
251
252                final int killCount =
253                        filteredOffspring.join().killCount() +
254                        filteredSurvivors.join().killCount();
255
256                final int invalidCount =
257                        filteredOffspring.join().invalidCount() +
258                        filteredSurvivors.join().invalidCount();
259
260                final int alterationCount = alteredOffspring.join().alterations();
261
262                EvolutionResult<G, C> er = EvolutionResult.of(
263                        _optimize,
264                        result,
265                        es.generation(),
266                        timing.toDurations(),
267                        killCount,
268                        invalidCount,
269                        alterationCount
270                );
271
272                final EvolutionResult<G, C> interceptedResult = _interceptor.after(er);
273                if (er != interceptedResult) {
274                        er = interceptedResult.withPopulation(
275                                timing.evaluation.timing(() ->
276                                        eval(interceptedResult.population())
277                        ));
278                }
279
280                timing.evolve.stop();
281
282                return er
283                        .withDurations(timing.toDurations())
284                        .clean();
285        }
286
287        // Selects the survivor population. A new population object is returned.
288        private ISeq<Phenotype<G, C>>
289        selectSurvivors(final ISeq<Phenotype<G, C>> population) {
290                return _evolutionParams.survivorsSize() > 0
291                        ? _evolutionParams.survivorsSelector()
292                                .select(population, _evolutionParams.survivorsSize(), _optimize)
293                        : ISeq.empty();
294        }
295
296        // Selects the offspring population. A new population object is returned.
297        private ISeq<Phenotype<G, C>>
298        selectOffspring(final ISeq<Phenotype<G, C>> population) {
299                return _evolutionParams.offspringSize() > 0
300                        ? _evolutionParams.offspringSelector()
301                                .select(population, _evolutionParams.offspringSize(), _optimize)
302                        : ISeq.empty();
303        }
304
305        // Filters out invalid and old individuals. Filtering is done in place.
306        private FilterResult<G, C> filter(
307                final Seq<Phenotype<G, C>> population,
308                final long generation
309        ) {
310                int killCount = 0;
311                int invalidCount = 0;
312
313                final MSeq<Phenotype<G, C>> pop = MSeq.of(population);
314                for (int i = 0, n = pop.size(); i < n; ++i) {
315                        final Phenotype<G, C> individual = pop.get(i);
316
317                        if (!_constraint.test(individual)) {
318                                pop.set(i, _constraint.repair(individual, generation));
319                                ++invalidCount;
320                        } else if (individual.age(generation) >
321                                                _evolutionParams.maximalPhenotypeAge())
322                        {
323                                pop.set(i, Phenotype.of(_genotypeFactory.newInstance(), generation));
324                                ++killCount;
325                        }
326                }
327
328                return new FilterResult<>(pop.toISeq(), killCount, invalidCount);
329        }
330
331
332        /* *************************************************************************
333         * Evaluation methods.
334         **************************************************************************/
335
336        /**
337         * Evaluates the fitness function of the given population with the configured
338         * {@link Evaluator} of this engine and returns a new population
339         * with its fitness value assigned.
340         *
341         * @since 5.0
342         *
343         * @see Evaluator
344         * @see Evaluator#eval(Seq)
345         *
346         * @param population the population to evaluate
347         * @return a new population with assigned fitness values
348         * @throws IllegalStateException if the configured fitness function doesn't
349         *         return a population with the same size as the input population.
350         *         This exception is also thrown if one of the populations
351         *         phenotype has no fitness value assigned.
352         */
353        @Override
354        public ISeq<Phenotype<G, C>> eval(final Seq<Phenotype<G, C>> population) {
355                final ISeq<Phenotype<G, C>> evaluated = _evaluator.eval(population);
356
357                if (population.size() != evaluated.size()) {
358                        throw new IllegalStateException(format(
359                                "Expected %d individuals, but got %d. " +
360                                        "Check your evaluator function.",
361                                population.size(), evaluated.size()
362                        ));
363                }
364                if (!evaluated.forAll(Phenotype::isEvaluated)) {
365                        throw new IllegalStateException(
366                                "Some phenotypes have no assigned fitness value. " +
367                                        "Check your evaluator function."
368                        );
369                }
370
371                return evaluated;
372        }
373
374
375        /* *************************************************************************
376         * Evolution Stream creation.
377         **************************************************************************/
378
379        @Override
380        public EvolutionStream<G, C>
381        stream(final Supplier<EvolutionStart<G, C>> start) {
382                return EvolutionStream.ofEvolution(
383                        () -> evolutionStart(start.get()),
384                        this
385                );
386        }
387
388        @Override
389        public EvolutionStream<G, C> stream(final EvolutionInit<G> init) {
390                return stream(evolutionStart(init));
391        }
392
393        private EvolutionStart<G, C>
394        evolutionStart(final EvolutionStart<G, C> start) {
395                final ISeq<Phenotype<G, C>> population = start.population();
396                final long gen = start.generation();
397
398                final Stream<Phenotype<G, C>> stream = Stream.concat(
399                        population.stream(),
400                        _genotypeFactory.instances()
401                                .map(gt -> Phenotype.of(gt, gen))
402                );
403
404                final ISeq<Phenotype<G, C>> pop = stream
405                        .limit(populationSize())
406                        .collect(ISeq.toISeq());
407
408                return EvolutionStart.of(pop, gen);
409        }
410
411        private EvolutionStart<G, C>
412        evolutionStart(final EvolutionInit<G> init) {
413                final ISeq<Genotype<G>> pop = init.population();
414                final long gen = init.generation();
415
416                return evolutionStart(
417                        EvolutionStart.of(
418                                pop.map(gt -> Phenotype.of(gt, gen)),
419                                gen
420                        )
421                );
422        }
423
424        /* *************************************************************************
425         * Property access methods.
426         **************************************************************************/
427
428        /**
429         * Return the used genotype {@link Factory} of the GA. The genotype factory
430         * is used for creating the initial population and new, random individuals
431         * when needed (as replacement for invalid and/or died genotypes).
432         *
433         * @return the used genotype {@link Factory} of the GA.
434         */
435        public Factory<Genotype<G>> genotypeFactory() {
436                return _genotypeFactory;
437        }
438
439        /**
440         * Return the constraint of the evolution problem.
441         *
442         * @since 5.0
443         *
444         * @return the constraint of the evolution problem
445         */
446        public Constraint<G, C> constraint() {
447                return _constraint;
448        }
449
450        /**
451         * Return the used survivor {@link Selector} of the GA.
452         *
453         * @return the used survivor {@link Selector} of the GA.
454         */
455        public Selector<G, C> survivorsSelector() {
456                return _evolutionParams.survivorsSelector();
457        }
458
459        /**
460         * Return the used offspring {@link Selector} of the GA.
461         *
462         * @return the used offspring {@link Selector} of the GA.
463         */
464        public Selector<G, C> offspringSelector() {
465                return _evolutionParams.offspringSelector();
466        }
467
468        /**
469         * Return the used {@link Alterer} of the GA.
470         *
471         * @return the used {@link Alterer} of the GA.
472         */
473        public Alterer<G, C> alterer() {
474                return _evolutionParams.alterer();
475        }
476
477        /**
478         * Return the number of selected offspring.
479         *
480         * @return the number of selected offspring
481         */
482        public int offspringSize() {
483                return _evolutionParams.offspringSize();
484        }
485
486        /**
487         * The number of selected survivors.
488         *
489         * @return the number of selected survivors
490         */
491        public int survivorsSize() {
492                return _evolutionParams.survivorsSize();
493        }
494
495        /**
496         * Return the number of individuals of a population.
497         *
498         * @return the number of individuals of a population
499         */
500        public int populationSize() {
501                return _evolutionParams.populationSize();
502        }
503
504        /**
505         * Return the maximal allowed phenotype age.
506         *
507         * @return the maximal allowed phenotype age
508         */
509        public long maximalPhenotypeAge() {
510                return _evolutionParams.maximalPhenotypeAge();
511        }
512
513        /**
514         * Return the optimization strategy.
515         *
516         * @return the optimization strategy
517         */
518        public Optimize optimize() {
519                return _optimize;
520        }
521
522        /**
523         * Return the {@link InstantSource} the engine is using for measuring the
524         * execution time.
525         *
526         * @return the clock used for measuring the execution time
527         */
528        public InstantSource clock() {
529                return _clock;
530        }
531
532        /**
533         * Return the {@link Executor} the engine is using for executing the
534         * evolution steps.
535         *
536         * @return the executor used for performing the evolution steps
537         */
538        public Executor executor() {
539                return _executor;
540        }
541
542        /**
543         * Return the evolution interceptor.
544         *
545         * @since 6.0
546         *
547         * @return the evolution result mapper
548         */
549        public EvolutionInterceptor<G, C> interceptor() {
550                return _interceptor;
551        }
552
553        /**
554         * Create a new evolution {@code Engine.Builder} initialized with the values
555         * of the current evolution {@code Engine}. With this method, the evolution
556         * engine can serve as a template for a new one.
557         *
558         * @return a new engine builder
559         */
560        public Builder<G, C> toBuilder() {
561                return new Builder<>(_evaluator, _genotypeFactory)
562                        .clock(_clock)
563                        .executor(_executor)
564                        .optimize(_optimize)
565                        .constraint(_constraint)
566                        .evolutionParams(_evolutionParams)
567                        .interceptor(_interceptor);
568        }
569
570
571        /* *************************************************************************
572         * Static Builder methods.
573         **************************************************************************/
574
575        /**
576         * Create a new evolution {@code Engine.Builder} with the given fitness
577         * function and genotype factory.
578         *
579         * @param ff the fitness function
580         * @param gtf the genotype factory
581         * @param <G> the gene type
582         * @param <C> the fitness function result type
583         * @return a new engine builder
584         * @throws java.lang.NullPointerException if one of the arguments is
585         *         {@code null}.
586         */
587        public static <G extends Gene<?, G>, C extends Comparable<? super C>>
588        Builder<G, C> builder(
589                final Function<? super Genotype<G>, ? extends C> ff,
590                final Factory<Genotype<G>> gtf
591        ) {
592                return new Builder<>(Evaluators.concurrent(ff, commonPool()), gtf);
593        }
594
595        /**
596         * Create a new evolution {@code Engine.Builder} with the given fitness
597         * function and problem {@code codec}.
598         *
599         * @since 3.2
600         *
601         * @param ff the fitness evaluator
602         * @param codec the problem codec
603         * @param <T> the fitness function input type
604         * @param <C> the fitness function result type
605         * @param <G> the gene type
606         * @return a new engine builder
607         * @throws java.lang.NullPointerException if one of the arguments is
608         *         {@code null}.
609         */
610        public static <T, G extends Gene<?, G>, C extends Comparable<? super C>>
611        Builder<G, C> builder(
612                final Function<? super T, ? extends C> ff,
613                final Codec<T, G> codec
614        ) {
615                return builder(ff.compose(codec.decoder()), codec.encoding());
616        }
617
618        /**
619         * Create a new evolution {@code Engine.Builder} for the given
620         * {@link Problem}.
621         *
622         * @since 3.4
623         *
624         * @param problem the problem to be solved by the evolution {@code Engine}
625         * @param <T> the (<i>native</i>) argument type of the problem fitness function
626         * @param <G> the gene type the evolution engine is working with
627         * @param <C> the result type of the fitness function
628         * @return Create a new evolution {@code Engine.Builder}
629         */
630        public static <T, G extends Gene<?, G>, C extends Comparable<? super C>>
631        Builder<G, C> builder(final Problem<T, G, C> problem) {
632                final var builder = builder(problem.fitness(), problem.codec());
633                problem.constraint().ifPresent(builder::constraint);
634                return builder;
635        }
636
637        /**
638         * Create a new evolution {@code Engine.Builder} with the given fitness
639         * function and chromosome templates.
640         *
641         * @param ff the fitness function
642         * @param chromosome the first chromosome
643         * @param chromosomes the chromosome templates
644         * @param <G> the gene type
645         * @param <C> the fitness function result type
646         * @return a new engine builder
647         * @throws java.lang.NullPointerException if one of the arguments is
648         *         {@code null}.
649         */
650        @SafeVarargs
651        public static <G extends Gene<?, G>, C extends Comparable<? super C>>
652        Builder<G, C> builder(
653                final Function<? super Genotype<G>, ? extends C> ff,
654                final Chromosome<G> chromosome,
655                final Chromosome<G>... chromosomes
656        ) {
657                return builder(ff, Genotype.of(chromosome, chromosomes));
658        }
659
660
661        /* *************************************************************************
662         * Engine builder
663         **************************************************************************/
664
665
666        /**
667         * Builder class for building GA {@code Engine} instances.
668         *
669         * @see Engine
670         *
671         * @param <G> the gene type
672         * @param <C> the fitness function result type
673         *
674         * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
675         * @since 3.0
676         * @version 6.0
677         */
678        public static final class Builder<
679                G extends Gene<?, G>,
680                C extends Comparable<? super C>
681        >
682                implements Copyable<Builder<G, C>>
683        {
684
685                // No default values for this properties.
686                private final Evaluator<G, C> _evaluator;
687                private final Factory<Genotype<G>> _genotypeFactory;
688                private Constraint<G, C> _constraint;
689                private Optimize _optimize = Optimize.MAXIMUM;
690
691                // Evolution parameters.
692                private final EvolutionParams.Builder<G, C> _evolutionParams =
693                        EvolutionParams.builder();
694
695
696                // Engine execution environment.
697                private Executor _executor = commonPool();
698                private InstantSource _clock = NanoClock.systemUTC();
699
700                private EvolutionInterceptor<G, C> _interceptor =
701                        EvolutionInterceptor.identity();
702
703                /**
704                 * Create a new evolution {@code Engine.Builder} with the given fitness
705                 * evaluator and genotype factory. This is the most general way of
706                 * creating an engine builder.
707                 *
708                 * @since 5.0
709                 *
710                 * @see Engine#builder(Function, Codec)
711                 * @see Engine#builder(Function, Factory)
712                 * @see Engine#builder(Problem)
713                 * @see Engine#builder(Function, Chromosome, Chromosome[])
714                 *
715                 * @param evaluator the fitness evaluator
716                 * @param genotypeFactory the genotype factory
717                 * @throws NullPointerException if one of the arguments is {@code null}.
718                 */
719                public Builder(
720                        final Evaluator<G, C> evaluator,
721                        final Factory<Genotype<G>> genotypeFactory
722                ) {
723                        _genotypeFactory = requireNonNull(genotypeFactory);
724                        _evaluator = requireNonNull(evaluator);
725                }
726
727                /**
728                 * Applies the given {@code setup} recipe to {@code this} engine builder.
729                 *
730                 * @since 6.0
731                 *
732                 * @param setup the setup recipe applying to {@code this} builder
733                 * @return {@code this} builder, for command chaining
734                 * @throws NullPointerException if the {@code setup} is {@code null}.
735                 */
736                public Builder<G, C> setup(final Setup<G, C> setup) {
737                        setup.apply(this);
738                        return this;
739                }
740
741                /**
742                 * Set the evolution parameters used by the engine.
743                 *
744                 * @since 5.2
745                 *
746                 * @param params the evolution parameter
747                 * @return {@code this} builder, for command chaining
748                 * @throws NullPointerException if the {@code params} is {@code null}.
749                 */
750                public Builder<G, C> evolutionParams(final EvolutionParams<G, C> params) {
751                        _evolutionParams.evolutionParams(params);
752                        return this;
753                }
754
755                /**
756                 * The selector used for selecting the offspring population. <i>Default
757                 * values is set to {@code TournamentSelector<>(3)}.</i>
758                 *
759                 * @param selector used for selecting the offspring population
760                 * @return {@code this} builder, for command chaining
761                 * @throws NullPointerException if one of the {@code selector} is
762                 *         {@code null}.
763                 */
764                public Builder<G, C> offspringSelector(final Selector<G, C> selector) {
765                        _evolutionParams.offspringSelector(selector);
766                        return this;
767                }
768
769                /**
770                 * The selector used for selecting the survivor population. <i>Default
771                 * values is set to {@code TournamentSelector<>(3)}.</i>
772                 *
773                 * @param selector used for selecting survivor population
774                 * @return {@code this} builder, for command chaining
775                 * @throws NullPointerException if one of the {@code selector} is
776                 *         {@code null}.
777                 */
778                public Builder<G, C> survivorsSelector(final Selector<G, C> selector) {
779                        _evolutionParams.survivorsSelector(selector);
780                        return this;
781                }
782
783                /**
784                 * The selector used for selecting the survivors and offspring
785                 * population. <i>Default values is set to
786                 * {@code TournamentSelector<>(3)}.</i>
787                 *
788                 * @param selector used for selecting survivors and offspring population
789                 * @return {@code this} builder, for command chaining
790                 * @throws NullPointerException if one of the {@code selector} is
791                 *         {@code null}.
792                 */
793                public Builder<G, C> selector(final Selector<G, C> selector) {
794                        _evolutionParams.selector(selector);
795                        return this;
796                }
797
798                /**
799                 * The alterers used for alter the offspring population. <i>Default
800                 * values is set to {@code new SinglePointCrossover<>(0.2)} followed by
801                 * {@code new Mutator<>(0.15)}.</i>
802                 *
803                 * @param first the first alterer used for alter the offspring
804                 *        population
805                 * @param rest the rest of the alterers used for alter the offspring
806                 *        population
807                 * @return {@code this} builder, for command chaining
808                 * @throws NullPointerException if one of the alterers is {@code null}.
809                 */
810                @SafeVarargs
811                public final Builder<G, C> alterers(
812                        final Alterer<G, C> first,
813                        final Alterer<G, C>... rest
814                ) {
815                        _evolutionParams.alterers(first, rest);
816                        return this;
817                }
818
819                /**
820                 * The phenotype constraint is used for detecting invalid individuals
821                 * and repairing them.
822                 *
823                 * <p><i>Default implementation uses {@code Phenotype::isValid} for
824                 * validating the phenotype.</i></p>
825                 *
826                 * @since 5.0
827                 *
828                 * @param constraint phenotype constraint which can override the default
829                 *        implementation the {@link Phenotype#isValid()} method and repairs
830                 *        invalid phenotypes when needed.
831                 * @return {@code this} builder, for command chaining
832                 * @throws NullPointerException if one of the {@code constraint} is
833                 *         {@code null}.
834                 */
835                public Builder<G, C> constraint(final Constraint<G, C> constraint) {
836                        _constraint = constraint;
837                        return this;
838                }
839
840                /**
841                 * The optimization strategy used by the engine. <i>Default values is
842                 * set to {@code Optimize.MAXIMUM}.</i>
843                 *
844                 * @param optimize the optimization strategy used by the engine
845                 * @return {@code this} builder, for command chaining
846                 * @throws NullPointerException if one of the {@code optimize} is
847                 *         {@code null}.
848                 */
849                public Builder<G, C> optimize(final Optimize optimize) {
850                        _optimize = requireNonNull(optimize);
851                        return this;
852                }
853
854                /**
855                 * Set to a fitness-maximizing strategy.
856                 *
857                 * @since 3.4
858                 *
859                 * @return {@code this} builder, for command chaining
860                 */
861                public Builder<G, C> maximizing() {
862                        return optimize(Optimize.MAXIMUM);
863                }
864
865                /**
866                 * Set to a fitness minimizing strategy.
867                 *
868                 * @since 3.4
869                 *
870                 * @return {@code this} builder, for command chaining
871                 */
872                public Builder<G, C> minimizing() {
873                        return optimize(Optimize.MINIMUM);
874                }
875
876                /**
877                 * The offspring fraction. <i>Default values is set to {@code 0.6}.</i>
878                 * This method call is equivalent to
879                 * {@code survivorsFraction(1 - offspringFraction)} and will override
880                 * any previously set survivors-fraction.
881                 *
882                 * @see #survivorsFraction(double)
883                 *
884                 * @param fraction the offspring fraction
885                 * @return {@code this} builder, for command chaining
886                 * @throws java.lang.IllegalArgumentException if the fraction is not
887                 *         within the range [0, 1].
888                 */
889                public Builder<G, C> offspringFraction(final double fraction) {
890                        _evolutionParams.offspringFraction(fraction);
891                        return this;
892                }
893
894                /**
895                 * The survivor fraction. <i>Default values is set to {@code 0.4}.</i>
896                 * This method call is equivalent to
897                 * {@code offspringFraction(1 - survivorsFraction)} and will override
898                 * any previously set offspring-fraction.
899                 *
900                 * @since 3.8
901                 *
902                 * @see #offspringFraction(double)
903                 *
904                 * @param fraction the survivor fraction
905                 * @return {@code this} builder, for command chaining
906                 * @throws java.lang.IllegalArgumentException if the fraction is not
907                 *         within the range [0, 1].
908                 */
909                public Builder<G, C> survivorsFraction(final double fraction) {
910                        return offspringFraction(1 - fraction);
911                }
912
913                /**
914                 * The number of offspring individuals.
915                 *
916                 * @since 3.8
917                 *
918                 * @param size the number of offspring individuals.
919                 * @return {@code this} builder, for command chaining
920                 * @throws java.lang.IllegalArgumentException if the size is not
921                 *         within the range [0, population-size].
922                 */
923                public Builder<G, C> offspringSize(final int size) {
924                        if (size < 0) {
925                                throw new IllegalArgumentException(format(
926                                        "Offspring size must be greater or equal zero, but was %s.",
927                                        size
928                                ));
929                        }
930
931                        return offspringFraction(size/(double)_evolutionParams.populationSize());
932                }
933
934                /**
935                 * The number of survivors.
936                 *
937                 * @since 3.8
938                 *
939                 * @param size the number of survivors.
940                 * @return {@code this} builder, for command chaining
941                 * @throws java.lang.IllegalArgumentException if the size is not
942                 *         within the range [0, population-size].
943                 */
944                public Builder<G, C> survivorsSize(final int size) {
945                        if (size < 0) {
946                                throw new IllegalArgumentException(format(
947                                        "Survivors must be greater or equal zero, but was %s.",
948                                        size
949                                ));
950                        }
951
952                        return survivorsFraction(size/(double)_evolutionParams.populationSize());
953                }
954
955                /**
956                 * The number of individuals which form the population. <i>Default
957                 * values is set to {@code 50}.</i>
958                 *
959                 * @param size the number of individuals of a population
960                 * @return {@code this} builder, for command chaining
961                 * @throws java.lang.IllegalArgumentException if {@code size < 1}
962                 */
963                public Builder<G, C> populationSize(final int size) {
964                        _evolutionParams.populationSize(size);
965                        return this;
966                }
967
968                /**
969                 * The maximal allowed age of a phenotype. <i>Default values is set to
970                 * {@code 70}.</i>
971                 *
972                 * @param age the maximal phenotype age
973                 * @return {@code this} builder, for command chaining
974                 * @throws java.lang.IllegalArgumentException if {@code age < 1}
975                 */
976                public Builder<G, C> maximalPhenotypeAge(final long age) {
977                        _evolutionParams.maximalPhenotypeAge(age);
978                        return this;
979                }
980
981                /**
982                 * The executor used by the engine.
983                 *
984                 * @param executor the executor used by the engine
985                 * @return {@code this} builder, for command chaining
986                 */
987                public Builder<G, C> executor(final Executor executor) {
988                        _executor = requireNonNull(executor);
989                        return this;
990                }
991
992                /**
993                 * The clock used for calculating the execution durations.
994                 *
995                 * @param clock the clock used for calculating the execution durations
996                 * @return {@code this} builder, for command chaining
997                 */
998                public Builder<G, C> clock(final InstantSource clock) {
999                        _clock = requireNonNull(clock);
1000                        return this;
1001                }
1002
1003                /**
1004                 * The evolution interceptor, which allows to change the evolution start
1005                 * and result.
1006                 *
1007                 * @since 6.0
1008                 * @see EvolutionResult#toUniquePopulation()
1009                 *
1010                 * @param interceptor the evolution interceptor
1011                 * @return {@code this} builder, for command chaining
1012                 * @throws NullPointerException if the given {@code interceptor} is
1013                 *         {@code null}
1014                 */
1015                public Builder<G, C>
1016                interceptor(final EvolutionInterceptor<G, C> interceptor) {
1017                        _interceptor = requireNonNull(interceptor);
1018                        return this;
1019                }
1020
1021                /**
1022                 * Builds a new {@code Engine} instance from the set properties.
1023                 *
1024                 * @return a new {@code Engine} instance from the set properties
1025                 */
1026                public Engine<G, C> build() {
1027                        return new Engine<>(
1028                                __evaluator(),
1029                                _genotypeFactory,
1030                                __constraint(),
1031                                _optimize,
1032                                _evolutionParams.build(),
1033                                _executor,
1034                                _clock,
1035                                _interceptor
1036                        );
1037                }
1038
1039                private Evaluator<G, C> __evaluator() {
1040                        return _evaluator instanceof ConcurrentEvaluator<G, C> ce
1041                                ? ce.with(_executor)
1042                                : _evaluator;
1043                }
1044
1045                private Constraint<G, C> __constraint() {
1046                        return _constraint == null
1047                                ? RetryConstraint.of(_genotypeFactory)
1048                                : _constraint;
1049                }
1050
1051                /* *********************************************************************
1052                 * Current properties
1053                 ***********************************************************************/
1054
1055                /**
1056                 * Return the used {@link Alterer} of the GA.
1057                 *
1058                 * @return the used {@link Alterer} of the GA.
1059                 */
1060                public Alterer<G, C> alterer() {
1061                        return _evolutionParams.alterer();
1062                }
1063
1064                /**
1065                 * Return the {@link InstantSource} the engine is using for measuring
1066                 * the execution time.
1067                 *
1068                 * @since 3.1
1069                 *
1070                 * @return the clock used for measuring the execution time
1071                 */
1072                public InstantSource clock() {
1073                        return _clock;
1074                }
1075
1076                /**
1077                 * Return the {@link Executor} the engine is using for executing the
1078                 * evolution steps.
1079                 *
1080                 * @since 3.1
1081                 *
1082                 * @return the executor used for performing the evolution steps
1083                 */
1084                public Executor executor() {
1085                        return _executor;
1086                }
1087
1088                /**
1089                 * Return the used genotype {@link Factory} of the GA. The genotype factory
1090                 * is used for creating the initial population and new, random individuals
1091                 * when needed (as replacement for invalid and/or died genotypes).
1092                 *
1093                 * @since 3.1
1094                 *
1095                 * @return the used genotype {@link Factory} of the GA.
1096                 */
1097                public Factory<Genotype<G>> genotypeFactory() {
1098                        return _genotypeFactory;
1099                }
1100
1101                /**
1102                 * Return the constraint of the evolution problem.
1103                 *
1104                 * @since 5.0
1105                 *
1106                 * @return the constraint of the evolution problem
1107                 */
1108                public Constraint<G, C> constraint() {
1109                        return _constraint;
1110                }
1111
1112                /**
1113                 * Return the currently set evolution parameters.
1114                 *
1115                 * @since 5.2
1116                 *
1117                 * @return the currently set evolution parameters
1118                 */
1119                public EvolutionParams<G, C> evolutionParams() {
1120                        return _evolutionParams.build();
1121                }
1122
1123                /**
1124                 * Return the maximal allowed phenotype age.
1125                 *
1126                 * @since 3.1
1127                 *
1128                 * @return the maximal allowed phenotype age
1129                 */
1130                public long maximalPhenotypeAge() {
1131                        return _evolutionParams.maximalPhenotypeAge();
1132                }
1133
1134                /**
1135                 * Return the offspring fraction.
1136                 *
1137                 * @return the offspring fraction.
1138                 */
1139                public double offspringFraction() {
1140                        return _evolutionParams.offspringFraction();
1141                }
1142
1143                /**
1144                 * Return the used offspring {@link Selector} of the GA.
1145                 *
1146                 * @since 3.1
1147                 *
1148                 * @return the used offspring {@link Selector} of the GA.
1149                 */
1150                public Selector<G, C> offspringSelector() {
1151                        return _evolutionParams.offspringSelector();
1152                }
1153
1154                /**
1155                 * Return the used survivor {@link Selector} of the GA.
1156                 *
1157                 * @since 3.1
1158                 *
1159                 * @return the used survivor {@link Selector} of the GA.
1160                 */
1161                public Selector<G, C> survivorsSelector() {
1162                        return _evolutionParams.survivorsSelector();
1163                }
1164
1165                /**
1166                 * Return the optimization strategy.
1167                 *
1168                 * @since 3.1
1169                 *
1170                 * @return the optimization strategy
1171                 */
1172                public Optimize optimize() {
1173                        return _optimize;
1174                }
1175
1176                /**
1177                 * Return the number of individuals of a population.
1178                 *
1179                 * @since 3.1
1180                 *
1181                 * @return the number of individuals of a population
1182                 */
1183                public int populationSize() {
1184                        return _evolutionParams.populationSize();
1185                }
1186
1187                /**
1188                 * Return the evolution interceptor.
1189                 *
1190                 * @since 6.0
1191                 *
1192                 * @return the evolution interceptor
1193                 */
1194                public EvolutionInterceptor<G, C> interceptor() {
1195                        return _interceptor;
1196                }
1197
1198                /**
1199                 * Create a new builder, with the current configuration.
1200                 *
1201                 * @since 3.1
1202                 *
1203                 * @return a new builder, with the current configuration
1204                 */
1205                @Override
1206                public Builder<G, C> copy() {
1207                        return new Builder<>(_evaluator, _genotypeFactory)
1208                                .clock(_clock)
1209                                .executor(_executor)
1210                                .constraint(_constraint)
1211                                .optimize(_optimize)
1212                                .evolutionParams(_evolutionParams.build())
1213                                .interceptor(_interceptor);
1214                }
1215
1216        }
1217
1218
1219        /* *************************************************************************
1220         * Engine setup
1221         **************************************************************************/
1222
1223
1224        /**
1225         * This interface represents a recipe for configuring (setup) a given
1226         * {@link Builder}. It is mainly used for grouping mutually dependent
1227         * engine configurations. The following code snippet shows a possible usage
1228         * example.
1229         *
1230         * <pre>{@code
1231         * final Engine<CharacterGene, Integer> engine = Engine.builder(problem)
1232         *     .setup(new WeaselProgram<>())
1233         *     .build();
1234         * }</pre>
1235         *
1236         * @see Builder#setup(Setup)
1237         *
1238         * @param <G> the gene type
1239         * @param <C> the fitness result type
1240         *
1241         * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
1242         * @version 6.0
1243         * @since 6.0
1244         */
1245        @FunctionalInterface
1246        public interface Setup<
1247                G extends Gene<?, G>,
1248                C extends Comparable<? super C>
1249        > {
1250
1251                /**
1252                 * Applies {@code this} setup to the given engine {@code builder}.
1253                 *
1254                 * @param builder the engine builder to set up (configure)
1255                 */
1256                void apply(final Builder<G, C> builder);
1257
1258        }
1259}
1260
1261
1262