001/* 002 * Java Genetic Algorithm Library (jenetics-4.4.0). 003 * Copyright (c) 2007-2019 Franz Wilhelmstötter 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 * Author: 018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com) 019 */ 020package io.jenetics.engine; 021 022import static java.lang.Math.round; 023import static java.lang.String.format; 024import static java.util.Objects.requireNonNull; 025import static io.jenetics.internal.util.require.probability; 026 027import java.time.Clock; 028import java.util.Iterator; 029import java.util.Objects; 030import java.util.concurrent.CompletableFuture; 031import java.util.concurrent.Executor; 032import java.util.concurrent.ForkJoinPool; 033import java.util.function.Function; 034import java.util.function.Predicate; 035import java.util.function.Supplier; 036import java.util.function.UnaryOperator; 037import java.util.stream.Stream; 038 039import io.jenetics.Alterer; 040import io.jenetics.AltererResult; 041import io.jenetics.Chromosome; 042import io.jenetics.Gene; 043import io.jenetics.Genotype; 044import io.jenetics.Mutator; 045import io.jenetics.Optimize; 046import io.jenetics.Phenotype; 047import io.jenetics.Selector; 048import io.jenetics.SinglePointCrossover; 049import io.jenetics.TournamentSelector; 050import io.jenetics.internal.util.require; 051import io.jenetics.util.Copyable; 052import io.jenetics.util.Factory; 053import io.jenetics.util.ISeq; 054import io.jenetics.util.MSeq; 055import io.jenetics.util.NanoClock; 056import io.jenetics.util.Seq; 057 058/** 059 * Genetic algorithm <em>engine</em> which is the main class. The following 060 * example shows the main steps in initializing and executing the GA. 061 * 062 * <pre>{@code 063 * public class RealFunction { 064 * // Definition of the fitness function. 065 * private static Double eval(final Genotype<DoubleGene> gt) { 066 * final double x = gt.getGene().doubleValue(); 067 * return cos(0.5 + sin(x))*cos(x); 068 * } 069 * 070 * public static void main(String[] args) { 071 * // Create/configuring the engine via its builder. 072 * final Engine<DoubleGene, Double> engine = Engine 073 * .builder( 074 * RealFunction::eval, 075 * DoubleChromosome.of(0.0, 2.0*PI)) 076 * .populationSize(500) 077 * .optimize(Optimize.MINIMUM) 078 * .alterers( 079 * new Mutator<>(0.03), 080 * new MeanAlterer<>(0.6)) 081 * .build(); 082 * 083 * // Execute the GA (engine). 084 * final Phenotype<DoubleGene, Double> result = engine.stream() 085 * // Truncate the evolution stream if no better individual could 086 * // be found after 5 consecutive generations. 087 * .limit(bySteadyFitness(5)) 088 * // Terminate the evolution after maximal 100 generations. 089 * .limit(100) 090 * .collect(toBestPhenotype()); 091 * } 092 * } 093 * }</pre> 094 * 095 * The architecture allows to decouple the configuration of the engine from the 096 * execution. The {@code Engine} is configured via the {@code Engine.Builder} 097 * class and can't be changed after creation. The actual <i>evolution</i> is 098 * performed by the {@link EvolutionStream}, which is created by the 099 * {@code Engine}. 100 * 101 * @implNote 102 * This class is thread safe: 103 * No mutable state is maintained by the engine. Therefore it is save to 104 * create multiple evolution streams with one engine, which may be actually 105 * used in different threads. 106 * 107 * @see Engine.Builder 108 * @see EvolutionStart 109 * @see EvolutionResult 110 * @see EvolutionStream 111 * @see EvolutionStatistics 112 * @see Codec 113 * 114 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 115 * @since 3.0 116 * @version 4.1 117 */ 118@SuppressWarnings("deprecation") 119public final class Engine< 120 G extends Gene<?, G>, 121 C extends Comparable<? super C> 122> 123 implements 124 Function<EvolutionStart<G, C>, EvolutionResult<G, C>>, 125 EvolutionStreamable<G, C>, 126 EvolutionIterable<G, C> 127{ 128 129 // Problem definition. 130 private final Function<? super Genotype<G>, ? extends C> _fitnessFunction; 131 private final Factory<Genotype<G>> _genotypeFactory; 132 133 // Evolution parameters. 134 private final Function<? super C, ? extends C> _fitnessScaler; 135 private final Selector<G, C> _survivorsSelector; 136 private final Selector<G, C> _offspringSelector; 137 private final Alterer<G, C> _alterer; 138 private final Predicate<? super Phenotype<G, C>> _validator; 139 private final Optimize _optimize; 140 private final int _offspringCount; 141 private final int _survivorsCount; 142 private final long _maximalPhenotypeAge; 143 144 // Execution context for concurrent execution of evolving steps. 145 private final TimedExecutor _executor; 146 private final Evaluator<G, C> _evaluator; 147 private final Clock _clock; 148 149 // Additional parameters. 150 private final int _individualCreationRetries; 151 private final UnaryOperator<EvolutionResult<G, C>> _mapper; 152 153 154 /** 155 * Create a new GA engine with the given parameters. 156 * 157 * @param fitnessFunction the fitness function this GA is using. 158 * @param genotypeFactory the genotype factory this GA is working with. 159 * @param fitnessScaler the fitness scaler this GA is using. 160 * @param survivorsSelector the selector used for selecting the survivors 161 * @param offspringSelector the selector used for selecting the offspring 162 * @param alterer the alterer used for altering the offspring 163 * @param validator phenotype validator which can override the default 164 * implementation the {@link Phenotype#isValid()} method. 165 * @param optimize the kind of optimization (minimize or maximize) 166 * @param offspringCount the number of the offspring individuals 167 * @param survivorsCount the number of the survivor individuals 168 * @param maximalPhenotypeAge the maximal age of an individual 169 * @param executor the executor used for executing the single evolve steps 170 * @param evaluator the population fitness evaluator 171 * @param clock the clock used for calculating the timing results 172 * @param individualCreationRetries the maximal number of attempts for 173 * creating a valid individual. 174 * @throws NullPointerException if one of the arguments is {@code null} 175 * @throws IllegalArgumentException if the given integer values are smaller 176 * than one. 177 */ 178 Engine( 179 final Function<? super Genotype<G>, ? extends C> fitnessFunction, 180 final Factory<Genotype<G>> genotypeFactory, 181 final Function<? super C, ? extends C> fitnessScaler, 182 final Selector<G, C> survivorsSelector, 183 final Selector<G, C> offspringSelector, 184 final Alterer<G, C> alterer, 185 final Predicate<? super Phenotype<G, C>> validator, 186 final Optimize optimize, 187 final int offspringCount, 188 final int survivorsCount, 189 final long maximalPhenotypeAge, 190 final Executor executor, 191 final Evaluator<G, C> evaluator, 192 final Clock clock, 193 final int individualCreationRetries, 194 final UnaryOperator<EvolutionResult<G, C>> mapper 195 ) { 196 _fitnessFunction = requireNonNull(fitnessFunction); 197 _fitnessScaler = requireNonNull(fitnessScaler); 198 _genotypeFactory = requireNonNull(genotypeFactory); 199 _survivorsSelector = requireNonNull(survivorsSelector); 200 _offspringSelector = requireNonNull(offspringSelector); 201 _alterer = requireNonNull(alterer); 202 _validator = requireNonNull(validator); 203 _optimize = requireNonNull(optimize); 204 205 _offspringCount = require.nonNegative(offspringCount); 206 _survivorsCount = require.nonNegative(survivorsCount); 207 _maximalPhenotypeAge = require.positive(maximalPhenotypeAge); 208 209 _executor = new TimedExecutor(requireNonNull(executor)); 210 _evaluator = requireNonNull(evaluator); 211 _clock = requireNonNull(clock); 212 213 if (individualCreationRetries < 0) { 214 throw new IllegalArgumentException(format( 215 "Retry count must not be negative: %d", 216 individualCreationRetries 217 )); 218 } 219 _individualCreationRetries = individualCreationRetries; 220 _mapper = requireNonNull(mapper); 221 } 222 223 /** 224 * Perform one evolution step with the given {@code population} and 225 * {@code generation}. New phenotypes are created with the fitness function 226 * and fitness scaler defined by this <em>engine</em> 227 * <p> 228 * <em>This method is thread-safe.</em> 229 * 230 * @see #evolve(EvolutionStart) 231 * 232 * @param population the population to evolve 233 * @param generation the current generation; used for calculating the 234 * phenotype age. 235 * @return the evolution result 236 * @throws java.lang.NullPointerException if the given {@code population} is 237 * {@code null} 238 * @throws IllegalArgumentException if the given {@code generation} is 239 * smaller then one 240 */ 241 public EvolutionResult<G, C> evolve( 242 final ISeq<Phenotype<G, C>> population, 243 final long generation 244 ) { 245 return evolve(EvolutionStart.of(population, generation)); 246 } 247 248 /** 249 * Perform one evolution step with the given evolution {@code start} object 250 * New phenotypes are created with the fitness function and fitness scaler 251 * defined by this <em>engine</em> 252 * <p> 253 * <em>This method is thread-safe.</em> 254 * 255 * @since 3.1 256 * @see #evolve(ISeq, long) 257 * 258 * @param start the evolution start object 259 * @return the evolution result 260 * @throws java.lang.NullPointerException if the given evolution 261 * {@code start} is {@code null} 262 */ 263 public EvolutionResult<G, C> evolve(final EvolutionStart<G, C> start) { 264 final Timer timer = Timer.of(_clock).start(); 265 266 // Initial evaluation of the population. 267 final Timer evaluateTimer = Timer.of(_clock).start(); 268 final ISeq<Phenotype<G, C>> evalPop = 269 _evaluator.evaluate(start.getPopulation()); 270 271 if (start.getPopulation().size() != evalPop.size()) { 272 throw new IllegalStateException(format( 273 "Expected %d individuals, but got %d. " + 274 "Check your evaluator function.", 275 start.getPopulation().size(), evalPop.size() 276 )); 277 } 278 279 evaluateTimer.stop(); 280 281 // Select the offspring population. 282 final CompletableFuture<TimedResult<ISeq<Phenotype<G, C>>>> offspring = 283 _executor.async(() -> 284 selectOffspring(evalPop), 285 _clock 286 ); 287 288 // Select the survivor population. 289 final CompletableFuture<TimedResult<ISeq<Phenotype<G, C>>>> survivors = 290 _executor.async(() -> 291 selectSurvivors(evalPop), 292 _clock 293 ); 294 295 // Altering the offspring population. 296 final CompletableFuture<TimedResult<AltererResult<G, C>>> alteredOffspring = 297 _executor.thenApply(offspring, p -> 298 _alterer.alter(p.result, start.getGeneration()), 299 _clock 300 ); 301 302 // Filter and replace invalid and old survivor individuals. 303 final CompletableFuture<TimedResult<FilterResult<G, C>>> filteredSurvivors = 304 _executor.thenApply(survivors, pop -> 305 filter(pop.result, start.getGeneration()), 306 _clock 307 ); 308 309 // Filter and replace invalid and old offspring individuals. 310 final CompletableFuture<TimedResult<FilterResult<G, C>>> filteredOffspring = 311 _executor.thenApply(alteredOffspring, pop -> 312 filter(pop.result.getPopulation(), start.getGeneration()), 313 _clock 314 ); 315 316 // Combining survivors and offspring to the new population. 317 final CompletableFuture<ISeq<Phenotype<G, C>>> population = 318 filteredSurvivors.thenCombineAsync(filteredOffspring, (s, o) -> 319 ISeq.of(s.result.population.append(o.result.population)), 320 _executor.get() 321 ); 322 323 // Evaluate the fitness-function and wait for result. 324 final ISeq<Phenotype<G, C>> pop = population.join(); 325 final TimedResult<ISeq<Phenotype<G, C>>> result = TimedResult 326 .of(() -> _evaluator.evaluate(pop), _clock) 327 .get(); 328 329 330 final EvolutionDurations durations = EvolutionDurations.of( 331 offspring.join().duration, 332 survivors.join().duration, 333 alteredOffspring.join().duration, 334 filteredOffspring.join().duration, 335 filteredSurvivors.join().duration, 336 result.duration.plus(evaluateTimer.getTime()), 337 timer.stop().getTime() 338 ); 339 340 final int killCount = 341 filteredOffspring.join().result.killCount + 342 filteredSurvivors.join().result.killCount; 343 344 final int invalidCount = 345 filteredOffspring.join().result.invalidCount + 346 filteredSurvivors.join().result.invalidCount; 347 348 return _mapper.apply( 349 EvolutionResult.of( 350 _optimize, 351 result.result, 352 start.getGeneration(), 353 durations, 354 killCount, 355 invalidCount, 356 alteredOffspring.join().result.getAlterations() 357 ) 358 ); 359 } 360 361 /** 362 * This method is an <i>alias</i> for the {@link #evolve(EvolutionStart)} 363 * method. 364 * 365 * @since 3.1 366 */ 367 @Override 368 public EvolutionResult<G, C> apply(final EvolutionStart<G, C> start) { 369 return evolve(start); 370 } 371 372 // Selects the survivors population. A new population object is returned. 373 private ISeq<Phenotype<G, C>> 374 selectSurvivors(final ISeq<Phenotype<G, C>> population) { 375 return _survivorsCount > 0 376 ?_survivorsSelector.select(population, _survivorsCount, _optimize) 377 : ISeq.empty(); 378 } 379 380 // Selects the offspring population. A new population object is returned. 381 private ISeq<Phenotype<G, C>> 382 selectOffspring(final ISeq<Phenotype<G, C>> population) { 383 return _offspringCount > 0 384 ? _offspringSelector.select(population, _offspringCount, _optimize) 385 : ISeq.empty(); 386 } 387 388 // Filters out invalid and old individuals. Filtering is done in place. 389 private FilterResult<G, C> filter( 390 final Seq<Phenotype<G, C>> population, 391 final long generation 392 ) { 393 int killCount = 0; 394 int invalidCount = 0; 395 396 final MSeq<Phenotype<G, C>> pop = MSeq.of(population); 397 for (int i = 0, n = pop.size(); i < n; ++i) { 398 final Phenotype<G, C> individual = pop.get(i); 399 400 if (!_validator.test(individual)) { 401 pop.set(i, newPhenotype(generation)); 402 ++invalidCount; 403 } else if (individual.getAge(generation) > _maximalPhenotypeAge) { 404 pop.set(i, newPhenotype(generation)); 405 ++killCount; 406 } 407 } 408 409 return new FilterResult<>(pop.toISeq(), killCount, invalidCount); 410 } 411 412 // Create a new and valid phenotype 413 private Phenotype<G, C> newPhenotype(final long generation) { 414 int count = 0; 415 Phenotype<G, C> phenotype; 416 do { 417 phenotype = Phenotype.of( 418 _genotypeFactory.newInstance(), 419 generation, 420 _fitnessFunction, 421 _fitnessScaler 422 ); 423 } while (++count < _individualCreationRetries && 424 !_validator.test(phenotype)); 425 426 return phenotype; 427 } 428 429 430 /* ************************************************************************* 431 * Evolution Stream/Iterator creation. 432 **************************************************************************/ 433 434 @Deprecated 435 @Override 436 public Iterator<EvolutionResult<G, C>> 437 iterator(final Supplier<EvolutionStart<G, C>> start) { 438 return new EvolutionIterator<>(evolutionStart(start), this::evolve); 439 } 440 441 @Deprecated 442 @Override 443 public Iterator<EvolutionResult<G, C>> iterator(final EvolutionInit<G> init) { 444 return iterator(evolutionStart(init)); 445 } 446 447 @Override 448 public EvolutionStream<G, C> 449 stream(final Supplier<EvolutionStart<G, C>> start) { 450 return EvolutionStream.of(evolutionStart(start), this::evolve); 451 } 452 453 @Override 454 public EvolutionStream<G, C> stream(final EvolutionInit<G> init) { 455 return stream(evolutionStart(init)); 456 } 457 458 private Supplier<EvolutionStart<G, C>> 459 evolutionStart(final Supplier<EvolutionStart<G, C>> start) { 460 return () -> { 461 final EvolutionStart<G, C> es = start.get(); 462 final ISeq<Phenotype<G, C>> population = es.getPopulation(); 463 final long generation = es.getGeneration(); 464 465 final Stream<Phenotype<G, C>> stream = Stream.concat( 466 population.stream().map(this::toFixedPhenotype), 467 Stream.generate(() -> newPhenotype(generation)) 468 ); 469 470 final ISeq<Phenotype<G, C>> pop = stream 471 .limit(getPopulationSize()) 472 .collect(ISeq.toISeq()); 473 474 return EvolutionStart.of(pop, generation); 475 }; 476 } 477 478 private Phenotype<G, C> toFixedPhenotype(final Phenotype<G, C> pt) { 479 return 480 pt.getFitnessFunction() == _fitnessFunction && 481 pt.getFitnessScaler() == _fitnessScaler 482 ? pt 483 : pt.newInstance( 484 pt.getGeneration(), 485 _fitnessFunction, 486 _fitnessScaler 487 ); 488 } 489 490 private Supplier<EvolutionStart<G, C>> 491 evolutionStart(final EvolutionInit<G> init) { 492 return evolutionStart(() -> EvolutionStart.of( 493 init.getPopulation() 494 .map(gt -> Phenotype.of( 495 gt, 496 init.getGeneration(), 497 _fitnessFunction, 498 _fitnessScaler) 499 ), 500 init.getGeneration()) 501 ); 502 } 503 504 /* ************************************************************************* 505 * Property access methods. 506 **************************************************************************/ 507 508 /** 509 * Return the fitness function of the GA engine. 510 * 511 * @return the fitness function 512 */ 513 public Function<? super Genotype<G>, ? extends C> getFitnessFunction() { 514 return _fitnessFunction; 515 } 516 517 /** 518 * Return the fitness scaler of the GA engine. 519 * 520 * @return the fitness scaler 521 * 522 * @deprecated The fitness scaler will be remove in a future version. 523 */ 524 @Deprecated 525 public Function<? super C, ? extends C> getFitnessScaler() { 526 return _fitnessScaler; 527 } 528 529 /** 530 * Return the used genotype {@link Factory} of the GA. The genotype factory 531 * is used for creating the initial population and new, random individuals 532 * when needed (as replacement for invalid and/or died genotypes). 533 * 534 * @return the used genotype {@link Factory} of the GA. 535 */ 536 public Factory<Genotype<G>> getGenotypeFactory() { 537 return _genotypeFactory; 538 } 539 540 /** 541 * Return the used survivor {@link Selector} of the GA. 542 * 543 * @return the used survivor {@link Selector} of the GA. 544 */ 545 public Selector<G, C> getSurvivorsSelector() { 546 return _survivorsSelector; 547 } 548 549 /** 550 * Return the used offspring {@link Selector} of the GA. 551 * 552 * @return the used offspring {@link Selector} of the GA. 553 */ 554 public Selector<G, C> getOffspringSelector() { 555 return _offspringSelector; 556 } 557 558 /** 559 * Return the used {@link Alterer} of the GA. 560 * 561 * @return the used {@link Alterer} of the GA. 562 */ 563 public Alterer<G, C> getAlterer() { 564 return _alterer; 565 } 566 567 /** 568 * Return the number of selected offsprings. 569 * 570 * @return the number of selected offsprings 571 */ 572 public int getOffspringCount() { 573 return _offspringCount; 574 } 575 576 /** 577 * The number of selected survivors. 578 * 579 * @return the number of selected survivors 580 */ 581 public int getSurvivorsCount() { 582 return _survivorsCount; 583 } 584 585 /** 586 * Return the number of individuals of a population. 587 * 588 * @return the number of individuals of a population 589 */ 590 public int getPopulationSize() { 591 return _offspringCount + _survivorsCount; 592 } 593 594 /** 595 * Return the maximal allowed phenotype age. 596 * 597 * @return the maximal allowed phenotype age 598 */ 599 public long getMaximalPhenotypeAge() { 600 return _maximalPhenotypeAge; 601 } 602 603 /** 604 * Return the optimization strategy. 605 * 606 * @return the optimization strategy 607 */ 608 public Optimize getOptimize() { 609 return _optimize; 610 } 611 612 /** 613 * Return the {@link Clock} the engine is using for measuring the execution 614 * time. 615 * 616 * @return the clock used for measuring the execution time 617 */ 618 public Clock getClock() { 619 return _clock; 620 } 621 622 /** 623 * Return the {@link Executor} the engine is using for executing the 624 * evolution steps. 625 * 626 * @return the executor used for performing the evolution steps 627 */ 628 public Executor getExecutor() { 629 return _executor.get(); 630 } 631 632 633 /** 634 * Return the maximal number of attempt before the {@code Engine} gives 635 * up creating a valid individual ({@code Phenotype}). 636 * 637 * @since 4.0 638 * 639 * @return the maximal number of {@code Phenotype} creation attempts 640 */ 641 public int getIndividualCreationRetries() { 642 return _individualCreationRetries; 643 } 644 645 /** 646 * Return the evolution result mapper. 647 * 648 * @since 4.0 649 * 650 * @return the evolution result mapper 651 */ 652 public UnaryOperator<EvolutionResult<G, C>> getMapper() { 653 return _mapper; 654 } 655 656 /* ************************************************************************* 657 * Builder methods. 658 **************************************************************************/ 659 660 /** 661 * Create a new evolution {@code Engine.Builder} initialized with the values 662 * of the current evolution {@code Engine}. With this method, the evolution 663 * engine can serve as a template for a new one. 664 * 665 * @return a new engine builder 666 */ 667 public Builder<G, C> builder() { 668 return new Builder<G, C>(_genotypeFactory, _fitnessFunction) 669 .alterers(_alterer) 670 .clock(_clock) 671 .evaluator(_evaluator) 672 .executor(_executor.get()) 673 .fitnessScaler(_fitnessScaler) 674 .maximalPhenotypeAge(_maximalPhenotypeAge) 675 .offspringFraction((double)_offspringCount/(double)getPopulationSize()) 676 .offspringSelector(_offspringSelector) 677 .optimize(_optimize) 678 .phenotypeValidator(_validator) 679 .populationSize(getPopulationSize()) 680 .survivorsSelector(_survivorsSelector) 681 .individualCreationRetries(_individualCreationRetries) 682 .mapping(_mapper); 683 } 684 685 /** 686 * Create a new evolution {@code Engine.Builder} for the given 687 * {@link Problem}. 688 * 689 * @since 3.4 690 * 691 * @param problem the problem to be solved by the evolution {@code Engine} 692 * @param <T> the (<i>native</i>) argument type of the problem fitness function 693 * @param <G> the gene type the evolution engine is working with 694 * @param <C> the result type of the fitness function 695 * @return Create a new evolution {@code Engine.Builder} 696 */ 697 public static <T, G extends Gene<?, G>, C extends Comparable<? super C>> 698 Builder<G, C> builder(final Problem<T, G, C> problem) { 699 return builder(problem.fitness(), problem.codec()); 700 } 701 702 /** 703 * Create a new evolution {@code Engine.Builder} with the given fitness 704 * function and genotype factory. 705 * 706 * @param ff the fitness function 707 * @param genotypeFactory the genotype factory 708 * @param <G> the gene type 709 * @param <C> the fitness function result type 710 * @return a new engine builder 711 * @throws java.lang.NullPointerException if one of the arguments is 712 * {@code null}. 713 */ 714 public static <G extends Gene<?, G>, C extends Comparable<? super C>> 715 Builder<G, C> builder( 716 final Function<? super Genotype<G>, ? extends C> ff, 717 final Factory<Genotype<G>> genotypeFactory 718 ) { 719 return new Builder<>(genotypeFactory, ff); 720 } 721 722 /** 723 * Create a new evolution {@code Engine.Builder} with the given fitness 724 * function and chromosome templates. 725 * 726 * @param ff the fitness function 727 * @param chromosome the first chromosome 728 * @param chromosomes the chromosome templates 729 * @param <G> the gene type 730 * @param <C> the fitness function result type 731 * @return a new engine builder 732 * @throws java.lang.NullPointerException if one of the arguments is 733 * {@code null}. 734 */ 735 @SafeVarargs 736 public static <G extends Gene<?, G>, C extends Comparable<? super C>> 737 Builder<G, C> builder( 738 final Function<? super Genotype<G>, ? extends C> ff, 739 final Chromosome<G> chromosome, 740 final Chromosome<G>... chromosomes 741 ) { 742 return new Builder<>(Genotype.of(chromosome, chromosomes), ff); 743 } 744 745 /** 746 * Create a new evolution {@code Engine.Builder} with the given fitness 747 * function and problem {@code codec}. 748 * 749 * @since 3.2 750 * 751 * @param ff the fitness function 752 * @param codec the problem codec 753 * @param <T> the fitness function input type 754 * @param <C> the fitness function result type 755 * @param <G> the gene type 756 * @return a new engine builder 757 * @throws java.lang.NullPointerException if one of the arguments is 758 * {@code null}. 759 */ 760 public static <T, G extends Gene<?, G>, C extends Comparable<? super C>> 761 Builder<G, C> builder( 762 final Function<? super T, ? extends C> ff, 763 final Codec<T, G> codec 764 ) { 765 return builder(ff.compose(codec.decoder()), codec.encoding()); 766 } 767 768 769 /* ************************************************************************* 770 * Inner classes 771 **************************************************************************/ 772 773 774 /** 775 * This interface allows to define different strategies for evaluating the 776 * fitness functions of a given population. <em>Normally</em>, there is no 777 * need for <em>overriding</em> the default evaluation strategy, but it might 778 * be necessary if you have performance problems and a <em>batched</em> 779 * fitness evaluation would solve the problem. 780 * <p> 781 * The implementer is free to do the evaluation <em>in place</em>, or create 782 * new {@link Phenotype} instance and return the newly created one. A simple 783 * serial evaluator can easily implemented: 784 * 785 * <pre>{@code 786 * final Evaluator<G, C> evaluator = population -> { 787 * population.forEach(Phenotype::evaluate); 788 * return population.asISeq(); 789 * }; 790 * }</pre> 791 * 792 * @implSpec 793 * The size of the returned, evaluated, phenotype sequence must be exactly 794 * the size of the input phenotype sequence. It is allowed to return the 795 * input sequence, after evaluation, as well a newly created one. 796 * 797 * @apiNote 798 * This interface is an <em>advanced</em> {@code Engine} configuration 799 * feature, which should be only used when there is a performance gain from 800 * implementing a different evaluation strategy. Another use case is, when 801 * the fitness value of an individual also depends on the current composition 802 * of the population. 803 * 804 * @see GenotypeEvaluator 805 * @see Engine.Builder#evaluator(Engine.Evaluator) 806 * 807 * @param <G> the gene type 808 * @param <C> the fitness result type 809 * 810 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 811 * @version 4.2 812 * @since 4.2 813 */ 814 @FunctionalInterface 815 public static interface Evaluator< 816 G extends Gene<?, G>, 817 C extends Comparable<? super C> 818 > { 819 820 /** 821 * Evaluates the fitness values of the given {@code population}. The 822 * given {@code population} might contain already evaluated individuals. 823 * It is the responsibility of the implementer to filter out already 824 * evaluated individuals, if desired. 825 * 826 * @param population the population to evaluate 827 * @return the evaluated population. Implementers are free to return the 828 * the input population or a newly created one. 829 */ 830 public ISeq<Phenotype<G, C>> evaluate(final Seq<Phenotype<G, C>> population); 831 832 /** 833 * Create a new phenotype evaluator from a given genotype {@code evaluator}. 834 * 835 * @implNote 836 * The returned {@link Evaluator} will only forward <em>un</em>-evaluated 837 * individuals to the given genotype {@code evaluator}. This means, that 838 * already evaluated individuals are filtered from the population, which 839 * is then forwarded to the underlying genotype {@code evaluator}. 840 * 841 * @param evaluator the genotype evaluator 842 * @param <G> the gene type 843 * @param <C> the fitness result type 844 * @return a <em>normal</em> phenotype evaluator from the given genotype 845 * evaluator 846 * @throws NullPointerException if the given {@code evaluator} is 847 * {@code null} 848 */ 849 public static <G extends Gene<?, G>, C extends Comparable<? super C>> 850 Evaluator<G, C> of(final GenotypeEvaluator<G, C> evaluator) { 851 requireNonNull(evaluator); 852 853 return population -> { 854 final ISeq<Genotype<G>> genotypes = population.stream() 855 .filter(pt -> !pt.isEvaluated()) 856 .map(Phenotype::getGenotype) 857 .collect(ISeq.toISeq()); 858 859 if (genotypes.nonEmpty()) { 860 final ISeq<C> results = evaluator.evaluate( 861 genotypes, 862 population.get(0).getFitnessFunction() 863 ); 864 865 if (genotypes.size() != results.size()) { 866 throw new IllegalStateException(format( 867 "Expected %d results, but got %d. " + 868 "Check your evaluator function.", 869 genotypes.size(), results.size() 870 )); 871 } 872 873 final MSeq<Phenotype<G, C>> evaluated = population.asMSeq(); 874 for (int i = 0, j = 0; i < evaluated.length(); ++i) { 875 if (!population.get(i).isEvaluated()) { 876 evaluated.set( 877 i, 878 population.get(i).withFitness(results.get(j++)) 879 ); 880 } 881 } 882 883 return evaluated.toISeq(); 884 } else { 885 return population.asISeq(); 886 } 887 }; 888 } 889 890 } 891 892 /** 893 * This interface gives a different possibility in evaluating the fitness 894 * values of a population. Sometimes it is necessary (mostly for performance 895 * reason) to calculate the fitness for the whole population at once. This 896 * interface allows you to do so. A simple serial evaluator can easily 897 * implemented: 898 * 899 * <pre>{@code 900 * final GenotypeEvaluator<G, C> gte = (g, f) -> g.map(f).asISeq() 901 * final Evaluator<G, C> evaluator = Evaluator.of(gte); 902 * }</pre> 903 * 904 * @implSpec 905 * The size of the returned result sequence must be exactly the size of the 906 * input genotype sequence. 907 * 908 * @apiNote 909 * This interface is an <em>advanced</em> {@code Engine} configuration 910 * feature, which should be only used when there is a performance gain from 911 * implementing a different evaluation strategy. 912 * 913 * @see Evaluator 914 * @see Engine.Builder#evaluator(Engine.GenotypeEvaluator) 915 * 916 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 917 * @version 4.2 918 * @since 4.2 919 */ 920 @FunctionalInterface 921 public static interface GenotypeEvaluator< 922 G extends Gene<?, G>, 923 C extends Comparable<? super C> 924 > { 925 926 /** 927 * Calculate the fitness values for the given sequence of genotypes. 928 * 929 * @see Engine.Evaluator#of(Engine.GenotypeEvaluator) 930 * 931 * @param genotypes the genotypes to evaluate the fitness value for 932 * @param function the fitness function 933 * @return the fitness values for the given {@code genotypes} The length 934 * of the fitness result sequence must match with the size of 935 * the given {@code genotypes}. 936 */ 937 public ISeq<C> evaluate( 938 final Seq<Genotype<G>> genotypes, 939 final Function<? super Genotype<G>, ? extends C> function 940 ); 941 942 } 943 944 945 /** 946 * Builder class for building GA {@code Engine} instances. 947 * 948 * @see Engine 949 * 950 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 951 * @since 3.0 952 * @version 4.0 953 */ 954 public static final class Builder< 955 G extends Gene<?, G>, 956 C extends Comparable<? super C> 957 > 958 implements Copyable<Builder<G, C>> 959 { 960 961 // No default values for this properties. 962 private Function<? super Genotype<G>, ? extends C> _fitnessFunction; 963 private Factory<Genotype<G>> _genotypeFactory; 964 965 // This are the properties which default values. 966 private Function<? super C, ? extends C> _fitnessScaler = a -> a; 967 private Selector<G, C> _survivorsSelector = new TournamentSelector<>(3); 968 private Selector<G, C> _offspringSelector = new TournamentSelector<>(3); 969 private Alterer<G, C> _alterer = Alterer.of( 970 new SinglePointCrossover<G, C>(0.2), 971 new Mutator<>(0.15) 972 ); 973 private Predicate<? super Phenotype<G, C>> _validator = Phenotype::isValid; 974 private Optimize _optimize = Optimize.MAXIMUM; 975 private double _offspringFraction = 0.6; 976 private int _populationSize = 50; 977 private long _maximalPhenotypeAge = 70; 978 979 // Engine execution environment. 980 private Executor _executor = ForkJoinPool.commonPool(); 981 private Clock _clock = NanoClock.systemUTC(); 982 private Evaluator<G, C> _evaluator; 983 984 private int _individualCreationRetries = 10; 985 private UnaryOperator<EvolutionResult<G, C>> _mapper = r -> r; 986 987 private Builder( 988 final Factory<Genotype<G>> genotypeFactory, 989 final Function<? super Genotype<G>, ? extends C> fitnessFunction 990 ) { 991 _genotypeFactory = requireNonNull(genotypeFactory); 992 _fitnessFunction = requireNonNull(fitnessFunction); 993 } 994 995 /** 996 * Set the fitness function of the evolution {@code Engine}. 997 * 998 * @param function the fitness function to use in the GA {@code Engine} 999 * @return {@code this} builder, for command chaining 1000 */ 1001 public Builder<G, C> fitnessFunction( 1002 final Function<? super Genotype<G>, ? extends C> function 1003 ) { 1004 _fitnessFunction = requireNonNull(function); 1005 return this; 1006 } 1007 1008 /** 1009 * Set the fitness scaler of the evolution {@code Engine}. <i>Default 1010 * value is set to the identity function.</i> 1011 * 1012 * @param scaler the fitness scale to use in the GA {@code Engine} 1013 * @return {@code this} builder, for command chaining 1014 * 1015 * @deprecated The fitness scaler will be remove in a future version. 1016 */ 1017 @Deprecated 1018 public Builder<G, C> fitnessScaler( 1019 final Function<? super C, ? extends C> scaler 1020 ) { 1021 _fitnessScaler = requireNonNull(scaler); 1022 return this; 1023 } 1024 1025 /** 1026 * The genotype factory used for creating new individuals. 1027 * 1028 * @param genotypeFactory the genotype factory for creating new 1029 * individuals. 1030 * @return {@code this} builder, for command chaining 1031 */ 1032 public Builder<G, C> genotypeFactory( 1033 final Factory<Genotype<G>> genotypeFactory 1034 ) { 1035 _genotypeFactory = requireNonNull(genotypeFactory); 1036 return this; 1037 } 1038 1039 /** 1040 * The selector used for selecting the offspring population. <i>Default 1041 * values is set to {@code TournamentSelector<>(3)}.</i> 1042 * 1043 * @param selector used for selecting the offspring population 1044 * @return {@code this} builder, for command chaining 1045 */ 1046 public Builder<G, C> offspringSelector( 1047 final Selector<G, C> selector 1048 ) { 1049 _offspringSelector = requireNonNull(selector); 1050 return this; 1051 } 1052 1053 /** 1054 * The selector used for selecting the survivors population. <i>Default 1055 * values is set to {@code TournamentSelector<>(3)}.</i> 1056 * 1057 * @param selector used for selecting survivors population 1058 * @return {@code this} builder, for command chaining 1059 */ 1060 public Builder<G, C> survivorsSelector( 1061 final Selector<G, C> selector 1062 ) { 1063 _survivorsSelector = requireNonNull(selector); 1064 return this; 1065 } 1066 1067 /** 1068 * The selector used for selecting the survivors and offspring 1069 * population. <i>Default values is set to 1070 * {@code TournamentSelector<>(3)}.</i> 1071 * 1072 * @param selector used for selecting survivors and offspring population 1073 * @return {@code this} builder, for command chaining 1074 */ 1075 public Builder<G, C> selector(final Selector<G, C> selector) { 1076 _offspringSelector = requireNonNull(selector); 1077 _survivorsSelector = requireNonNull(selector); 1078 return this; 1079 } 1080 1081 /** 1082 * The alterers used for alter the offspring population. <i>Default 1083 * values is set to {@code new SinglePointCrossover<>(0.2)} followed by 1084 * {@code new Mutator<>(0.15)}.</i> 1085 * 1086 * @param first the first alterer used for alter the offspring 1087 * population 1088 * @param rest the rest of the alterers used for alter the offspring 1089 * population 1090 * @return {@code this} builder, for command chaining 1091 * @throws java.lang.NullPointerException if one of the alterers is 1092 * {@code null}. 1093 */ 1094 @SafeVarargs 1095 public final Builder<G, C> alterers( 1096 final Alterer<G, C> first, 1097 final Alterer<G, C>... rest 1098 ) { 1099 requireNonNull(first); 1100 Stream.of(rest).forEach(Objects::requireNonNull); 1101 1102 _alterer = rest.length == 0 1103 ? first 1104 : Alterer.of(rest).compose(first); 1105 1106 return this; 1107 } 1108 1109 /** 1110 * The phenotype validator used for detecting invalid individuals. 1111 * Alternatively it is also possible to set the genotype validator with 1112 * {@link #genotypeFactory(Factory)}, which will replace any 1113 * previously set phenotype validators. 1114 * 1115 * <p><i>Default value is set to {@code Phenotype::isValid}.</i></p> 1116 * 1117 * @since 3.1 1118 * 1119 * @see #genotypeValidator(Predicate) 1120 * 1121 * @param validator the {@code validator} used for validating the 1122 * individuals (phenotypes). 1123 * @return {@code this} builder, for command chaining 1124 * @throws java.lang.NullPointerException if the {@code validator} is 1125 * {@code null}. 1126 */ 1127 public Builder<G, C> phenotypeValidator( 1128 final Predicate<? super Phenotype<G, C>> validator 1129 ) { 1130 _validator = requireNonNull(validator); 1131 return this; 1132 } 1133 1134 /** 1135 * The genotype validator used for detecting invalid individuals. 1136 * Alternatively it is also possible to set the phenotype validator with 1137 * {@link #phenotypeValidator(Predicate)}, which will replace any 1138 * previously set genotype validators. 1139 * 1140 * <p><i>Default value is set to {@code Genotype::isValid}.</i></p> 1141 * 1142 * @since 3.1 1143 * 1144 * @see #phenotypeValidator(Predicate) 1145 * 1146 * @param validator the {@code validator} used for validating the 1147 * individuals (genotypes). 1148 * @return {@code this} builder, for command chaining 1149 * @throws java.lang.NullPointerException if the {@code validator} is 1150 * {@code null}. 1151 */ 1152 public Builder<G, C> genotypeValidator( 1153 final Predicate<? super Genotype<G>> validator 1154 ) { 1155 requireNonNull(validator); 1156 1157 _validator = pt -> validator.test(pt.getGenotype()); 1158 return this; 1159 } 1160 1161 /** 1162 * The optimization strategy used by the engine. <i>Default values is 1163 * set to {@code Optimize.MAXIMUM}.</i> 1164 * 1165 * @param optimize the optimization strategy used by the engine 1166 * @return {@code this} builder, for command chaining 1167 */ 1168 public Builder<G, C> optimize(final Optimize optimize) { 1169 _optimize = requireNonNull(optimize); 1170 return this; 1171 } 1172 1173 /** 1174 * Set to a fitness maximizing strategy. 1175 * 1176 * @since 3.4 1177 * 1178 * @return {@code this} builder, for command chaining 1179 */ 1180 public Builder<G, C> maximizing() { 1181 return optimize(Optimize.MAXIMUM); 1182 } 1183 1184 /** 1185 * Set to a fitness minimizing strategy. 1186 * 1187 * @since 3.4 1188 * 1189 * @return {@code this} builder, for command chaining 1190 */ 1191 public Builder<G, C> minimizing() { 1192 return optimize(Optimize.MINIMUM); 1193 } 1194 1195 /** 1196 * The offspring fraction. <i>Default values is set to {@code 0.6}.</i> 1197 * This method call is equivalent to 1198 * {@code survivorsFraction(1 - offspringFraction)} and will override 1199 * any previously set survivors-fraction. 1200 * 1201 * @see #survivorsFraction(double) 1202 * 1203 * @param fraction the offspring fraction 1204 * @return {@code this} builder, for command chaining 1205 * @throws java.lang.IllegalArgumentException if the fraction is not 1206 * within the range [0, 1]. 1207 */ 1208 public Builder<G, C> offspringFraction(final double fraction) { 1209 _offspringFraction = probability(fraction); 1210 return this; 1211 } 1212 1213 /** 1214 * The survivors fraction. <i>Default values is set to {@code 0.4}.</i> 1215 * This method call is equivalent to 1216 * {@code offspringFraction(1 - survivorsFraction)} and will override 1217 * any previously set offspring-fraction. 1218 * 1219 * @since 3.8 1220 * 1221 * @see #offspringFraction(double) 1222 * 1223 * @param fraction the survivors fraction 1224 * @return {@code this} builder, for command chaining 1225 * @throws java.lang.IllegalArgumentException if the fraction is not 1226 * within the range [0, 1]. 1227 */ 1228 public Builder<G, C> survivorsFraction(final double fraction) { 1229 _offspringFraction = 1.0 - probability(fraction); 1230 return this; 1231 } 1232 1233 /** 1234 * The number of offspring individuals. 1235 * 1236 * @since 3.8 1237 * 1238 * @param size the number of offspring individuals. 1239 * @return {@code this} builder, for command chaining 1240 * @throws java.lang.IllegalArgumentException if the size is not 1241 * within the range [0, population-size]. 1242 */ 1243 public Builder<G, C> offspringSize(final int size) { 1244 if (size < 0) { 1245 throw new IllegalArgumentException(format( 1246 "Offspring size must be greater or equal zero, but was %s.", 1247 size 1248 )); 1249 } 1250 1251 return offspringFraction((double)size/(double)_populationSize); 1252 } 1253 1254 /** 1255 * The number of survivors. 1256 * 1257 * @since 3.8 1258 * 1259 * @param size the number of survivors. 1260 * @return {@code this} builder, for command chaining 1261 * @throws java.lang.IllegalArgumentException if the size is not 1262 * within the range [0, population-size]. 1263 */ 1264 public Builder<G, C> survivorsSize(final int size) { 1265 if (size < 0) { 1266 throw new IllegalArgumentException(format( 1267 "Survivors must be greater or equal zero, but was %s.", 1268 size 1269 )); 1270 } 1271 1272 return survivorsFraction((double)size/(double)_populationSize); 1273 } 1274 1275 /** 1276 * The number of individuals which form the population. <i>Default 1277 * values is set to {@code 50}.</i> 1278 * 1279 * @param size the number of individuals of a population 1280 * @return {@code this} builder, for command chaining 1281 * @throws java.lang.IllegalArgumentException if {@code size < 1} 1282 */ 1283 public Builder<G, C> populationSize(final int size) { 1284 if (size < 1) { 1285 throw new IllegalArgumentException(format( 1286 "Population size must be greater than zero, but was %s.", 1287 size 1288 )); 1289 } 1290 _populationSize = size; 1291 return this; 1292 } 1293 1294 /** 1295 * The maximal allowed age of a phenotype. <i>Default values is set to 1296 * {@code 70}.</i> 1297 * 1298 * @param age the maximal phenotype age 1299 * @return {@code this} builder, for command chaining 1300 * @throws java.lang.IllegalArgumentException if {@code age < 1} 1301 */ 1302 public Builder<G, C> maximalPhenotypeAge(final long age) { 1303 if (age < 1) { 1304 throw new IllegalArgumentException(format( 1305 "Phenotype age must be greater than one, but was %s.", age 1306 )); 1307 } 1308 _maximalPhenotypeAge = age; 1309 return this; 1310 } 1311 1312 /** 1313 * The executor used by the engine. 1314 * 1315 * @param executor the executor used by the engine 1316 * @return {@code this} builder, for command chaining 1317 */ 1318 public Builder<G, C> executor(final Executor executor) { 1319 _executor = requireNonNull(executor); 1320 return this; 1321 } 1322 1323 /** 1324 * The clock used for calculating the execution durations. 1325 * 1326 * @param clock the clock used for calculating the execution durations 1327 * @return {@code this} builder, for command chaining 1328 */ 1329 public Builder<G, C> clock(final Clock clock) { 1330 _clock = requireNonNull(clock); 1331 return this; 1332 } 1333 1334 /** 1335 * The phenotype evaluator allows to change the evaluation strategy. 1336 * By default, the population is evaluated concurrently using the 1337 * defined {@link Executor} implementation. 1338 * 1339 * @apiNote 1340 * This is an <em>advanced</em> {@code Engine} configuration feature, 1341 * which should be only used when there is a performance gain from 1342 * implementing a different evaluation strategy. 1343 * 1344 * @since 4.2 1345 * 1346 * @param evaluator the population evaluation strategy 1347 * @return {@code this} builder, for command chaining 1348 */ 1349 public Builder<G, C> evaluator(final Evaluator<G, C> evaluator) { 1350 _evaluator = requireNonNull(evaluator); 1351 return this; 1352 } 1353 1354 /** 1355 * Setting the <em>genotype</em> evaluator used for evaluating the 1356 * fitness function of the population. 1357 * 1358 * @apiNote 1359 * This is an <em>advanced</em> {@code Engine} configuration feature, 1360 * which should be only used when there is a performance gain from 1361 * implementing a different evaluation strategy. 1362 * 1363 * @since 4.2 1364 * 1365 * @param evaluator the genotype evaluator 1366 * @return {@code this} builder, for command chaining 1367 */ 1368 public Builder<G, C> evaluator(final GenotypeEvaluator<G, C> evaluator) { 1369 _evaluator = Evaluator.of(evaluator); 1370 return this; 1371 } 1372 1373 /** 1374 * The maximal number of attempt before the {@code Engine} gives up 1375 * creating a valid individual ({@code Phenotype}). <i>Default values is 1376 * set to {@code 10}.</i> 1377 * 1378 * @since 3.1 1379 * 1380 * @param retries the maximal retry count 1381 * @throws IllegalArgumentException if the given retry {@code count} is 1382 * smaller than zero. 1383 * @return {@code this} builder, for command chaining 1384 */ 1385 public Builder<G, C> individualCreationRetries(final int retries) { 1386 if (retries < 0) { 1387 throw new IllegalArgumentException(format( 1388 "Retry count must not be negative: %d", 1389 retries 1390 )); 1391 } 1392 _individualCreationRetries = retries; 1393 return this; 1394 } 1395 1396 /** 1397 * The result mapper, which allows to change the evolution result after 1398 * each generation. 1399 * 1400 * @since 4.0 1401 * @see EvolutionResult#toUniquePopulation() 1402 * 1403 * @param mapper the evolution result mapper 1404 * @return {@code this} builder, for command chaining 1405 * @throws NullPointerException if the given {@code resultMapper} is 1406 * {@code null} 1407 */ 1408 public Builder<G, C> mapping( 1409 final Function< 1410 ? super EvolutionResult<G, C>, 1411 EvolutionResult<G, C> 1412 > mapper 1413 ) { 1414 _mapper = requireNonNull(mapper::apply); 1415 return this; 1416 } 1417 1418 /** 1419 * Builds an new {@code Engine} instance from the set properties. 1420 * 1421 * @return an new {@code Engine} instance from the set properties 1422 */ 1423 public Engine<G, C> build() { 1424 return new Engine<>( 1425 _fitnessFunction, 1426 _genotypeFactory, 1427 _fitnessScaler, 1428 _survivorsSelector, 1429 _offspringSelector, 1430 _alterer, 1431 _validator, 1432 _optimize, 1433 getOffspringCount(), 1434 getSurvivorsCount(), 1435 _maximalPhenotypeAge, 1436 _executor, 1437 _evaluator != null 1438 ? _evaluator 1439 : new ConcurrentEvaluator<>(_executor), 1440 _clock, 1441 _individualCreationRetries, 1442 _mapper 1443 ); 1444 } 1445 1446 private int getSurvivorsCount() { 1447 return _populationSize - getOffspringCount(); 1448 } 1449 1450 private int getOffspringCount() { 1451 return (int)round(_offspringFraction*_populationSize); 1452 } 1453 1454 /** 1455 * Return the used {@link Alterer} of the GA. 1456 * 1457 * @return the used {@link Alterer} of the GA. 1458 */ 1459 public Alterer<G, C> getAlterers() { 1460 return _alterer; 1461 } 1462 1463 /** 1464 * Return the {@link Clock} the engine is using for measuring the execution 1465 * time. 1466 * 1467 * @since 3.1 1468 * 1469 * @return the clock used for measuring the execution time 1470 */ 1471 public Clock getClock() { 1472 return _clock; 1473 } 1474 1475 /** 1476 * Return the {@link Executor} the engine is using for executing the 1477 * evolution steps. 1478 * 1479 * @since 3.1 1480 * 1481 * @return the executor used for performing the evolution steps 1482 */ 1483 public Executor getExecutor() { 1484 return _executor; 1485 } 1486 1487 /** 1488 * Return the fitness function of the GA engine. 1489 * 1490 * @since 3.1 1491 * 1492 * @return the fitness function 1493 */ 1494 public Function<? super Genotype<G>, ? extends C> getFitnessFunction() { 1495 return _fitnessFunction; 1496 } 1497 1498 /** 1499 * Return the fitness scaler of the GA engine. 1500 * 1501 * @since 3.1 1502 * 1503 * @return the fitness scaler 1504 * 1505 * @deprecated The fitness scaler will be remove in a future version. 1506 */ 1507 @Deprecated 1508 public Function<? super C, ? extends C> getFitnessScaler() { 1509 return _fitnessScaler; 1510 } 1511 1512 /** 1513 * Return the used genotype {@link Factory} of the GA. The genotype factory 1514 * is used for creating the initial population and new, random individuals 1515 * when needed (as replacement for invalid and/or died genotypes). 1516 * 1517 * @since 3.1 1518 * 1519 * @return the used genotype {@link Factory} of the GA. 1520 */ 1521 public Factory<Genotype<G>> getGenotypeFactory() { 1522 return _genotypeFactory; 1523 } 1524 1525 /** 1526 * Return the maximal allowed phenotype age. 1527 * 1528 * @since 3.1 1529 * 1530 * @return the maximal allowed phenotype age 1531 */ 1532 public long getMaximalPhenotypeAge() { 1533 return _maximalPhenotypeAge; 1534 } 1535 1536 /** 1537 * Return the offspring fraction. 1538 * 1539 * @return the offspring fraction. 1540 */ 1541 public double getOffspringFraction() { 1542 return _offspringFraction; 1543 } 1544 1545 /** 1546 * Return the used offspring {@link Selector} of the GA. 1547 * 1548 * @since 3.1 1549 * 1550 * @return the used offspring {@link Selector} of the GA. 1551 */ 1552 public Selector<G, C> getOffspringSelector() { 1553 return _offspringSelector; 1554 } 1555 1556 /** 1557 * Return the used survivor {@link Selector} of the GA. 1558 * 1559 * @since 3.1 1560 * 1561 * @return the used survivor {@link Selector} of the GA. 1562 */ 1563 public Selector<G, C> getSurvivorsSelector() { 1564 return _survivorsSelector; 1565 } 1566 1567 /** 1568 * Return the optimization strategy. 1569 * 1570 * @since 3.1 1571 * 1572 * @return the optimization strategy 1573 */ 1574 public Optimize getOptimize() { 1575 return _optimize; 1576 } 1577 1578 /** 1579 * Return the number of individuals of a population. 1580 * 1581 * @since 3.1 1582 * 1583 * @return the number of individuals of a population 1584 */ 1585 public int getPopulationSize() { 1586 return _populationSize; 1587 } 1588 1589 /** 1590 * Return the maximal number of attempt before the {@code Engine} gives 1591 * up creating a valid individual ({@code Phenotype}). 1592 * 1593 * @since 3.1 1594 * 1595 * @return the maximal number of {@code Phenotype} creation attempts 1596 */ 1597 public int getIndividualCreationRetries() { 1598 return _individualCreationRetries; 1599 } 1600 1601 /** 1602 * Return the evolution result mapper. 1603 * 1604 * @since 4.0 1605 * 1606 * @return the evolution result mapper 1607 */ 1608 public UnaryOperator<EvolutionResult<G, C>> getMapper() { 1609 return _mapper; 1610 } 1611 1612 /** 1613 * Create a new builder, with the current configuration. 1614 * 1615 * @since 3.1 1616 * 1617 * @return a new builder, with the current configuration 1618 */ 1619 @Override 1620 public Builder<G, C> copy() { 1621 return new Builder<G, C>(_genotypeFactory, _fitnessFunction) 1622 .alterers(_alterer) 1623 .clock(_clock) 1624 .executor(_executor) 1625 .evaluator(_evaluator) 1626 .fitnessScaler(_fitnessScaler) 1627 .maximalPhenotypeAge(_maximalPhenotypeAge) 1628 .offspringFraction(_offspringFraction) 1629 .offspringSelector(_offspringSelector) 1630 .phenotypeValidator(_validator) 1631 .optimize(_optimize) 1632 .populationSize(_populationSize) 1633 .survivorsSelector(_survivorsSelector) 1634 .individualCreationRetries(_individualCreationRetries) 1635 .mapping(_mapper); 1636 } 1637 1638 } 1639 1640}