001/*
002 * Java Genetic Algorithm Library (jenetics-6.0.0).
003 * Copyright (c) 2007-2020 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                return builder(problem.fitness(), problem.codec());
634        }
635
636        /**
637         * Create a new evolution {@code Engine.Builder} with the given fitness
638         * function and chromosome templates.
639         *
640         * @param ff the fitness function
641         * @param chromosome the first chromosome
642         * @param chromosomes the chromosome templates
643         * @param <G> the gene type
644         * @param <C> the fitness function result type
645         * @return a new engine builder
646         * @throws java.lang.NullPointerException if one of the arguments is
647         *         {@code null}.
648         */
649        @SafeVarargs
650        public static <G extends Gene<?, G>, C extends Comparable<? super C>>
651        Builder<G, C> builder(
652                final Function<? super Genotype<G>, ? extends C> ff,
653                final Chromosome<G> chromosome,
654                final Chromosome<G>... chromosomes
655        ) {
656                return builder(ff, Genotype.of(chromosome, chromosomes));
657        }
658
659
660        /* *************************************************************************
661         * Engine builder
662         **************************************************************************/
663
664
665        /**
666         * Builder class for building GA {@code Engine} instances.
667         *
668         * @see Engine
669         *
670         * @param <G> the gene type
671         * @param <C> the fitness function result type
672         *
673         * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
674         * @since 3.0
675         * @version 6.0
676         */
677        public static final class Builder<
678                G extends Gene<?, G>,
679                C extends Comparable<? super C>
680        >
681                implements Copyable<Builder<G, C>>
682        {
683
684                // No default values for this properties.
685                private final Evaluator<G, C> _evaluator;
686                private final Factory<Genotype<G>> _genotypeFactory;
687                private Constraint<G, C> _constraint;
688                private Optimize _optimize = Optimize.MAXIMUM;
689
690                // Evolution parameters.
691                private final EvolutionParams.Builder<G, C> _evolutionParams =
692                        EvolutionParams.builder();
693
694
695                // Engine execution environment.
696                private Executor _executor = commonPool();
697                private Clock _clock = NanoClock.systemUTC();
698
699                private EvolutionInterceptor<G, C> _interceptor =
700                        EvolutionInterceptor.identity();
701
702                /**
703                 * Create a new evolution {@code Engine.Builder} with the given fitness
704                 * evaluator and genotype factory. This is the most general way for
705                 * creating an engine builder.
706                 *
707                 * @since 5.0
708                 *
709                 * @see Engine#builder(Function, Codec)
710                 * @see Engine#builder(Function, Factory)
711                 * @see Engine#builder(Problem)
712                 * @see Engine#builder(Function, Chromosome, Chromosome[])
713                 *
714                 * @param evaluator the fitness evaluator
715                 * @param genotypeFactory the genotype factory
716                 * @throws NullPointerException if one of the arguments is {@code null}.
717                 */
718                public Builder(
719                        final Evaluator<G, C> evaluator,
720                        final Factory<Genotype<G>> genotypeFactory
721                ) {
722                        _genotypeFactory = requireNonNull(genotypeFactory);
723                        _evaluator = requireNonNull(evaluator);
724                }
725
726                /**
727                 * Applies the given {@code setup} recipe to {@code this} engine builder.
728                 *
729                 * @since 6.0
730                 *
731                 * @param setup the setup recipe applying to {@code this} builder
732                 * @return {@code this} builder, for command chaining
733                 * @throws NullPointerException if the {@code setup} is {@code null}.
734                 */
735                public Builder<G, C> setup(final Setup<G, C> setup) {
736                        setup.apply(this);
737                        return this;
738                }
739
740                /**
741                 * Set the evolution parameters used by the engine.
742                 *
743                 * @since 5.2
744                 *
745                 * @param params the evolution parameter
746                 * @return {@code this} builder, for command chaining
747                 * @throws NullPointerException if the {@code params} is {@code null}.
748                 */
749                public Builder<G, C> evolutionParams(final EvolutionParams<G, C> params) {
750                        _evolutionParams.evolutionParams(params);
751                        return this;
752                }
753
754                /**
755                 * The selector used for selecting the offspring population. <i>Default
756                 * values is set to {@code TournamentSelector<>(3)}.</i>
757                 *
758                 * @param selector used for selecting the offspring population
759                 * @return {@code this} builder, for command chaining
760                 * @throws NullPointerException if one of the {@code selector} is
761                 *         {@code null}.
762                 */
763                public Builder<G, C> offspringSelector(final Selector<G, C> selector) {
764                        _evolutionParams.offspringSelector(selector);
765                        return this;
766                }
767
768                /**
769                 * The selector used for selecting the survivors population. <i>Default
770                 * values is set to {@code TournamentSelector<>(3)}.</i>
771                 *
772                 * @param selector used for selecting survivors population
773                 * @return {@code this} builder, for command chaining
774                 * @throws NullPointerException if one of the {@code selector} is
775                 *         {@code null}.
776                 */
777                public Builder<G, C> survivorsSelector(final Selector<G, C> selector) {
778                        _evolutionParams.survivorsSelector(selector);
779                        return this;
780                }
781
782                /**
783                 * The selector used for selecting the survivors and offspring
784                 * population. <i>Default values is set to
785                 * {@code TournamentSelector<>(3)}.</i>
786                 *
787                 * @param selector used for selecting survivors and offspring population
788                 * @return {@code this} builder, for command chaining
789                 * @throws NullPointerException if one of the {@code selector} is
790                 *         {@code null}.
791                 */
792                public Builder<G, C> selector(final Selector<G, C> selector) {
793                        _evolutionParams.selector(selector);
794                        return this;
795                }
796
797                /**
798                 * The alterers used for alter the offspring population. <i>Default
799                 * values is set to {@code new SinglePointCrossover<>(0.2)} followed by
800                 * {@code new Mutator<>(0.15)}.</i>
801                 *
802                 * @param first the first alterer used for alter the offspring
803                 *        population
804                 * @param rest the rest of the alterers used for alter the offspring
805                 *        population
806                 * @return {@code this} builder, for command chaining
807                 * @throws NullPointerException if one of the alterers is {@code null}.
808                 */
809                @SafeVarargs
810                public final Builder<G, C> alterers(
811                        final Alterer<G, C> first,
812                        final Alterer<G, C>... rest
813                ) {
814                        _evolutionParams.alterers(first, rest);
815                        return this;
816                }
817
818                /**
819                 * The phenotype constraint is used for detecting invalid individuals
820                 * and repairing them.
821                 *
822                 * <p><i>Default implementation uses {@code Phenotype::isValid} for
823                 * validating the phenotype.</i></p>
824                 *
825                 * @since 5.0
826                 *
827                 * @param constraint phenotype constraint which can override the default
828                 *        implementation the {@link Phenotype#isValid()} method and repairs
829                 *        invalid phenotypes when needed.
830                 * @return {@code this} builder, for command chaining
831                 * @throws NullPointerException if one of the {@code constraint} is
832                 *         {@code null}.
833                 */
834                public Builder<G, C> constraint(final Constraint<G, C> constraint) {
835                        _constraint = constraint;
836                        return this;
837                }
838
839                /**
840                 * The optimization strategy used by the engine. <i>Default values is
841                 * set to {@code Optimize.MAXIMUM}.</i>
842                 *
843                 * @param optimize the optimization strategy used by the engine
844                 * @return {@code this} builder, for command chaining
845                 * @throws NullPointerException if one of the {@code optimize} is
846                 *         {@code null}.
847                 */
848                public Builder<G, C> optimize(final Optimize optimize) {
849                        _optimize = requireNonNull(optimize);
850                        return this;
851                }
852
853                /**
854                 * Set to a fitness maximizing strategy.
855                 *
856                 * @since 3.4
857                 *
858                 * @return {@code this} builder, for command chaining
859                 */
860                public Builder<G, C> maximizing() {
861                        return optimize(Optimize.MAXIMUM);
862                }
863
864                /**
865                 * Set to a fitness minimizing strategy.
866                 *
867                 * @since 3.4
868                 *
869                 * @return {@code this} builder, for command chaining
870                 */
871                public Builder<G, C> minimizing() {
872                        return optimize(Optimize.MINIMUM);
873                }
874
875                /**
876                 * The offspring fraction. <i>Default values is set to {@code 0.6}.</i>
877                 * This method call is equivalent to
878                 * {@code survivorsFraction(1 - offspringFraction)} and will override
879                 * any previously set survivors-fraction.
880                 *
881                 * @see #survivorsFraction(double)
882                 *
883                 * @param fraction the offspring fraction
884                 * @return {@code this} builder, for command chaining
885                 * @throws java.lang.IllegalArgumentException if the fraction is not
886                 *         within the range [0, 1].
887                 */
888                public Builder<G, C> offspringFraction(final double fraction) {
889                        _evolutionParams.offspringFraction(fraction);
890                        return this;
891                }
892
893                /**
894                 * The survivors fraction. <i>Default values is set to {@code 0.4}.</i>
895                 * This method call is equivalent to
896                 * {@code offspringFraction(1 - survivorsFraction)} and will override
897                 * any previously set offspring-fraction.
898                 *
899                 * @since 3.8
900                 *
901                 * @see #offspringFraction(double)
902                 *
903                 * @param fraction the survivors fraction
904                 * @return {@code this} builder, for command chaining
905                 * @throws java.lang.IllegalArgumentException if the fraction is not
906                 *         within the range [0, 1].
907                 */
908                public Builder<G, C> survivorsFraction(final double fraction) {
909                        return offspringFraction(1 - fraction);
910                }
911
912                /**
913                 * The number of offspring individuals.
914                 *
915                 * @since 3.8
916                 *
917                 * @param size the number of offspring individuals.
918                 * @return {@code this} builder, for command chaining
919                 * @throws java.lang.IllegalArgumentException if the size is not
920                 *         within the range [0, population-size].
921                 */
922                public Builder<G, C> offspringSize(final int size) {
923                        if (size < 0) {
924                                throw new IllegalArgumentException(format(
925                                        "Offspring size must be greater or equal zero, but was %s.",
926                                        size
927                                ));
928                        }
929
930                        return offspringFraction(size/(double)_evolutionParams.populationSize());
931                }
932
933                /**
934                 * The number of survivors.
935                 *
936                 * @since 3.8
937                 *
938                 * @param size the number of survivors.
939                 * @return {@code this} builder, for command chaining
940                 * @throws java.lang.IllegalArgumentException if the size is not
941                 *         within the range [0, population-size].
942                 */
943                public Builder<G, C> survivorsSize(final int size) {
944                        if (size < 0) {
945                                throw new IllegalArgumentException(format(
946                                        "Survivors must be greater or equal zero, but was %s.",
947                                        size
948                                ));
949                        }
950
951                        return survivorsFraction(size/(double)_evolutionParams.populationSize());
952                }
953
954                /**
955                 * The number of individuals which form the population. <i>Default
956                 * values is set to {@code 50}.</i>
957                 *
958                 * @param size the number of individuals of a population
959                 * @return {@code this} builder, for command chaining
960                 * @throws java.lang.IllegalArgumentException if {@code size < 1}
961                 */
962                public Builder<G, C> populationSize(final int size) {
963                        _evolutionParams.populationSize(size);
964                        return this;
965                }
966
967                /**
968                 * The maximal allowed age of a phenotype. <i>Default values is set to
969                 * {@code 70}.</i>
970                 *
971                 * @param age the maximal phenotype age
972                 * @return {@code this} builder, for command chaining
973                 * @throws java.lang.IllegalArgumentException if {@code age < 1}
974                 */
975                public Builder<G, C> maximalPhenotypeAge(final long age) {
976                        _evolutionParams.maximalPhenotypeAge(age);
977                        return this;
978                }
979
980                /**
981                 * The executor used by the engine.
982                 *
983                 * @param executor the executor used by the engine
984                 * @return {@code this} builder, for command chaining
985                 */
986                public Builder<G, C> executor(final Executor executor) {
987                        _executor = requireNonNull(executor);
988                        return this;
989                }
990
991                /**
992                 * The clock used for calculating the execution durations.
993                 *
994                 * @param clock the clock used for calculating the execution durations
995                 * @return {@code this} builder, for command chaining
996                 */
997                public Builder<G, C> clock(final Clock clock) {
998                        _clock = requireNonNull(clock);
999                        return this;
1000                }
1001
1002                /**
1003                 * The evolution interceptor, which allows to change the evolution start
1004                 * and result.
1005                 *
1006                 * @since 6.0
1007                 * @see EvolutionResult#toUniquePopulation()
1008                 *
1009                 * @param interceptor the evolution interceptor
1010                 * @return {@code this} builder, for command chaining
1011                 * @throws NullPointerException if the given {@code interceptor} is
1012                 *         {@code null}
1013                 */
1014                public Builder<G, C>
1015                interceptor(final EvolutionInterceptor<G, C> interceptor) {
1016                        _interceptor = requireNonNull(interceptor);
1017                        return this;
1018                }
1019
1020                /**
1021                 * Builds an new {@code Engine} instance from the set properties.
1022                 *
1023                 * @return an new {@code Engine} instance from the set properties
1024                 */
1025                public Engine<G, C> build() {
1026                        return new Engine<>(
1027                                __evaluator(),
1028                                _genotypeFactory,
1029                                __constraint(),
1030                                _optimize,
1031                                _evolutionParams.build(),
1032                                _executor,
1033                                _clock,
1034                                _interceptor
1035                        );
1036                }
1037
1038                private Evaluator<G, C> __evaluator() {
1039                        return _evaluator instanceof ConcurrentEvaluator
1040                                ? ((ConcurrentEvaluator<G, C>)_evaluator).with(_executor)
1041                                : _evaluator;
1042                }
1043
1044                private Constraint<G, C> __constraint() {
1045                        return _constraint == null
1046                                ? RetryConstraint.of(_genotypeFactory)
1047                                : _constraint;
1048                }
1049
1050                /* *********************************************************************
1051                 * Current properties
1052                 ***********************************************************************/
1053
1054                /**
1055                 * Return the used {@link Alterer} of the GA.
1056                 *
1057                 * @return the used {@link Alterer} of the GA.
1058                 */
1059                public Alterer<G, C> alterer() {
1060                        return _evolutionParams.alterer();
1061                }
1062
1063                /**
1064                 * Return the {@link Clock} the engine is using for measuring the execution
1065                 * time.
1066                 *
1067                 * @since 3.1
1068                 *
1069                 * @return the clock used for measuring the execution time
1070                 */
1071                public Clock clock() {
1072                        return _clock;
1073                }
1074
1075                /**
1076                 * Return the {@link Executor} the engine is using for executing the
1077                 * evolution steps.
1078                 *
1079                 * @since 3.1
1080                 *
1081                 * @return the executor used for performing the evolution steps
1082                 */
1083                public Executor executor() {
1084                        return _executor;
1085                }
1086
1087                /**
1088                 * Return the used genotype {@link Factory} of the GA. The genotype factory
1089                 * is used for creating the initial population and new, random individuals
1090                 * when needed (as replacement for invalid and/or died genotypes).
1091                 *
1092                 * @since 3.1
1093                 *
1094                 * @return the used genotype {@link Factory} of the GA.
1095                 */
1096                public Factory<Genotype<G>> genotypeFactory() {
1097                        return _genotypeFactory;
1098                }
1099
1100                /**
1101                 * Return the constraint of the evolution problem.
1102                 *
1103                 * @since 5.0
1104                 *
1105                 * @return the constraint of the evolution problem
1106                 */
1107                public Constraint<G, C> constraint() {
1108                        return _constraint;
1109                }
1110
1111                /**
1112                 * Return the currently set evolution parameters.
1113                 *
1114                 * @since 5.2
1115                 *
1116                 * @return the currently set evolution parameters
1117                 */
1118                public EvolutionParams<G, C> evolutionParams() {
1119                        return _evolutionParams.build();
1120                }
1121
1122                /**
1123                 * Return the maximal allowed phenotype age.
1124                 *
1125                 * @since 3.1
1126                 *
1127                 * @return the maximal allowed phenotype age
1128                 */
1129                public long maximalPhenotypeAge() {
1130                        return _evolutionParams.maximalPhenotypeAge();
1131                }
1132
1133                /**
1134                 * Return the offspring fraction.
1135                 *
1136                 * @return the offspring fraction.
1137                 */
1138                public double offspringFraction() {
1139                        return _evolutionParams.offspringFraction();
1140                }
1141
1142                /**
1143                 * Return the used offspring {@link Selector} of the GA.
1144                 *
1145                 * @since 3.1
1146                 *
1147                 * @return the used offspring {@link Selector} of the GA.
1148                 */
1149                public Selector<G, C> offspringSelector() {
1150                        return _evolutionParams.offspringSelector();
1151                }
1152
1153                /**
1154                 * Return the used survivor {@link Selector} of the GA.
1155                 *
1156                 * @since 3.1
1157                 *
1158                 * @return the used survivor {@link Selector} of the GA.
1159                 */
1160                public Selector<G, C> survivorsSelector() {
1161                        return _evolutionParams.survivorsSelector();
1162                }
1163
1164                /**
1165                 * Return the optimization strategy.
1166                 *
1167                 * @since 3.1
1168                 *
1169                 * @return the optimization strategy
1170                 */
1171                public Optimize optimize() {
1172                        return _optimize;
1173                }
1174
1175                /**
1176                 * Return the number of individuals of a population.
1177                 *
1178                 * @since 3.1
1179                 *
1180                 * @return the number of individuals of a population
1181                 */
1182                public int populationSize() {
1183                        return _evolutionParams.populationSize();
1184                }
1185
1186                /**
1187                 * Return the evolution interceptor.
1188                 *
1189                 * @since 6.0
1190                 *
1191                 * @return the evolution interceptor
1192                 */
1193                public EvolutionInterceptor<G, C> interceptor() {
1194                        return _interceptor;
1195                }
1196
1197                /**
1198                 * Create a new builder, with the current configuration.
1199                 *
1200                 * @since 3.1
1201                 *
1202                 * @return a new builder, with the current configuration
1203                 */
1204                @Override
1205                public Builder<G, C> copy() {
1206                        return new Builder<>(_evaluator, _genotypeFactory)
1207                                .clock(_clock)
1208                                .executor(_executor)
1209                                .constraint(_constraint)
1210                                .optimize(_optimize)
1211                                .evolutionParams(_evolutionParams.build())
1212                                .interceptor(_interceptor);
1213                }
1214
1215        }
1216
1217
1218        /* *************************************************************************
1219         * Engine setup
1220         **************************************************************************/
1221
1222
1223        /**
1224         * This interface represents a recipe for configuring (setup) a given
1225         * {@link Builder}. It is mainly used for grouping mutually dependent
1226         * engine configurations. The following code snippet shows a possible usage
1227         * example.
1228         *
1229         * <pre>{@code
1230         * final Engine<CharacterGene, Integer> engine = Engine.builder(problem)
1231         *     .setup(new WeaselProgram<>())
1232         *     .build();
1233         * }</pre>
1234         *
1235         * @see Builder#setup(Setup)
1236         *
1237         * @param <G> the gene type
1238         * @param <C> the fitness result type
1239         *
1240         * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
1241         * @version 6.0
1242         * @since 6.0
1243         */
1244        @FunctionalInterface
1245        public static interface Setup<
1246                G extends Gene<?, G>,
1247                C extends Comparable<? super C>
1248        > {
1249
1250                /**
1251                 * Applies {@code this} setup to the given engine {@code builder}.
1252                 *
1253                 * @param builder the engine builder to setup (configure)
1254                 */
1255                void apply(final Builder<G, C> builder);
1256
1257        }
1258}
1259
1260
1261