Engine.java
0001 /*
0002  * Java Genetic Algorithm Library (jenetics-6.3.0).
0003  * Copyright (c) 2007-2021 Franz Wilhelmstötter
0004  *
0005  * Licensed under the Apache License, Version 2.0 (the "License");
0006  * you may not use this file except in compliance with the License.
0007  * You may obtain a copy of the License at
0008  *
0009  *      http://www.apache.org/licenses/LICENSE-2.0
0010  *
0011  * Unless required by applicable law or agreed to in writing, software
0012  * distributed under the License is distributed on an "AS IS" BASIS,
0013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014  * See the License for the specific language governing permissions and
0015  * limitations under the License.
0016  *
0017  * Author:
0018  *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
0019  */
0020 package io.jenetics.engine;
0021 
0022 import static java.lang.String.format;
0023 import static java.util.Objects.requireNonNull;
0024 import static java.util.concurrent.CompletableFuture.supplyAsync;
0025 import static java.util.concurrent.ForkJoinPool.commonPool;
0026 
0027 import java.time.Clock;
0028 import java.util.concurrent.CompletableFuture;
0029 import java.util.concurrent.Executor;
0030 import java.util.function.Function;
0031 import java.util.function.Supplier;
0032 import java.util.stream.Stream;
0033 
0034 import io.jenetics.Alterer;
0035 import io.jenetics.AltererResult;
0036 import io.jenetics.Chromosome;
0037 import io.jenetics.Gene;
0038 import io.jenetics.Genotype;
0039 import io.jenetics.Optimize;
0040 import io.jenetics.Phenotype;
0041 import io.jenetics.Selector;
0042 import io.jenetics.util.Copyable;
0043 import io.jenetics.util.Factory;
0044 import io.jenetics.util.ISeq;
0045 import io.jenetics.util.MSeq;
0046 import io.jenetics.util.NanoClock;
0047 import io.jenetics.util.Seq;
0048 
0049 /**
0050  * Genetic algorithm <em>engine</em> which is the main class. The following
0051  * example shows the main steps in initializing and executing the GA.
0052  *
0053  <pre>{@code
0054  * public class RealFunction {
0055  *    // Definition of the fitness function.
0056  *    private static Double eval(final Genotype<DoubleGene> gt) {
0057  *        final double x = gt.gene().doubleValue();
0058  *        return cos(0.5 + sin(x))*cos(x);
0059  *    }
0060  *
0061  *    public static void main(String[] args) {
0062  *        // Create/configuring the engine via its builder.
0063  *        final Engine<DoubleGene, Double> engine = Engine
0064  *            .builder(
0065  *                RealFunction::eval,
0066  *                DoubleChromosome.of(0.0, 2.0*PI))
0067  *            .populationSize(500)
0068  *            .optimize(Optimize.MINIMUM)
0069  *            .alterers(
0070  *                new Mutator<>(0.03),
0071  *                new MeanAlterer<>(0.6))
0072  *            .build();
0073  *
0074  *        // Execute the GA (engine).
0075  *        final Phenotype<DoubleGene, Double> result = engine.stream()
0076  *             // Truncate the evolution stream if no better individual could
0077  *             // be found after 5 consecutive generations.
0078  *            .limit(bySteadyFitness(5))
0079  *             // Terminate the evolution after maximal 100 generations.
0080  *            .limit(100)
0081  *            .collect(toBestPhenotype());
0082  *     }
0083  * }
0084  * }</pre>
0085  *
0086  * The architecture allows to decouple the configuration of the engine from the
0087  * execution. The {@code Engine} is configured via the {@code Engine.Builder}
0088  * class and can't be changed after creation. The actual <i>evolution</i> is
0089  * performed by the {@link EvolutionStream}, which is created by the
0090  * {@code Engine}.
0091  *
0092  * @implNote
0093  *     This class is thread safe:
0094  *     No mutable state is maintained by the engine. Therefore it is save to
0095  *     create multiple evolution streams with one engine, which may be actually
0096  *     used in different threads.
0097  *
0098  @see Engine.Builder
0099  @see EvolutionStart
0100  @see EvolutionResult
0101  @see EvolutionStream
0102  @see EvolutionStatistics
0103  @see Codec
0104  @see Constraint
0105  *
0106  @param <G> the gene type
0107  @param <C> the fitness result type
0108  *
0109  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
0110  @since 3.0
0111  @version 6.0
0112  */
0113 public final class Engine<
0114     extends Gene<?, G>,
0115     extends Comparable<? super C>
0116 >
0117     implements
0118         Evolution<G, C>,
0119         EvolutionStreamable<G, C>,
0120         Evaluator<G, C>
0121 {
0122 
0123     // Problem definition.
0124     private final Evaluator<G, C> _evaluator;
0125     private final Factory<Genotype<G>> _genotypeFactory;
0126     private final Constraint<G, C> _constraint;
0127     private final Optimize _optimize;
0128 
0129     // Evolution parameters.
0130     private final EvolutionParams<G, C> _evolutionParams;
0131 
0132     // Execution context for concurrent execution of evolving steps.
0133     private final Executor _executor;
0134     private final Clock _clock;
0135     private final EvolutionInterceptor<G, C> _interceptor;
0136 
0137 
0138     /**
0139      * Create a new GA engine with the given parameters.
0140      *
0141      @param evaluator the population fitness evaluator
0142      @param genotypeFactory the genotype factory this GA is working with.
0143      @param constraint phenotype constraint which can override the default
0144      *        implementation the {@link Phenotype#isValid()} method and repairs
0145      *        invalid phenotypes when needed.
0146      @param optimize the kind of optimization (minimize or maximize)
0147      @param evolutionParams the evolution parameters, which influences the
0148      *        evolution process
0149      @param executor the executor used for executing the single evolve steps
0150      @param clock the clock used for calculating the timing results
0151      @param interceptor the evolution interceptor, which gives additional
0152      *        possibilities to influence the actual evolution
0153      @throws NullPointerException if one of the arguments is {@code null}
0154      @throws IllegalArgumentException if the given integer values are smaller
0155      *         than one.
0156      */
0157     Engine(
0158         final Evaluator<G, C> evaluator,
0159         final Factory<Genotype<G>> genotypeFactory,
0160         final Constraint<G, C> constraint,
0161         final Optimize optimize,
0162         final EvolutionParams<G, C> evolutionParams,
0163         final Executor executor,
0164         final Clock clock,
0165         final EvolutionInterceptor<G, C> interceptor
0166     ) {
0167         _evaluator = requireNonNull(evaluator);
0168         _genotypeFactory = requireNonNull(genotypeFactory);
0169         _constraint = requireNonNull(constraint);
0170         _optimize = requireNonNull(optimize);
0171         _evolutionParams = requireNonNull(evolutionParams);
0172         _executor = requireNonNull(executor);
0173         _clock = requireNonNull(clock);
0174         _interceptor = requireNonNull(interceptor);
0175     }
0176 
0177     @Override
0178     public EvolutionResult<G, C> evolve(final EvolutionStart<G, C> start) {
0179         final EvolutionTiming timing = new EvolutionTiming(_clock);
0180         timing.evolve.start();
0181 
0182         final EvolutionStart<G, C> interceptedStart = _interceptor.before(start);
0183 
0184         // Create initial population if `start` is empty.
0185         final EvolutionStart<G, C> es = interceptedStart.population().isEmpty()
0186             ? evolutionStart(interceptedStart)
0187             : interceptedStart;
0188 
0189         // Initial evaluation of the population.
0190         final ISeq<Phenotype<G, C>> population = es.isDirty()
0191             ? timing.evaluation.timing(() -> eval(es.population()))
0192             : es.population();
0193 
0194         // Select the offspring population.
0195         final CompletableFuture<ISeq<Phenotype<G, C>>> offspring =
0196             supplyAsync(() ->
0197                 timing.offspringSelection.timing(() ->
0198                     selectOffspring(population)
0199                 ),
0200                 _executor
0201             );
0202 
0203         // Select the survivor population.
0204         final CompletableFuture<ISeq<Phenotype<G, C>>> survivors =
0205             supplyAsync(() ->
0206                 timing.survivorsSelection.timing(() ->
0207                     selectSurvivors(population)
0208                 ),
0209                 _executor
0210             );
0211 
0212         // Altering the offspring population.
0213         final CompletableFuture<AltererResult<G, C>> alteredOffspring =
0214             offspring.thenApplyAsync(off ->
0215                 timing.offspringAlter.timing(() ->
0216                     _evolutionParams.alterer().alter(off, es.generation())
0217                 ),
0218                 _executor
0219             );
0220 
0221         // Filter and replace invalid and old survivor individuals.
0222         final CompletableFuture<FilterResult<G, C>> filteredSurvivors =
0223             survivors.thenApplyAsync(sur ->
0224                 timing.survivorFilter.timing(() ->
0225                     filter(sur, es.generation())
0226                 ),
0227                 _executor
0228             );
0229 
0230         // Filter and replace invalid and old offspring individuals.
0231         final CompletableFuture<FilterResult<G, C>> filteredOffspring =
0232             alteredOffspring.thenApplyAsync(off ->
0233                 timing.offspringFilter.timing(() ->
0234                     filter(off.population(), es.generation())
0235                 ),
0236                 _executor
0237             );
0238 
0239         // Combining survivors and offspring to the new population.
0240         final CompletableFuture<ISeq<Phenotype<G, C>>> nextPopulation =
0241             filteredSurvivors.thenCombineAsync(
0242                 filteredOffspring,
0243                 (s, o-> ISeq.of(s.population.append(o.population)),
0244                 _executor
0245             );
0246 
0247         // Evaluate the fitness-function and wait for result.
0248         final ISeq<Phenotype<G, C>> pop = nextPopulation.join();
0249         final ISeq<Phenotype<G, C>> result = timing.evaluation.timing(() ->
0250             eval(pop)
0251         );
0252 
0253         final int killCount =
0254             filteredOffspring.join().killCount +
0255             filteredSurvivors.join().killCount;
0256 
0257         final int invalidCount =
0258             filteredOffspring.join().invalidCount +
0259             filteredSurvivors.join().invalidCount;
0260 
0261         final int alterationCount = alteredOffspring.join().alterations();
0262 
0263         EvolutionResult<G, C> er = EvolutionResult.of(
0264             _optimize,
0265             result,
0266             es.generation(),
0267             timing.toDurations(),
0268             killCount,
0269             invalidCount,
0270             alterationCount
0271         );
0272 
0273         final EvolutionResult<G, C> interceptedResult = _interceptor.after(er);
0274         if (er != interceptedResult) {
0275             er = interceptedResult.withPopulation(
0276                 timing.evaluation.timing(() ->
0277                     eval(interceptedResult.population())
0278             ));
0279         }
0280 
0281         timing.evolve.stop();
0282 
0283         return er
0284             .withDurations(timing.toDurations())
0285             .clean();
0286     }
0287 
0288     // Selects the survivors population. A new population object is returned.
0289     private ISeq<Phenotype<G, C>>
0290     selectSurvivors(final ISeq<Phenotype<G, C>> population) {
0291         return _evolutionParams.survivorsSize() 0
0292             ? _evolutionParams.survivorsSelector()
0293                 .select(population, _evolutionParams.survivorsSize(), _optimize)
0294             : ISeq.empty();
0295     }
0296 
0297     // Selects the offspring population. A new population object is returned.
0298     private ISeq<Phenotype<G, C>>
0299     selectOffspring(final ISeq<Phenotype<G, C>> population) {
0300         return _evolutionParams.offspringSize() 0
0301             ? _evolutionParams.offspringSelector()
0302                 .select(population, _evolutionParams.offspringSize(), _optimize)
0303             : ISeq.empty();
0304     }
0305 
0306     // Filters out invalid and old individuals. Filtering is done in place.
0307     private FilterResult<G, C> filter(
0308         final Seq<Phenotype<G, C>> population,
0309         final long generation
0310     ) {
0311         int killCount = 0;
0312         int invalidCount = 0;
0313 
0314         final MSeq<Phenotype<G, C>> pop = MSeq.of(population);
0315         for (int i = 0, n = pop.size(); i < n; ++i) {
0316             final Phenotype<G, C> individual = pop.get(i);
0317 
0318             if (!_constraint.test(individual)) {
0319                 pop.set(i, _constraint.repair(individual, generation));
0320                 ++invalidCount;
0321             else if (individual.age(generation>
0322                         _evolutionParams.maximalPhenotypeAge())
0323             {
0324                 pop.set(i, Phenotype.of(_genotypeFactory.newInstance(), generation));
0325                 ++killCount;
0326             }
0327         }
0328 
0329         return new FilterResult<>(pop.toISeq(), killCount, invalidCount);
0330     }
0331 
0332 
0333     /* *************************************************************************
0334      * Evaluation methods.
0335      **************************************************************************/
0336 
0337     /**
0338      * Evaluates the fitness function of the given population with the configured
0339      {@link Evaluator} of this engine and returns a new population
0340      * with its fitness value assigned.
0341      *
0342      @since 5.0
0343      *
0344      @see Evaluator
0345      @see Evaluator#eval(Seq)
0346      *
0347      @param population the population to evaluate
0348      @return a new population with assigned fitness values
0349      @throws IllegalStateException if the configured fitness function doesn't
0350      *         return a population with the same size as the input population.
0351      *         This exception is also thrown if one of the populations
0352      *         phenotype has no fitness value assigned.
0353      */
0354     @Override
0355     public ISeq<Phenotype<G, C>> eval(final Seq<Phenotype<G, C>> population) {
0356         final ISeq<Phenotype<G, C>> evaluated = _evaluator.eval(population);
0357 
0358         if (population.size() != evaluated.size()) {
0359             throw new IllegalStateException(format(
0360                 "Expected %d individuals, but got %d. " +
0361                     "Check your evaluator function.",
0362                 population.size(), evaluated.size()
0363             ));
0364         }
0365         if (!evaluated.forAll(Phenotype::isEvaluated)) {
0366             throw new IllegalStateException(
0367                 "Some phenotypes have no assigned fitness value. " +
0368                     "Check your evaluator function."
0369             );
0370         }
0371 
0372         return evaluated;
0373     }
0374 
0375 
0376     /* *************************************************************************
0377      * Evolution Stream creation.
0378      **************************************************************************/
0379 
0380     @Override
0381     public EvolutionStream<G, C>
0382     stream(final Supplier<EvolutionStart<G, C>> start) {
0383         return EvolutionStream.ofEvolution(
0384             () -> evolutionStart(start.get()),
0385             this
0386         );
0387     }
0388 
0389     @Override
0390     public EvolutionStream<G, C> stream(final EvolutionInit<G> init) {
0391         return stream(evolutionStart(init));
0392     }
0393 
0394     private EvolutionStart<G, C>
0395     evolutionStart(final EvolutionStart<G, C> start) {
0396         final ISeq<Phenotype<G, C>> population = start.population();
0397         final long gen = start.generation();
0398 
0399         final Stream<Phenotype<G, C>> stream = Stream.concat(
0400             population.stream(),
0401             _genotypeFactory.instances()
0402                 .map(gt -> Phenotype.of(gt, gen))
0403         );
0404 
0405         final ISeq<Phenotype<G, C>> pop = stream
0406             .limit(populationSize())
0407             .collect(ISeq.toISeq());
0408 
0409         return EvolutionStart.of(pop, gen);
0410     }
0411 
0412     private EvolutionStart<G, C>
0413     evolutionStart(final EvolutionInit<G> init) {
0414         final ISeq<Genotype<G>> pop = init.population();
0415         final long gen = init.generation();
0416 
0417         return evolutionStart(
0418             EvolutionStart.of(
0419                 pop.map(gt -> Phenotype.of(gt, gen)),
0420                 gen
0421             )
0422         );
0423     }
0424 
0425     /* *************************************************************************
0426      * Property access methods.
0427      **************************************************************************/
0428 
0429     /**
0430      * Return the used genotype {@link Factory} of the GA. The genotype factory
0431      * is used for creating the initial population and new, random individuals
0432      * when needed (as replacement for invalid and/or died genotypes).
0433      *
0434      @return the used genotype {@link Factory} of the GA.
0435      */
0436     public Factory<Genotype<G>> genotypeFactory() {
0437         return _genotypeFactory;
0438     }
0439 
0440     /**
0441      * Return the constraint of the evolution problem.
0442      *
0443      @since 5.0
0444      *
0445      @return the constraint of the evolution problem
0446      */
0447     public Constraint<G, C> constraint() {
0448         return _constraint;
0449     }
0450 
0451     /**
0452      * Return the used survivor {@link Selector} of the GA.
0453      *
0454      @return the used survivor {@link Selector} of the GA.
0455      */
0456     public Selector<G, C> survivorsSelector() {
0457         return _evolutionParams.survivorsSelector();
0458     }
0459 
0460     /**
0461      * Return the used offspring {@link Selector} of the GA.
0462      *
0463      @return the used offspring {@link Selector} of the GA.
0464      */
0465     public Selector<G, C> offspringSelector() {
0466         return _evolutionParams.offspringSelector();
0467     }
0468 
0469     /**
0470      * Return the used {@link Alterer} of the GA.
0471      *
0472      @return the used {@link Alterer} of the GA.
0473      */
0474     public Alterer<G, C> alterer() {
0475         return _evolutionParams.alterer();
0476     }
0477 
0478     /**
0479      * Return the number of selected offspring.
0480      *
0481      @return the number of selected offspring
0482      */
0483     public int offspringSize() {
0484         return _evolutionParams.offspringSize();
0485     }
0486 
0487     /**
0488      * The number of selected survivors.
0489      *
0490      @return the number of selected survivors
0491      */
0492     public int survivorsSize() {
0493         return _evolutionParams.survivorsSize();
0494     }
0495 
0496     /**
0497      * Return the number of individuals of a population.
0498      *
0499      @return the number of individuals of a population
0500      */
0501     public int populationSize() {
0502         return _evolutionParams.populationSize();
0503     }
0504 
0505     /**
0506      * Return the maximal allowed phenotype age.
0507      *
0508      @return the maximal allowed phenotype age
0509      */
0510     public long maximalPhenotypeAge() {
0511         return _evolutionParams.maximalPhenotypeAge();
0512     }
0513 
0514     /**
0515      * Return the optimization strategy.
0516      *
0517      @return the optimization strategy
0518      */
0519     public Optimize optimize() {
0520         return _optimize;
0521     }
0522 
0523     /**
0524      * Return the {@link Clock} the engine is using for measuring the execution
0525      * time.
0526      *
0527      @return the clock used for measuring the execution time
0528      */
0529     public Clock clock() {
0530         return _clock;
0531     }
0532 
0533     /**
0534      * Return the {@link Executor} the engine is using for executing the
0535      * evolution steps.
0536      *
0537      @return the executor used for performing the evolution steps
0538      */
0539     public Executor executor() {
0540         return _executor;
0541     }
0542 
0543     /**
0544      * Return the evolution interceptor.
0545      *
0546      @since 6.0
0547      *
0548      @return the evolution result mapper
0549      */
0550     public EvolutionInterceptor<G, C> interceptor() {
0551         return _interceptor;
0552     }
0553 
0554     /**
0555      * Create a new evolution {@code Engine.Builder} initialized with the values
0556      * of the current evolution {@code Engine}. With this method, the evolution
0557      * engine can serve as a template for a new one.
0558      *
0559      @return a new engine builder
0560      */
0561     public Builder<G, C> toBuilder() {
0562         return new Builder<>(_evaluator, _genotypeFactory)
0563             .clock(_clock)
0564             .executor(_executor)
0565             .optimize(_optimize)
0566             .constraint(_constraint)
0567             .evolutionParams(_evolutionParams)
0568             .interceptor(_interceptor);
0569     }
0570 
0571 
0572     /* *************************************************************************
0573      * Static Builder methods.
0574      **************************************************************************/
0575 
0576     /**
0577      * Create a new evolution {@code Engine.Builder} with the given fitness
0578      * function and genotype factory.
0579      *
0580      @param ff the fitness function
0581      @param gtf the genotype factory
0582      @param <G> the gene type
0583      @param <C> the fitness function result type
0584      @return a new engine builder
0585      @throws java.lang.NullPointerException if one of the arguments is
0586      *         {@code null}.
0587      */
0588     public static <G extends Gene<?, G>, C extends Comparable<? super C>>
0589     Builder<G, C> builder(
0590         final Function<? super Genotype<G>, ? extends C> ff,
0591         final Factory<Genotype<G>> gtf
0592     ) {
0593         return new Builder<>(Evaluators.concurrent(ff, commonPool()), gtf);
0594     }
0595 
0596     /**
0597      * Create a new evolution {@code Engine.Builder} with the given fitness
0598      * function and problem {@code codec}.
0599      *
0600      @since 3.2
0601      *
0602      @param ff the fitness evaluator
0603      @param codec the problem codec
0604      @param <T> the fitness function input type
0605      @param <C> the fitness function result type
0606      @param <G> the gene type
0607      @return a new engine builder
0608      @throws java.lang.NullPointerException if one of the arguments is
0609      *         {@code null}.
0610      */
0611     public static <T, G extends Gene<?, G>, C extends Comparable<? super C>>
0612     Builder<G, C> builder(
0613         final Function<? super T, ? extends C> ff,
0614         final Codec<T, G> codec
0615     ) {
0616         return builder(ff.compose(codec.decoder()), codec.encoding());
0617     }
0618 
0619     /**
0620      * Create a new evolution {@code Engine.Builder} for the given
0621      {@link Problem}.
0622      *
0623      @since 3.4
0624      *
0625      @param problem the problem to be solved by the evolution {@code Engine}
0626      @param <T> the (<i>native</i>) argument type of the problem fitness function
0627      @param <G> the gene type the evolution engine is working with
0628      @param <C> the result type of the fitness function
0629      @return Create a new evolution {@code Engine.Builder}
0630      */
0631     public static <T, G extends Gene<?, G>, C extends Comparable<? super C>>
0632     Builder<G, C> builder(final Problem<T, G, C> problem) {
0633         final var builder = builder(problem.fitness(), problem.codec());
0634         problem.constraint().ifPresent(builder::constraint);
0635         return builder;
0636     }
0637 
0638     /**
0639      * Create a new evolution {@code Engine.Builder} with the given fitness
0640      * function and chromosome templates.
0641      *
0642      @param ff the fitness function
0643      @param chromosome the first chromosome
0644      @param chromosomes the chromosome templates
0645      @param <G> the gene type
0646      @param <C> the fitness function result type
0647      @return a new engine builder
0648      @throws java.lang.NullPointerException if one of the arguments is
0649      *         {@code null}.
0650      */
0651     @SafeVarargs
0652     public static <G extends Gene<?, G>, C extends Comparable<? super C>>
0653     Builder<G, C> builder(
0654         final Function<? super Genotype<G>, ? extends C> ff,
0655         final Chromosome<G> chromosome,
0656         final Chromosome<G>... chromosomes
0657     ) {
0658         return builder(ff, Genotype.of(chromosome, chromosomes));
0659     }
0660 
0661 
0662     /* *************************************************************************
0663      * Engine builder
0664      **************************************************************************/
0665 
0666 
0667     /**
0668      * Builder class for building GA {@code Engine} instances.
0669      *
0670      @see Engine
0671      *
0672      @param <G> the gene type
0673      @param <C> the fitness function result type
0674      *
0675      @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
0676      @since 3.0
0677      @version 6.0
0678      */
0679     public static final class Builder<
0680         extends Gene<?, G>,
0681         extends Comparable<? super C>
0682     >
0683         implements Copyable<Builder<G, C>>
0684     {
0685 
0686         // No default values for this properties.
0687         private final Evaluator<G, C> _evaluator;
0688         private final Factory<Genotype<G>> _genotypeFactory;
0689         private Constraint<G, C> _constraint;
0690         private Optimize _optimize = Optimize.MAXIMUM;
0691 
0692         // Evolution parameters.
0693         private final EvolutionParams.Builder<G, C> _evolutionParams =
0694             EvolutionParams.builder();
0695 
0696 
0697         // Engine execution environment.
0698         private Executor _executor = commonPool();
0699         private Clock _clock = NanoClock.systemUTC();
0700 
0701         private EvolutionInterceptor<G, C> _interceptor =
0702             EvolutionInterceptor.identity();
0703 
0704         /**
0705          * Create a new evolution {@code Engine.Builder} with the given fitness
0706          * evaluator and genotype factory. This is the most general way for
0707          * creating an engine builder.
0708          *
0709          @since 5.0
0710          *
0711          @see Engine#builder(Function, Codec)
0712          @see Engine#builder(Function, Factory)
0713          @see Engine#builder(Problem)
0714          @see Engine#builder(Function, Chromosome, Chromosome[])
0715          *
0716          @param evaluator the fitness evaluator
0717          @param genotypeFactory the genotype factory
0718          @throws NullPointerException if one of the arguments is {@code null}.
0719          */
0720         public Builder(
0721             final Evaluator<G, C> evaluator,
0722             final Factory<Genotype<G>> genotypeFactory
0723         ) {
0724             _genotypeFactory = requireNonNull(genotypeFactory);
0725             _evaluator = requireNonNull(evaluator);
0726         }
0727 
0728         /**
0729          * Applies the given {@code setup} recipe to {@code this} engine builder.
0730          *
0731          @since 6.0
0732          *
0733          @param setup the setup recipe applying to {@code this} builder
0734          @return {@code this} builder, for command chaining
0735          @throws NullPointerException if the {@code setup} is {@code null}.
0736          */
0737         public Builder<G, C> setup(final Setup<G, C> setup) {
0738             setup.apply(this);
0739             return this;
0740         }
0741 
0742         /**
0743          * Set the evolution parameters used by the engine.
0744          *
0745          @since 5.2
0746          *
0747          @param params the evolution parameter
0748          @return {@code this} builder, for command chaining
0749          @throws NullPointerException if the {@code params} is {@code null}.
0750          */
0751         public Builder<G, C> evolutionParams(final EvolutionParams<G, C> params) {
0752             _evolutionParams.evolutionParams(params);
0753             return this;
0754         }
0755 
0756         /**
0757          * The selector used for selecting the offspring population. <i>Default
0758          * values is set to {@code TournamentSelector<>(3)}.</i>
0759          *
0760          @param selector used for selecting the offspring population
0761          @return {@code this} builder, for command chaining
0762          @throws NullPointerException if one of the {@code selector} is
0763          *         {@code null}.
0764          */
0765         public Builder<G, C> offspringSelector(final Selector<G, C> selector) {
0766             _evolutionParams.offspringSelector(selector);
0767             return this;
0768         }
0769 
0770         /**
0771          * The selector used for selecting the survivors population. <i>Default
0772          * values is set to {@code TournamentSelector<>(3)}.</i>
0773          *
0774          @param selector used for selecting survivors population
0775          @return {@code this} builder, for command chaining
0776          @throws NullPointerException if one of the {@code selector} is
0777          *         {@code null}.
0778          */
0779         public Builder<G, C> survivorsSelector(final Selector<G, C> selector) {
0780             _evolutionParams.survivorsSelector(selector);
0781             return this;
0782         }
0783 
0784         /**
0785          * The selector used for selecting the survivors and offspring
0786          * population. <i>Default values is set to
0787          * {@code TournamentSelector<>(3)}.</i>
0788          *
0789          @param selector used for selecting survivors and offspring population
0790          @return {@code this} builder, for command chaining
0791          @throws NullPointerException if one of the {@code selector} is
0792          *         {@code null}.
0793          */
0794         public Builder<G, C> selector(final Selector<G, C> selector) {
0795             _evolutionParams.selector(selector);
0796             return this;
0797         }
0798 
0799         /**
0800          * The alterers used for alter the offspring population. <i>Default
0801          * values is set to {@code new SinglePointCrossover<>(0.2)} followed by
0802          * {@code new Mutator<>(0.15)}.</i>
0803          *
0804          @param first the first alterer used for alter the offspring
0805          *        population
0806          @param rest the rest of the alterers used for alter the offspring
0807          *        population
0808          @return {@code this} builder, for command chaining
0809          @throws NullPointerException if one of the alterers is {@code null}.
0810          */
0811         @SafeVarargs
0812         public final Builder<G, C> alterers(
0813             final Alterer<G, C> first,
0814             final Alterer<G, C>... rest
0815         ) {
0816             _evolutionParams.alterers(first, rest);
0817             return this;
0818         }
0819 
0820         /**
0821          * The phenotype constraint is used for detecting invalid individuals
0822          * and repairing them.
0823          *
0824          <p><i>Default implementation uses {@code Phenotype::isValid} for
0825          * validating the phenotype.</i></p>
0826          *
0827          @since 5.0
0828          *
0829          @param constraint phenotype constraint which can override the default
0830          *        implementation the {@link Phenotype#isValid()} method and repairs
0831          *        invalid phenotypes when needed.
0832          @return {@code this} builder, for command chaining
0833          @throws NullPointerException if one of the {@code constraint} is
0834          *         {@code null}.
0835          */
0836         public Builder<G, C> constraint(final Constraint<G, C> constraint) {
0837             _constraint = constraint;
0838             return this;
0839         }
0840 
0841         /**
0842          * The optimization strategy used by the engine. <i>Default values is
0843          * set to {@code Optimize.MAXIMUM}.</i>
0844          *
0845          @param optimize the optimization strategy used by the engine
0846          @return {@code this} builder, for command chaining
0847          @throws NullPointerException if one of the {@code optimize} is
0848          *         {@code null}.
0849          */
0850         public Builder<G, C> optimize(final Optimize optimize) {
0851             _optimize = requireNonNull(optimize);
0852             return this;
0853         }
0854 
0855         /**
0856          * Set to a fitness maximizing strategy.
0857          *
0858          @since 3.4
0859          *
0860          @return {@code this} builder, for command chaining
0861          */
0862         public Builder<G, C> maximizing() {
0863             return optimize(Optimize.MAXIMUM);
0864         }
0865 
0866         /**
0867          * Set to a fitness minimizing strategy.
0868          *
0869          @since 3.4
0870          *
0871          @return {@code this} builder, for command chaining
0872          */
0873         public Builder<G, C> minimizing() {
0874             return optimize(Optimize.MINIMUM);
0875         }
0876 
0877         /**
0878          * The offspring fraction. <i>Default values is set to {@code 0.6}.</i>
0879          * This method call is equivalent to
0880          * {@code survivorsFraction(1 - offspringFraction)} and will override
0881          * any previously set survivors-fraction.
0882          *
0883          @see #survivorsFraction(double)
0884          *
0885          @param fraction the offspring fraction
0886          @return {@code this} builder, for command chaining
0887          @throws java.lang.IllegalArgumentException if the fraction is not
0888          *         within the range [0, 1].
0889          */
0890         public Builder<G, C> offspringFraction(final double fraction) {
0891             _evolutionParams.offspringFraction(fraction);
0892             return this;
0893         }
0894 
0895         /**
0896          * The survivors fraction. <i>Default values is set to {@code 0.4}.</i>
0897          * This method call is equivalent to
0898          * {@code offspringFraction(1 - survivorsFraction)} and will override
0899          * any previously set offspring-fraction.
0900          *
0901          @since 3.8
0902          *
0903          @see #offspringFraction(double)
0904          *
0905          @param fraction the survivors fraction
0906          @return {@code this} builder, for command chaining
0907          @throws java.lang.IllegalArgumentException if the fraction is not
0908          *         within the range [0, 1].
0909          */
0910         public Builder<G, C> survivorsFraction(final double fraction) {
0911             return offspringFraction(- fraction);
0912         }
0913 
0914         /**
0915          * The number of offspring individuals.
0916          *
0917          @since 3.8
0918          *
0919          @param size the number of offspring individuals.
0920          @return {@code this} builder, for command chaining
0921          @throws java.lang.IllegalArgumentException if the size is not
0922          *         within the range [0, population-size].
0923          */
0924         public Builder<G, C> offspringSize(final int size) {
0925             if (size < 0) {
0926                 throw new IllegalArgumentException(format(
0927                     "Offspring size must be greater or equal zero, but was %s.",
0928                     size
0929                 ));
0930             }
0931 
0932             return offspringFraction(size/(double)_evolutionParams.populationSize());
0933         }
0934 
0935         /**
0936          * The number of survivors.
0937          *
0938          @since 3.8
0939          *
0940          @param size the number of survivors.
0941          @return {@code this} builder, for command chaining
0942          @throws java.lang.IllegalArgumentException if the size is not
0943          *         within the range [0, population-size].
0944          */
0945         public Builder<G, C> survivorsSize(final int size) {
0946             if (size < 0) {
0947                 throw new IllegalArgumentException(format(
0948                     "Survivors must be greater or equal zero, but was %s.",
0949                     size
0950                 ));
0951             }
0952 
0953             return survivorsFraction(size/(double)_evolutionParams.populationSize());
0954         }
0955 
0956         /**
0957          * The number of individuals which form the population. <i>Default
0958          * values is set to {@code 50}.</i>
0959          *
0960          @param size the number of individuals of a population
0961          @return {@code this} builder, for command chaining
0962          @throws java.lang.IllegalArgumentException if {@code size < 1}
0963          */
0964         public Builder<G, C> populationSize(final int size) {
0965             _evolutionParams.populationSize(size);
0966             return this;
0967         }
0968 
0969         /**
0970          * The maximal allowed age of a phenotype. <i>Default values is set to
0971          * {@code 70}.</i>
0972          *
0973          @param age the maximal phenotype age
0974          @return {@code this} builder, for command chaining
0975          @throws java.lang.IllegalArgumentException if {@code age < 1}
0976          */
0977         public Builder<G, C> maximalPhenotypeAge(final long age) {
0978             _evolutionParams.maximalPhenotypeAge(age);
0979             return this;
0980         }
0981 
0982         /**
0983          * The executor used by the engine.
0984          *
0985          @param executor the executor used by the engine
0986          @return {@code this} builder, for command chaining
0987          */
0988         public Builder<G, C> executor(final Executor executor) {
0989             _executor = requireNonNull(executor);
0990             return this;
0991         }
0992 
0993         /**
0994          * The clock used for calculating the execution durations.
0995          *
0996          @param clock the clock used for calculating the execution durations
0997          @return {@code this} builder, for command chaining
0998          */
0999         public Builder<G, C> clock(final Clock clock) {
1000             _clock = requireNonNull(clock);
1001             return this;
1002         }
1003 
1004         /**
1005          * The evolution interceptor, which allows to change the evolution start
1006          * and result.
1007          *
1008          @since 6.0
1009          @see EvolutionResult#toUniquePopulation()
1010          *
1011          @param interceptor the evolution interceptor
1012          @return {@code this} builder, for command chaining
1013          @throws NullPointerException if the given {@code interceptor} is
1014          *         {@code null}
1015          */
1016         public Builder<G, C>
1017         interceptor(final EvolutionInterceptor<G, C> interceptor) {
1018             _interceptor = requireNonNull(interceptor);
1019             return this;
1020         }
1021 
1022         /**
1023          * Builds an new {@code Engine} instance from the set properties.
1024          *
1025          @return an new {@code Engine} instance from the set properties
1026          */
1027         public Engine<G, C> build() {
1028             return new Engine<>(
1029                 __evaluator(),
1030                 _genotypeFactory,
1031                 __constraint(),
1032                 _optimize,
1033                 _evolutionParams.build(),
1034                 _executor,
1035                 _clock,
1036                 _interceptor
1037             );
1038         }
1039 
1040         private Evaluator<G, C> __evaluator() {
1041             return _evaluator instanceof ConcurrentEvaluator
1042                 ((ConcurrentEvaluator<G, C>)_evaluator).with(_executor)
1043                 : _evaluator;
1044         }
1045 
1046         private Constraint<G, C> __constraint() {
1047             return _constraint == null
1048                 ? RetryConstraint.of(_genotypeFactory)
1049                 : _constraint;
1050         }
1051 
1052         /* *********************************************************************
1053          * Current properties
1054          ***********************************************************************/
1055 
1056         /**
1057          * Return the used {@link Alterer} of the GA.
1058          *
1059          @return the used {@link Alterer} of the GA.
1060          */
1061         public Alterer<G, C> alterer() {
1062             return _evolutionParams.alterer();
1063         }
1064 
1065         /**
1066          * Return the {@link Clock} the engine is using for measuring the execution
1067          * time.
1068          *
1069          @since 3.1
1070          *
1071          @return the clock used for measuring the execution time
1072          */
1073         public Clock clock() {
1074             return _clock;
1075         }
1076 
1077         /**
1078          * Return the {@link Executor} the engine is using for executing the
1079          * evolution steps.
1080          *
1081          @since 3.1
1082          *
1083          @return the executor used for performing the evolution steps
1084          */
1085         public Executor executor() {
1086             return _executor;
1087         }
1088 
1089         /**
1090          * Return the used genotype {@link Factory} of the GA. The genotype factory
1091          * is used for creating the initial population and new, random individuals
1092          * when needed (as replacement for invalid and/or died genotypes).
1093          *
1094          @since 3.1
1095          *
1096          @return the used genotype {@link Factory} of the GA.
1097          */
1098         public Factory<Genotype<G>> genotypeFactory() {
1099             return _genotypeFactory;
1100         }
1101 
1102         /**
1103          * Return the constraint of the evolution problem.
1104          *
1105          @since 5.0
1106          *
1107          @return the constraint of the evolution problem
1108          */
1109         public Constraint<G, C> constraint() {
1110             return _constraint;
1111         }
1112 
1113         /**
1114          * Return the currently set evolution parameters.
1115          *
1116          @since 5.2
1117          *
1118          @return the currently set evolution parameters
1119          */
1120         public EvolutionParams<G, C> evolutionParams() {
1121             return _evolutionParams.build();
1122         }
1123 
1124         /**
1125          * Return the maximal allowed phenotype age.
1126          *
1127          @since 3.1
1128          *
1129          @return the maximal allowed phenotype age
1130          */
1131         public long maximalPhenotypeAge() {
1132             return _evolutionParams.maximalPhenotypeAge();
1133         }
1134 
1135         /**
1136          * Return the offspring fraction.
1137          *
1138          @return the offspring fraction.
1139          */
1140         public double offspringFraction() {
1141             return _evolutionParams.offspringFraction();
1142         }
1143 
1144         /**
1145          * Return the used offspring {@link Selector} of the GA.
1146          *
1147          @since 3.1
1148          *
1149          @return the used offspring {@link Selector} of the GA.
1150          */
1151         public Selector<G, C> offspringSelector() {
1152             return _evolutionParams.offspringSelector();
1153         }
1154 
1155         /**
1156          * Return the used survivor {@link Selector} of the GA.
1157          *
1158          @since 3.1
1159          *
1160          @return the used survivor {@link Selector} of the GA.
1161          */
1162         public Selector<G, C> survivorsSelector() {
1163             return _evolutionParams.survivorsSelector();
1164         }
1165 
1166         /**
1167          * Return the optimization strategy.
1168          *
1169          @since 3.1
1170          *
1171          @return the optimization strategy
1172          */
1173         public Optimize optimize() {
1174             return _optimize;
1175         }
1176 
1177         /**
1178          * Return the number of individuals of a population.
1179          *
1180          @since 3.1
1181          *
1182          @return the number of individuals of a population
1183          */
1184         public int populationSize() {
1185             return _evolutionParams.populationSize();
1186         }
1187 
1188         /**
1189          * Return the evolution interceptor.
1190          *
1191          @since 6.0
1192          *
1193          @return the evolution interceptor
1194          */
1195         public EvolutionInterceptor<G, C> interceptor() {
1196             return _interceptor;
1197         }
1198 
1199         /**
1200          * Create a new builder, with the current configuration.
1201          *
1202          @since 3.1
1203          *
1204          @return a new builder, with the current configuration
1205          */
1206         @Override
1207         public Builder<G, C> copy() {
1208             return new Builder<>(_evaluator, _genotypeFactory)
1209                 .clock(_clock)
1210                 .executor(_executor)
1211                 .constraint(_constraint)
1212                 .optimize(_optimize)
1213                 .evolutionParams(_evolutionParams.build())
1214                 .interceptor(_interceptor);
1215         }
1216 
1217     }
1218 
1219 
1220     /* *************************************************************************
1221      * Engine setup
1222      **************************************************************************/
1223 
1224 
1225     /**
1226      * This interface represents a recipe for configuring (setup) a given
1227      {@link Builder}. It is mainly used for grouping mutually dependent
1228      * engine configurations. The following code snippet shows a possible usage
1229      * example.
1230      *
1231      <pre>{@code
1232      * final Engine<CharacterGene, Integer> engine = Engine.builder(problem)
1233      *     .setup(new WeaselProgram<>())
1234      *     .build();
1235      * }</pre>
1236      *
1237      @see Builder#setup(Setup)
1238      *
1239      @param <G> the gene type
1240      @param <C> the fitness result type
1241      *
1242      @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
1243      @version 6.0
1244      @since 6.0
1245      */
1246     @FunctionalInterface
1247     public interface Setup<
1248         extends Gene<?, G>,
1249         extends Comparable<? super C>
1250     {
1251 
1252         /**
1253          * Applies {@code this} setup to the given engine {@code builder}.
1254          *
1255          @param builder the engine builder to setup (configure)
1256          */
1257         void apply(final Builder<G, C> builder);
1258 
1259     }
1260 }
1261 
1262