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