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