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