Engine.java
0001 /*
0002  * Java Genetic Algorithm Library (jenetics-6.0.0).
0003  * Copyright (c) 2007-2020 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         return builder(problem.fitness(), problem.codec());
0634     }
0635 
0636     /**
0637      * Create a new evolution {@code Engine.Builder} with the given fitness
0638      * function and chromosome templates.
0639      *
0640      @param ff the fitness function
0641      @param chromosome the first chromosome
0642      @param chromosomes the chromosome templates
0643      @param <G> the gene type
0644      @param <C> the fitness function result type
0645      @return a new engine builder
0646      @throws java.lang.NullPointerException if one of the arguments is
0647      *         {@code null}.
0648      */
0649     @SafeVarargs
0650     public static <G extends Gene<?, G>, C extends Comparable<? super C>>
0651     Builder<G, C> builder(
0652         final Function<? super Genotype<G>, ? extends C> ff,
0653         final Chromosome<G> chromosome,
0654         final Chromosome<G>... chromosomes
0655     ) {
0656         return builder(ff, Genotype.of(chromosome, chromosomes));
0657     }
0658 
0659 
0660     /* *************************************************************************
0661      * Engine builder
0662      **************************************************************************/
0663 
0664 
0665     /**
0666      * Builder class for building GA {@code Engine} instances.
0667      *
0668      @see Engine
0669      *
0670      @param <G> the gene type
0671      @param <C> the fitness function result type
0672      *
0673      @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
0674      @since 3.0
0675      @version 6.0
0676      */
0677     public static final class Builder<
0678         extends Gene<?, G>,
0679         extends Comparable<? super C>
0680     >
0681         implements Copyable<Builder<G, C>>
0682     {
0683 
0684         // No default values for this properties.
0685         private final Evaluator<G, C> _evaluator;
0686         private final Factory<Genotype<G>> _genotypeFactory;
0687         private Constraint<G, C> _constraint;
0688         private Optimize _optimize = Optimize.MAXIMUM;
0689 
0690         // Evolution parameters.
0691         private final EvolutionParams.Builder<G, C> _evolutionParams =
0692             EvolutionParams.builder();
0693 
0694 
0695         // Engine execution environment.
0696         private Executor _executor = commonPool();
0697         private Clock _clock = NanoClock.systemUTC();
0698 
0699         private EvolutionInterceptor<G, C> _interceptor =
0700             EvolutionInterceptor.identity();
0701 
0702         /**
0703          * Create a new evolution {@code Engine.Builder} with the given fitness
0704          * evaluator and genotype factory. This is the most general way for
0705          * creating an engine builder.
0706          *
0707          @since 5.0
0708          *
0709          @see Engine#builder(Function, Codec)
0710          @see Engine#builder(Function, Factory)
0711          @see Engine#builder(Problem)
0712          @see Engine#builder(Function, Chromosome, Chromosome[])
0713          *
0714          @param evaluator the fitness evaluator
0715          @param genotypeFactory the genotype factory
0716          @throws NullPointerException if one of the arguments is {@code null}.
0717          */
0718         public Builder(
0719             final Evaluator<G, C> evaluator,
0720             final Factory<Genotype<G>> genotypeFactory
0721         ) {
0722             _genotypeFactory = requireNonNull(genotypeFactory);
0723             _evaluator = requireNonNull(evaluator);
0724         }
0725 
0726         /**
0727          * Applies the given {@code setup} recipe to {@code this} engine builder.
0728          *
0729          @since 6.0
0730          *
0731          @param setup the setup recipe applying to {@code this} builder
0732          @return {@code this} builder, for command chaining
0733          @throws NullPointerException if the {@code setup} is {@code null}.
0734          */
0735         public Builder<G, C> setup(final Setup<G, C> setup) {
0736             setup.apply(this);
0737             return this;
0738         }
0739 
0740         /**
0741          * Set the evolution parameters used by the engine.
0742          *
0743          @since 5.2
0744          *
0745          @param params the evolution parameter
0746          @return {@code this} builder, for command chaining
0747          @throws NullPointerException if the {@code params} is {@code null}.
0748          */
0749         public Builder<G, C> evolutionParams(final EvolutionParams<G, C> params) {
0750             _evolutionParams.evolutionParams(params);
0751             return this;
0752         }
0753 
0754         /**
0755          * The selector used for selecting the offspring population. <i>Default
0756          * values is set to {@code TournamentSelector<>(3)}.</i>
0757          *
0758          @param selector used for selecting the offspring population
0759          @return {@code this} builder, for command chaining
0760          @throws NullPointerException if one of the {@code selector} is
0761          *         {@code null}.
0762          */
0763         public Builder<G, C> offspringSelector(final Selector<G, C> selector) {
0764             _evolutionParams.offspringSelector(selector);
0765             return this;
0766         }
0767 
0768         /**
0769          * The selector used for selecting the survivors population. <i>Default
0770          * values is set to {@code TournamentSelector<>(3)}.</i>
0771          *
0772          @param selector used for selecting survivors population
0773          @return {@code this} builder, for command chaining
0774          @throws NullPointerException if one of the {@code selector} is
0775          *         {@code null}.
0776          */
0777         public Builder<G, C> survivorsSelector(final Selector<G, C> selector) {
0778             _evolutionParams.survivorsSelector(selector);
0779             return this;
0780         }
0781 
0782         /**
0783          * The selector used for selecting the survivors and offspring
0784          * population. <i>Default values is set to
0785          * {@code TournamentSelector<>(3)}.</i>
0786          *
0787          @param selector used for selecting survivors and offspring population
0788          @return {@code this} builder, for command chaining
0789          @throws NullPointerException if one of the {@code selector} is
0790          *         {@code null}.
0791          */
0792         public Builder<G, C> selector(final Selector<G, C> selector) {
0793             _evolutionParams.selector(selector);
0794             return this;
0795         }
0796 
0797         /**
0798          * The alterers used for alter the offspring population. <i>Default
0799          * values is set to {@code new SinglePointCrossover<>(0.2)} followed by
0800          * {@code new Mutator<>(0.15)}.</i>
0801          *
0802          @param first the first alterer used for alter the offspring
0803          *        population
0804          @param rest the rest of the alterers used for alter the offspring
0805          *        population
0806          @return {@code this} builder, for command chaining
0807          @throws NullPointerException if one of the alterers is {@code null}.
0808          */
0809         @SafeVarargs
0810         public final Builder<G, C> alterers(
0811             final Alterer<G, C> first,
0812             final Alterer<G, C>... rest
0813         ) {
0814             _evolutionParams.alterers(first, rest);
0815             return this;
0816         }
0817 
0818         /**
0819          * The phenotype constraint is used for detecting invalid individuals
0820          * and repairing them.
0821          *
0822          <p><i>Default implementation uses {@code Phenotype::isValid} for
0823          * validating the phenotype.</i></p>
0824          *
0825          @since 5.0
0826          *
0827          @param constraint phenotype constraint which can override the default
0828          *        implementation the {@link Phenotype#isValid()} method and repairs
0829          *        invalid phenotypes when needed.
0830          @return {@code this} builder, for command chaining
0831          @throws NullPointerException if one of the {@code constraint} is
0832          *         {@code null}.
0833          */
0834         public Builder<G, C> constraint(final Constraint<G, C> constraint) {
0835             _constraint = constraint;
0836             return this;
0837         }
0838 
0839         /**
0840          * The optimization strategy used by the engine. <i>Default values is
0841          * set to {@code Optimize.MAXIMUM}.</i>
0842          *
0843          @param optimize the optimization strategy used by the engine
0844          @return {@code this} builder, for command chaining
0845          @throws NullPointerException if one of the {@code optimize} is
0846          *         {@code null}.
0847          */
0848         public Builder<G, C> optimize(final Optimize optimize) {
0849             _optimize = requireNonNull(optimize);
0850             return this;
0851         }
0852 
0853         /**
0854          * Set to a fitness maximizing strategy.
0855          *
0856          @since 3.4
0857          *
0858          @return {@code this} builder, for command chaining
0859          */
0860         public Builder<G, C> maximizing() {
0861             return optimize(Optimize.MAXIMUM);
0862         }
0863 
0864         /**
0865          * Set to a fitness minimizing strategy.
0866          *
0867          @since 3.4
0868          *
0869          @return {@code this} builder, for command chaining
0870          */
0871         public Builder<G, C> minimizing() {
0872             return optimize(Optimize.MINIMUM);
0873         }
0874 
0875         /**
0876          * The offspring fraction. <i>Default values is set to {@code 0.6}.</i>
0877          * This method call is equivalent to
0878          * {@code survivorsFraction(1 - offspringFraction)} and will override
0879          * any previously set survivors-fraction.
0880          *
0881          @see #survivorsFraction(double)
0882          *
0883          @param fraction the offspring fraction
0884          @return {@code this} builder, for command chaining
0885          @throws java.lang.IllegalArgumentException if the fraction is not
0886          *         within the range [0, 1].
0887          */
0888         public Builder<G, C> offspringFraction(final double fraction) {
0889             _evolutionParams.offspringFraction(fraction);
0890             return this;
0891         }
0892 
0893         /**
0894          * The survivors fraction. <i>Default values is set to {@code 0.4}.</i>
0895          * This method call is equivalent to
0896          * {@code offspringFraction(1 - survivorsFraction)} and will override
0897          * any previously set offspring-fraction.
0898          *
0899          @since 3.8
0900          *
0901          @see #offspringFraction(double)
0902          *
0903          @param fraction the survivors fraction
0904          @return {@code this} builder, for command chaining
0905          @throws java.lang.IllegalArgumentException if the fraction is not
0906          *         within the range [0, 1].
0907          */
0908         public Builder<G, C> survivorsFraction(final double fraction) {
0909             return offspringFraction(- fraction);
0910         }
0911 
0912         /**
0913          * The number of offspring individuals.
0914          *
0915          @since 3.8
0916          *
0917          @param size the number of offspring individuals.
0918          @return {@code this} builder, for command chaining
0919          @throws java.lang.IllegalArgumentException if the size is not
0920          *         within the range [0, population-size].
0921          */
0922         public Builder<G, C> offspringSize(final int size) {
0923             if (size < 0) {
0924                 throw new IllegalArgumentException(format(
0925                     "Offspring size must be greater or equal zero, but was %s.",
0926                     size
0927                 ));
0928             }
0929 
0930             return offspringFraction(size/(double)_evolutionParams.populationSize());
0931         }
0932 
0933         /**
0934          * The number of survivors.
0935          *
0936          @since 3.8
0937          *
0938          @param size the number of survivors.
0939          @return {@code this} builder, for command chaining
0940          @throws java.lang.IllegalArgumentException if the size is not
0941          *         within the range [0, population-size].
0942          */
0943         public Builder<G, C> survivorsSize(final int size) {
0944             if (size < 0) {
0945                 throw new IllegalArgumentException(format(
0946                     "Survivors must be greater or equal zero, but was %s.",
0947                     size
0948                 ));
0949             }
0950 
0951             return survivorsFraction(size/(double)_evolutionParams.populationSize());
0952         }
0953 
0954         /**
0955          * The number of individuals which form the population. <i>Default
0956          * values is set to {@code 50}.</i>
0957          *
0958          @param size the number of individuals of a population
0959          @return {@code this} builder, for command chaining
0960          @throws java.lang.IllegalArgumentException if {@code size < 1}
0961          */
0962         public Builder<G, C> populationSize(final int size) {
0963             _evolutionParams.populationSize(size);
0964             return this;
0965         }
0966 
0967         /**
0968          * The maximal allowed age of a phenotype. <i>Default values is set to
0969          * {@code 70}.</i>
0970          *
0971          @param age the maximal phenotype age
0972          @return {@code this} builder, for command chaining
0973          @throws java.lang.IllegalArgumentException if {@code age < 1}
0974          */
0975         public Builder<G, C> maximalPhenotypeAge(final long age) {
0976             _evolutionParams.maximalPhenotypeAge(age);
0977             return this;
0978         }
0979 
0980         /**
0981          * The executor used by the engine.
0982          *
0983          @param executor the executor used by the engine
0984          @return {@code this} builder, for command chaining
0985          */
0986         public Builder<G, C> executor(final Executor executor) {
0987             _executor = requireNonNull(executor);
0988             return this;
0989         }
0990 
0991         /**
0992          * The clock used for calculating the execution durations.
0993          *
0994          @param clock the clock used for calculating the execution durations
0995          @return {@code this} builder, for command chaining
0996          */
0997         public Builder<G, C> clock(final Clock clock) {
0998             _clock = requireNonNull(clock);
0999             return this;
1000         }
1001 
1002         /**
1003          * The evolution interceptor, which allows to change the evolution start
1004          * and result.
1005          *
1006          @since 6.0
1007          @see EvolutionResult#toUniquePopulation()
1008          *
1009          @param interceptor the evolution interceptor
1010          @return {@code this} builder, for command chaining
1011          @throws NullPointerException if the given {@code interceptor} is
1012          *         {@code null}
1013          */
1014         public Builder<G, C>
1015         interceptor(final EvolutionInterceptor<G, C> interceptor) {
1016             _interceptor = requireNonNull(interceptor);
1017             return this;
1018         }
1019 
1020         /**
1021          * Builds an new {@code Engine} instance from the set properties.
1022          *
1023          @return an new {@code Engine} instance from the set properties
1024          */
1025         public Engine<G, C> build() {
1026             return new Engine<>(
1027                 __evaluator(),
1028                 _genotypeFactory,
1029                 __constraint(),
1030                 _optimize,
1031                 _evolutionParams.build(),
1032                 _executor,
1033                 _clock,
1034                 _interceptor
1035             );
1036         }
1037 
1038         private Evaluator<G, C> __evaluator() {
1039             return _evaluator instanceof ConcurrentEvaluator
1040                 ((ConcurrentEvaluator<G, C>)_evaluator).with(_executor)
1041                 : _evaluator;
1042         }
1043 
1044         private Constraint<G, C> __constraint() {
1045             return _constraint == null
1046                 ? RetryConstraint.of(_genotypeFactory)
1047                 : _constraint;
1048         }
1049 
1050         /* *********************************************************************
1051          * Current properties
1052          ***********************************************************************/
1053 
1054         /**
1055          * Return the used {@link Alterer} of the GA.
1056          *
1057          @return the used {@link Alterer} of the GA.
1058          */
1059         public Alterer<G, C> alterer() {
1060             return _evolutionParams.alterer();
1061         }
1062 
1063         /**
1064          * Return the {@link Clock} the engine is using for measuring the execution
1065          * time.
1066          *
1067          @since 3.1
1068          *
1069          @return the clock used for measuring the execution time
1070          */
1071         public Clock clock() {
1072             return _clock;
1073         }
1074 
1075         /**
1076          * Return the {@link Executor} the engine is using for executing the
1077          * evolution steps.
1078          *
1079          @since 3.1
1080          *
1081          @return the executor used for performing the evolution steps
1082          */
1083         public Executor executor() {
1084             return _executor;
1085         }
1086 
1087         /**
1088          * Return the used genotype {@link Factory} of the GA. The genotype factory
1089          * is used for creating the initial population and new, random individuals
1090          * when needed (as replacement for invalid and/or died genotypes).
1091          *
1092          @since 3.1
1093          *
1094          @return the used genotype {@link Factory} of the GA.
1095          */
1096         public Factory<Genotype<G>> genotypeFactory() {
1097             return _genotypeFactory;
1098         }
1099 
1100         /**
1101          * Return the constraint of the evolution problem.
1102          *
1103          @since 5.0
1104          *
1105          @return the constraint of the evolution problem
1106          */
1107         public Constraint<G, C> constraint() {
1108             return _constraint;
1109         }
1110 
1111         /**
1112          * Return the currently set evolution parameters.
1113          *
1114          @since 5.2
1115          *
1116          @return the currently set evolution parameters
1117          */
1118         public EvolutionParams<G, C> evolutionParams() {
1119             return _evolutionParams.build();
1120         }
1121 
1122         /**
1123          * Return the maximal allowed phenotype age.
1124          *
1125          @since 3.1
1126          *
1127          @return the maximal allowed phenotype age
1128          */
1129         public long maximalPhenotypeAge() {
1130             return _evolutionParams.maximalPhenotypeAge();
1131         }
1132 
1133         /**
1134          * Return the offspring fraction.
1135          *
1136          @return the offspring fraction.
1137          */
1138         public double offspringFraction() {
1139             return _evolutionParams.offspringFraction();
1140         }
1141 
1142         /**
1143          * Return the used offspring {@link Selector} of the GA.
1144          *
1145          @since 3.1
1146          *
1147          @return the used offspring {@link Selector} of the GA.
1148          */
1149         public Selector<G, C> offspringSelector() {
1150             return _evolutionParams.offspringSelector();
1151         }
1152 
1153         /**
1154          * Return the used survivor {@link Selector} of the GA.
1155          *
1156          @since 3.1
1157          *
1158          @return the used survivor {@link Selector} of the GA.
1159          */
1160         public Selector<G, C> survivorsSelector() {
1161             return _evolutionParams.survivorsSelector();
1162         }
1163 
1164         /**
1165          * Return the optimization strategy.
1166          *
1167          @since 3.1
1168          *
1169          @return the optimization strategy
1170          */
1171         public Optimize optimize() {
1172             return _optimize;
1173         }
1174 
1175         /**
1176          * Return the number of individuals of a population.
1177          *
1178          @since 3.1
1179          *
1180          @return the number of individuals of a population
1181          */
1182         public int populationSize() {
1183             return _evolutionParams.populationSize();
1184         }
1185 
1186         /**
1187          * Return the evolution interceptor.
1188          *
1189          @since 6.0
1190          *
1191          @return the evolution interceptor
1192          */
1193         public EvolutionInterceptor<G, C> interceptor() {
1194             return _interceptor;
1195         }
1196 
1197         /**
1198          * Create a new builder, with the current configuration.
1199          *
1200          @since 3.1
1201          *
1202          @return a new builder, with the current configuration
1203          */
1204         @Override
1205         public Builder<G, C> copy() {
1206             return new Builder<>(_evaluator, _genotypeFactory)
1207                 .clock(_clock)
1208                 .executor(_executor)
1209                 .constraint(_constraint)
1210                 .optimize(_optimize)
1211                 .evolutionParams(_evolutionParams.build())
1212                 .interceptor(_interceptor);
1213         }
1214 
1215     }
1216 
1217 
1218     /* *************************************************************************
1219      * Engine setup
1220      **************************************************************************/
1221 
1222 
1223     /**
1224      * This interface represents a recipe for configuring (setup) a given
1225      {@link Builder}. It is mainly used for grouping mutually dependent
1226      * engine configurations. The following code snippet shows a possible usage
1227      * example.
1228      *
1229      <pre>{@code
1230      * final Engine<CharacterGene, Integer> engine = Engine.builder(problem)
1231      *     .setup(new WeaselProgram<>())
1232      *     .build();
1233      * }</pre>
1234      *
1235      @see Builder#setup(Setup)
1236      *
1237      @param <G> the gene type
1238      @param <C> the fitness result type
1239      *
1240      @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
1241      @version 6.0
1242      @since 6.0
1243      */
1244     @FunctionalInterface
1245     public static interface Setup<
1246         extends Gene<?, G>,
1247         extends Comparable<? super C>
1248     {
1249 
1250         /**
1251          * Applies {@code this} setup to the given engine {@code builder}.
1252          *
1253          @param builder the engine builder to setup (configure)
1254          */
1255         void apply(final Builder<G, C> builder);
1256 
1257     }
1258 }
1259 
1260