001/* 002 * Java Genetic Algorithm Library (jenetics-4.2.0). 003 * Copyright (c) 2007-2018 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 public Function<? super C, ? extends C> getFitnessScaler() { 523 return _fitnessScaler; 524 } 525 526 /** 527 * Return the used genotype {@link Factory} of the GA. The genotype factory 528 * is used for creating the initial population and new, random individuals 529 * when needed (as replacement for invalid and/or died genotypes). 530 * 531 * @return the used genotype {@link Factory} of the GA. 532 */ 533 public Factory<Genotype<G>> getGenotypeFactory() { 534 return _genotypeFactory; 535 } 536 537 /** 538 * Return the used survivor {@link Selector} of the GA. 539 * 540 * @return the used survivor {@link Selector} of the GA. 541 */ 542 public Selector<G, C> getSurvivorsSelector() { 543 return _survivorsSelector; 544 } 545 546 /** 547 * Return the used offspring {@link Selector} of the GA. 548 * 549 * @return the used offspring {@link Selector} of the GA. 550 */ 551 public Selector<G, C> getOffspringSelector() { 552 return _offspringSelector; 553 } 554 555 /** 556 * Return the used {@link Alterer} of the GA. 557 * 558 * @return the used {@link Alterer} of the GA. 559 */ 560 public Alterer<G, C> getAlterer() { 561 return _alterer; 562 } 563 564 /** 565 * Return the number of selected offsprings. 566 * 567 * @return the number of selected offsprings 568 */ 569 public int getOffspringCount() { 570 return _offspringCount; 571 } 572 573 /** 574 * The number of selected survivors. 575 * 576 * @return the number of selected survivors 577 */ 578 public int getSurvivorsCount() { 579 return _survivorsCount; 580 } 581 582 /** 583 * Return the number of individuals of a population. 584 * 585 * @return the number of individuals of a population 586 */ 587 public int getPopulationSize() { 588 return _offspringCount + _survivorsCount; 589 } 590 591 /** 592 * Return the maximal allowed phenotype age. 593 * 594 * @return the maximal allowed phenotype age 595 */ 596 public long getMaximalPhenotypeAge() { 597 return _maximalPhenotypeAge; 598 } 599 600 /** 601 * Return the optimization strategy. 602 * 603 * @return the optimization strategy 604 */ 605 public Optimize getOptimize() { 606 return _optimize; 607 } 608 609 /** 610 * Return the {@link Clock} the engine is using for measuring the execution 611 * time. 612 * 613 * @return the clock used for measuring the execution time 614 */ 615 public Clock getClock() { 616 return _clock; 617 } 618 619 /** 620 * Return the {@link Executor} the engine is using for executing the 621 * evolution steps. 622 * 623 * @return the executor used for performing the evolution steps 624 */ 625 public Executor getExecutor() { 626 return _executor.get(); 627 } 628 629 630 /** 631 * Return the maximal number of attempt before the {@code Engine} gives 632 * up creating a valid individual ({@code Phenotype}). 633 * 634 * @since 4.0 635 * 636 * @return the maximal number of {@code Phenotype} creation attempts 637 */ 638 public int getIndividualCreationRetries() { 639 return _individualCreationRetries; 640 } 641 642 /** 643 * Return the evolution result mapper. 644 * 645 * @since 4.0 646 * 647 * @return the evolution result mapper 648 */ 649 public UnaryOperator<EvolutionResult<G, C>> getMapper() { 650 return _mapper; 651 } 652 653 /* ************************************************************************* 654 * Builder methods. 655 **************************************************************************/ 656 657 /** 658 * Create a new evolution {@code Engine.Builder} initialized with the values 659 * of the current evolution {@code Engine}. With this method, the evolution 660 * engine can serve as a template for a new one. 661 * 662 * @return a new engine builder 663 */ 664 public Builder<G, C> builder() { 665 return new Builder<G, C>(_genotypeFactory, _fitnessFunction) 666 .alterers(_alterer) 667 .clock(_clock) 668 .evaluator(_evaluator) 669 .executor(_executor.get()) 670 .fitnessScaler(_fitnessScaler) 671 .maximalPhenotypeAge(_maximalPhenotypeAge) 672 .offspringFraction((double)_offspringCount/(double)getPopulationSize()) 673 .offspringSelector(_offspringSelector) 674 .optimize(_optimize) 675 .phenotypeValidator(_validator) 676 .populationSize(getPopulationSize()) 677 .survivorsSelector(_survivorsSelector) 678 .individualCreationRetries(_individualCreationRetries) 679 .mapping(_mapper); 680 } 681 682 /** 683 * Create a new evolution {@code Engine.Builder} for the given 684 * {@link Problem}. 685 * 686 * @since 3.4 687 * 688 * @param problem the problem to be solved by the evolution {@code Engine} 689 * @param <T> the (<i>native</i>) argument type of the problem fitness function 690 * @param <G> the gene type the evolution engine is working with 691 * @param <C> the result type of the fitness function 692 * @return Create a new evolution {@code Engine.Builder} 693 */ 694 public static <T, G extends Gene<?, G>, C extends Comparable<? super C>> 695 Builder<G, C> builder(final Problem<T, G, C> problem) { 696 return builder(problem.fitness(), problem.codec()); 697 } 698 699 /** 700 * Create a new evolution {@code Engine.Builder} with the given fitness 701 * function and genotype factory. 702 * 703 * @param ff the fitness function 704 * @param genotypeFactory the genotype factory 705 * @param <G> the gene type 706 * @param <C> the fitness function result type 707 * @return a new engine builder 708 * @throws java.lang.NullPointerException if one of the arguments is 709 * {@code null}. 710 */ 711 public static <G extends Gene<?, G>, C extends Comparable<? super C>> 712 Builder<G, C> builder( 713 final Function<? super Genotype<G>, ? extends C> ff, 714 final Factory<Genotype<G>> genotypeFactory 715 ) { 716 return new Builder<>(genotypeFactory, ff); 717 } 718 719 /** 720 * Create a new evolution {@code Engine.Builder} with the given fitness 721 * function and chromosome templates. 722 * 723 * @param ff the fitness function 724 * @param chromosome the first chromosome 725 * @param chromosomes the chromosome templates 726 * @param <G> the gene type 727 * @param <C> the fitness function result type 728 * @return a new engine builder 729 * @throws java.lang.NullPointerException if one of the arguments is 730 * {@code null}. 731 */ 732 @SafeVarargs 733 public static <G extends Gene<?, G>, C extends Comparable<? super C>> 734 Builder<G, C> builder( 735 final Function<? super Genotype<G>, ? extends C> ff, 736 final Chromosome<G> chromosome, 737 final Chromosome<G>... chromosomes 738 ) { 739 return new Builder<>(Genotype.of(chromosome, chromosomes), ff); 740 } 741 742 /** 743 * Create a new evolution {@code Engine.Builder} with the given fitness 744 * function and problem {@code codec}. 745 * 746 * @since 3.2 747 * 748 * @param ff the fitness function 749 * @param codec the problem codec 750 * @param <T> the fitness function input type 751 * @param <C> the fitness function result type 752 * @param <G> the gene type 753 * @return a new engine builder 754 * @throws java.lang.NullPointerException if one of the arguments is 755 * {@code null}. 756 */ 757 public static <T, G extends Gene<?, G>, C extends Comparable<? super C>> 758 Builder<G, C> builder( 759 final Function<? super T, ? extends C> ff, 760 final Codec<T, G> codec 761 ) { 762 return builder(ff.compose(codec.decoder()), codec.encoding()); 763 } 764 765 766 /* ************************************************************************* 767 * Inner classes 768 **************************************************************************/ 769 770 771 /** 772 * This interface allows to define different strategies for evaluating the 773 * fitness functions of a given population. <em>Normally</em>, there is no 774 * need for <em>overriding</em> the default evaluation strategy, but it might 775 * be necessary if you have performance problems and a <em>batched</em> 776 * fitness evaluation would solve the problem. 777 * <p> 778 * The implementer is free to do the evaluation <em>in place</em>, or create 779 * new {@link Phenotype} instance and return the newly created one. A simple 780 * serial evaluator can easily implemented: 781 * 782 * <pre>{@code 783 * final Evaluator<G, C> evaluator = population -> { 784 * population.forEach(Phenotype::evaluate); 785 * return population.asISeq(); 786 * }; 787 * }</pre> 788 * 789 * @implSpec 790 * The size of the returned, evaluated, phenotype sequence must be exactly 791 * the size of the input phenotype sequence. It is allowed to return the 792 * input sequence, after evaluation, as well a newly created one. 793 * 794 * @apiNote 795 * This interface is an <em>advanced</em> {@code Engine} configuration 796 * feature, which should be only used when there is a performance gain from 797 * implementing a different evaluation strategy. Another use case is, when 798 * the fitness value of an individual also depends on the current composition 799 * of the population. 800 * 801 * @see GenotypeEvaluator 802 * @see Engine.Builder#evaluator(Engine.Evaluator) 803 * 804 * @param <G> the gene type 805 * @param <C> the fitness result type 806 * 807 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 808 * @version 4.2 809 * @since 4.2 810 */ 811 @FunctionalInterface 812 public static interface Evaluator< 813 G extends Gene<?, G>, 814 C extends Comparable<? super C> 815 > { 816 817 /** 818 * Evaluates the fitness values of the given {@code population}. The 819 * given {@code population} might contain already evaluated individuals. 820 * It is the responsibility of the implementer to filter out already 821 * evaluated individuals, if desired. 822 * 823 * @param population the population to evaluate 824 * @return the evaluated population. Implementers are free to return the 825 * the input population or a newly created one. 826 */ 827 public ISeq<Phenotype<G, C>> evaluate(final Seq<Phenotype<G, C>> population); 828 829 /** 830 * Create a new phenotype evaluator from a given genotype {@code evaluator}. 831 * 832 * @implNote 833 * The returned {@link Evaluator} will only forward <em>un</em>-evaluated 834 * individuals to the given genotype {@code evaluator}. This means, that 835 * already evaluated individuals are filtered from the population, which 836 * is then forwarded to the underlying genotype {@code evaluator}. 837 * 838 * @param evaluator the genotype evaluator 839 * @param <G> the gene type 840 * @param <C> the fitness result type 841 * @return a <em>normal</em> phenotype evaluator from the given genotype 842 * evaluator 843 * @throws NullPointerException if the given {@code evaluator} is 844 * {@code null} 845 */ 846 public static <G extends Gene<?, G>, C extends Comparable<? super C>> 847 Evaluator<G, C> of(final GenotypeEvaluator<G, C> evaluator) { 848 requireNonNull(evaluator); 849 850 return population -> { 851 final ISeq<Genotype<G>> genotypes = population.stream() 852 .filter(pt -> !pt.isEvaluated()) 853 .map(Phenotype::getGenotype) 854 .collect(ISeq.toISeq()); 855 856 if (genotypes.nonEmpty()) { 857 final ISeq<C> results = evaluator.evaluate( 858 genotypes, 859 population.get(0).getFitnessFunction() 860 ); 861 862 if (genotypes.size() != results.size()) { 863 throw new IllegalStateException(format( 864 "Expected %d results, but got %d. " + 865 "Check your evaluator function.", 866 genotypes.size(), results.size() 867 )); 868 } 869 870 final MSeq<Phenotype<G, C>> evaluated = population.asMSeq(); 871 for (int i = 0, j = 0; i < evaluated.length(); ++i) { 872 if (!population.get(i).isEvaluated()) { 873 evaluated.set( 874 i, 875 population.get(i).withFitness(results.get(j++)) 876 ); 877 } 878 } 879 880 return evaluated.toISeq(); 881 } else { 882 return population.asISeq(); 883 } 884 }; 885 } 886 887 } 888 889 /** 890 * This interface gives a different possibility in evaluating the fitness 891 * values of a population. Sometimes it is necessary (mostly for performance 892 * reason) to calculate the fitness for the whole population at once. This 893 * interface allows you to do so. A simple serial evaluator can easily 894 * implemented: 895 * 896 * <pre>{@code 897 * final GenotypeEvaluator<G, C> gte = (g, f) -> g.map(f).asISeq() 898 * final Evaluator<G, C> evaluator = Evaluator.of(gte); 899 * }</pre> 900 * 901 * @implSpec 902 * The size of the returned result sequence must be exactly the size of the 903 * input genotype sequence. 904 * 905 * @apiNote 906 * This interface is an <em>advanced</em> {@code Engine} configuration 907 * feature, which should be only used when there is a performance gain from 908 * implementing a different evaluation strategy. 909 * 910 * @see Evaluator 911 * @see Engine.Builder#evaluator(Engine.GenotypeEvaluator) 912 * 913 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 914 * @version 4.2 915 * @since 4.2 916 */ 917 @FunctionalInterface 918 public static interface GenotypeEvaluator< 919 G extends Gene<?, G>, 920 C extends Comparable<? super C> 921 > { 922 923 /** 924 * Calculate the fitness values for the given sequence of genotypes. 925 * 926 * @see Engine.Evaluator#of(Engine.GenotypeEvaluator) 927 * 928 * @param genotypes the genotypes to evaluate the fitness value for 929 * @param function the fitness function 930 * @return the fitness values for the given {@code genotypes} The length 931 * of the fitness result sequence must match with the size of 932 * the given {@code genotypes}. 933 */ 934 public ISeq<C> evaluate( 935 final Seq<Genotype<G>> genotypes, 936 final Function<? super Genotype<G>, ? extends C> function 937 ); 938 939 } 940 941 942 /** 943 * Builder class for building GA {@code Engine} instances. 944 * 945 * @see Engine 946 * 947 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 948 * @since 3.0 949 * @version 4.0 950 */ 951 public static final class Builder< 952 G extends Gene<?, G>, 953 C extends Comparable<? super C> 954 > 955 implements Copyable<Builder<G, C>> 956 { 957 958 // No default values for this properties. 959 private Function<? super Genotype<G>, ? extends C> _fitnessFunction; 960 private Factory<Genotype<G>> _genotypeFactory; 961 962 // This are the properties which default values. 963 private Function<? super C, ? extends C> _fitnessScaler = a -> a; 964 private Selector<G, C> _survivorsSelector = new TournamentSelector<>(3); 965 private Selector<G, C> _offspringSelector = new TournamentSelector<>(3); 966 private Alterer<G, C> _alterer = Alterer.of( 967 new SinglePointCrossover<G, C>(0.2), 968 new Mutator<>(0.15) 969 ); 970 private Predicate<? super Phenotype<G, C>> _validator = Phenotype::isValid; 971 private Optimize _optimize = Optimize.MAXIMUM; 972 private double _offspringFraction = 0.6; 973 private int _populationSize = 50; 974 private long _maximalPhenotypeAge = 70; 975 976 // Engine execution environment. 977 private Executor _executor = ForkJoinPool.commonPool(); 978 private Clock _clock = NanoClock.systemUTC(); 979 private Evaluator<G, C> _evaluator; 980 981 private int _individualCreationRetries = 10; 982 private UnaryOperator<EvolutionResult<G, C>> _mapper = r -> r; 983 984 private Builder( 985 final Factory<Genotype<G>> genotypeFactory, 986 final Function<? super Genotype<G>, ? extends C> fitnessFunction 987 ) { 988 _genotypeFactory = requireNonNull(genotypeFactory); 989 _fitnessFunction = requireNonNull(fitnessFunction); 990 } 991 992 /** 993 * Set the fitness function of the evolution {@code Engine}. 994 * 995 * @param function the fitness function to use in the GA {@code Engine} 996 * @return {@code this} builder, for command chaining 997 */ 998 public Builder<G, C> fitnessFunction( 999 final Function<? super Genotype<G>, ? extends C> function 1000 ) { 1001 _fitnessFunction = requireNonNull(function); 1002 return this; 1003 } 1004 1005 /** 1006 * Set the fitness scaler of the evolution {@code Engine}. <i>Default 1007 * value is set to the identity function.</i> 1008 * 1009 * @param scaler the fitness scale to use in the GA {@code Engine} 1010 * @return {@code this} builder, for command chaining 1011 */ 1012 public Builder<G, C> fitnessScaler( 1013 final Function<? super C, ? extends C> scaler 1014 ) { 1015 _fitnessScaler = requireNonNull(scaler); 1016 return this; 1017 } 1018 1019 /** 1020 * The genotype factory used for creating new individuals. 1021 * 1022 * @param genotypeFactory the genotype factory for creating new 1023 * individuals. 1024 * @return {@code this} builder, for command chaining 1025 */ 1026 public Builder<G, C> genotypeFactory( 1027 final Factory<Genotype<G>> genotypeFactory 1028 ) { 1029 _genotypeFactory = requireNonNull(genotypeFactory); 1030 return this; 1031 } 1032 1033 /** 1034 * The selector used for selecting the offspring population. <i>Default 1035 * values is set to {@code TournamentSelector<>(3)}.</i> 1036 * 1037 * @param selector used for selecting the offspring population 1038 * @return {@code this} builder, for command chaining 1039 */ 1040 public Builder<G, C> offspringSelector( 1041 final Selector<G, C> selector 1042 ) { 1043 _offspringSelector = requireNonNull(selector); 1044 return this; 1045 } 1046 1047 /** 1048 * The selector used for selecting the survivors population. <i>Default 1049 * values is set to {@code TournamentSelector<>(3)}.</i> 1050 * 1051 * @param selector used for selecting survivors population 1052 * @return {@code this} builder, for command chaining 1053 */ 1054 public Builder<G, C> survivorsSelector( 1055 final Selector<G, C> selector 1056 ) { 1057 _survivorsSelector = requireNonNull(selector); 1058 return this; 1059 } 1060 1061 /** 1062 * The selector used for selecting the survivors and offspring 1063 * population. <i>Default values is set to 1064 * {@code TournamentSelector<>(3)}.</i> 1065 * 1066 * @param selector used for selecting survivors and offspring population 1067 * @return {@code this} builder, for command chaining 1068 */ 1069 public Builder<G, C> selector(final Selector<G, C> selector) { 1070 _offspringSelector = requireNonNull(selector); 1071 _survivorsSelector = requireNonNull(selector); 1072 return this; 1073 } 1074 1075 /** 1076 * The alterers used for alter the offspring population. <i>Default 1077 * values is set to {@code new SinglePointCrossover<>(0.2)} followed by 1078 * {@code new Mutator<>(0.15)}.</i> 1079 * 1080 * @param first the first alterer used for alter the offspring 1081 * population 1082 * @param rest the rest of the alterers used for alter the offspring 1083 * population 1084 * @return {@code this} builder, for command chaining 1085 * @throws java.lang.NullPointerException if one of the alterers is 1086 * {@code null}. 1087 */ 1088 @SafeVarargs 1089 public final Builder<G, C> alterers( 1090 final Alterer<G, C> first, 1091 final Alterer<G, C>... rest 1092 ) { 1093 requireNonNull(first); 1094 Stream.of(rest).forEach(Objects::requireNonNull); 1095 1096 _alterer = rest.length == 0 1097 ? first 1098 : Alterer.of(rest).compose(first); 1099 1100 return this; 1101 } 1102 1103 /** 1104 * The phenotype validator used for detecting invalid individuals. 1105 * Alternatively it is also possible to set the genotype validator with 1106 * {@link #genotypeFactory(Factory)}, which will replace any 1107 * previously set phenotype validators. 1108 * 1109 * <p><i>Default value is set to {@code Phenotype::isValid}.</i></p> 1110 * 1111 * @since 3.1 1112 * 1113 * @see #genotypeValidator(Predicate) 1114 * 1115 * @param validator the {@code validator} used for validating the 1116 * individuals (phenotypes). 1117 * @return {@code this} builder, for command chaining 1118 * @throws java.lang.NullPointerException if the {@code validator} is 1119 * {@code null}. 1120 */ 1121 public Builder<G, C> phenotypeValidator( 1122 final Predicate<? super Phenotype<G, C>> validator 1123 ) { 1124 _validator = requireNonNull(validator); 1125 return this; 1126 } 1127 1128 /** 1129 * The genotype validator used for detecting invalid individuals. 1130 * Alternatively it is also possible to set the phenotype validator with 1131 * {@link #phenotypeValidator(Predicate)}, which will replace any 1132 * previously set genotype validators. 1133 * 1134 * <p><i>Default value is set to {@code Genotype::isValid}.</i></p> 1135 * 1136 * @since 3.1 1137 * 1138 * @see #phenotypeValidator(Predicate) 1139 * 1140 * @param validator the {@code validator} used for validating the 1141 * individuals (genotypes). 1142 * @return {@code this} builder, for command chaining 1143 * @throws java.lang.NullPointerException if the {@code validator} is 1144 * {@code null}. 1145 */ 1146 public Builder<G, C> genotypeValidator( 1147 final Predicate<? super Genotype<G>> validator 1148 ) { 1149 requireNonNull(validator); 1150 1151 _validator = pt -> validator.test(pt.getGenotype()); 1152 return this; 1153 } 1154 1155 /** 1156 * The optimization strategy used by the engine. <i>Default values is 1157 * set to {@code Optimize.MAXIMUM}.</i> 1158 * 1159 * @param optimize the optimization strategy used by the engine 1160 * @return {@code this} builder, for command chaining 1161 */ 1162 public Builder<G, C> optimize(final Optimize optimize) { 1163 _optimize = requireNonNull(optimize); 1164 return this; 1165 } 1166 1167 /** 1168 * Set to a fitness maximizing strategy. 1169 * 1170 * @since 3.4 1171 * 1172 * @return {@code this} builder, for command chaining 1173 */ 1174 public Builder<G, C> maximizing() { 1175 return optimize(Optimize.MAXIMUM); 1176 } 1177 1178 /** 1179 * Set to a fitness minimizing strategy. 1180 * 1181 * @since 3.4 1182 * 1183 * @return {@code this} builder, for command chaining 1184 */ 1185 public Builder<G, C> minimizing() { 1186 return optimize(Optimize.MINIMUM); 1187 } 1188 1189 /** 1190 * The offspring fraction. <i>Default values is set to {@code 0.6}.</i> 1191 * This method call is equivalent to 1192 * {@code survivorsFraction(1 - offspringFraction)} and will override 1193 * any previously set survivors-fraction. 1194 * 1195 * @see #survivorsFraction(double) 1196 * 1197 * @param fraction the offspring fraction 1198 * @return {@code this} builder, for command chaining 1199 * @throws java.lang.IllegalArgumentException if the fraction is not 1200 * within the range [0, 1]. 1201 */ 1202 public Builder<G, C> offspringFraction(final double fraction) { 1203 _offspringFraction = probability(fraction); 1204 return this; 1205 } 1206 1207 /** 1208 * The survivors fraction. <i>Default values is set to {@code 0.4}.</i> 1209 * This method call is equivalent to 1210 * {@code offspringFraction(1 - survivorsFraction)} and will override 1211 * any previously set offspring-fraction. 1212 * 1213 * @since 3.8 1214 * 1215 * @see #offspringFraction(double) 1216 * 1217 * @param fraction the survivors fraction 1218 * @return {@code this} builder, for command chaining 1219 * @throws java.lang.IllegalArgumentException if the fraction is not 1220 * within the range [0, 1]. 1221 */ 1222 public Builder<G, C> survivorsFraction(final double fraction) { 1223 _offspringFraction = 1.0 - probability(fraction); 1224 return this; 1225 } 1226 1227 /** 1228 * The number of offspring individuals. 1229 * 1230 * @since 3.8 1231 * 1232 * @param size the number of offspring individuals. 1233 * @return {@code this} builder, for command chaining 1234 * @throws java.lang.IllegalArgumentException if the size is not 1235 * within the range [0, population-size]. 1236 */ 1237 public Builder<G, C> offspringSize(final int size) { 1238 if (size < 0) { 1239 throw new IllegalArgumentException(format( 1240 "Offspring size must be greater or equal zero, but was %s.", 1241 size 1242 )); 1243 } 1244 1245 return offspringFraction((double)size/(double)_populationSize); 1246 } 1247 1248 /** 1249 * The number of survivors. 1250 * 1251 * @since 3.8 1252 * 1253 * @param size the number of survivors. 1254 * @return {@code this} builder, for command chaining 1255 * @throws java.lang.IllegalArgumentException if the size is not 1256 * within the range [0, population-size]. 1257 */ 1258 public Builder<G, C> survivorsSize(final int size) { 1259 if (size < 0) { 1260 throw new IllegalArgumentException(format( 1261 "Survivors must be greater or equal zero, but was %s.", 1262 size 1263 )); 1264 } 1265 1266 return survivorsFraction((double)size/(double)_populationSize); 1267 } 1268 1269 /** 1270 * The number of individuals which form the population. <i>Default 1271 * values is set to {@code 50}.</i> 1272 * 1273 * @param size the number of individuals of a population 1274 * @return {@code this} builder, for command chaining 1275 * @throws java.lang.IllegalArgumentException if {@code size < 1} 1276 */ 1277 public Builder<G, C> populationSize(final int size) { 1278 if (size < 1) { 1279 throw new IllegalArgumentException(format( 1280 "Population size must be greater than zero, but was %s.", 1281 size 1282 )); 1283 } 1284 _populationSize = size; 1285 return this; 1286 } 1287 1288 /** 1289 * The maximal allowed age of a phenotype. <i>Default values is set to 1290 * {@code 70}.</i> 1291 * 1292 * @param age the maximal phenotype age 1293 * @return {@code this} builder, for command chaining 1294 * @throws java.lang.IllegalArgumentException if {@code age < 1} 1295 */ 1296 public Builder<G, C> maximalPhenotypeAge(final long age) { 1297 if (age < 1) { 1298 throw new IllegalArgumentException(format( 1299 "Phenotype age must be greater than one, but was %s.", age 1300 )); 1301 } 1302 _maximalPhenotypeAge = age; 1303 return this; 1304 } 1305 1306 /** 1307 * The executor used by the engine. 1308 * 1309 * @param executor the executor used by the engine 1310 * @return {@code this} builder, for command chaining 1311 */ 1312 public Builder<G, C> executor(final Executor executor) { 1313 _executor = requireNonNull(executor); 1314 return this; 1315 } 1316 1317 /** 1318 * The clock used for calculating the execution durations. 1319 * 1320 * @param clock the clock used for calculating the execution durations 1321 * @return {@code this} builder, for command chaining 1322 */ 1323 public Builder<G, C> clock(final Clock clock) { 1324 _clock = requireNonNull(clock); 1325 return this; 1326 } 1327 1328 /** 1329 * The phenotype evaluator allows to change the evaluation strategy. 1330 * By default, the population is evaluated concurrently using the 1331 * defined {@link Executor} implementation. 1332 * 1333 * @apiNote 1334 * This is an <em>advanced</em> {@code Engine} configuration feature, 1335 * which should be only used when there is a performance gain from 1336 * implementing a different evaluation strategy. 1337 * 1338 * @since 4.2 1339 * 1340 * @param evaluator the population evaluation strategy 1341 * @return {@code this} builder, for command chaining 1342 */ 1343 public Builder<G, C> evaluator(final Evaluator<G, C> evaluator) { 1344 _evaluator = requireNonNull(evaluator); 1345 return this; 1346 } 1347 1348 /** 1349 * Setting the <em>genotype</em> evaluator used for evaluating the 1350 * fitness function of the population. 1351 * 1352 * @apiNote 1353 * This is an <em>advanced</em> {@code Engine} configuration feature, 1354 * which should be only used when there is a performance gain from 1355 * implementing a different evaluation strategy. 1356 * 1357 * @since 4.2 1358 * 1359 * @param evaluator the genotype evaluator 1360 * @return {@code this} builder, for command chaining 1361 */ 1362 public Builder<G, C> evaluator(final GenotypeEvaluator<G, C> evaluator) { 1363 _evaluator = Evaluator.of(evaluator); 1364 return this; 1365 } 1366 1367 /** 1368 * The maximal number of attempt before the {@code Engine} gives up 1369 * creating a valid individual ({@code Phenotype}). <i>Default values is 1370 * set to {@code 10}.</i> 1371 * 1372 * @since 3.1 1373 * 1374 * @param retries the maximal retry count 1375 * @throws IllegalArgumentException if the given retry {@code count} is 1376 * smaller than zero. 1377 * @return {@code this} builder, for command chaining 1378 */ 1379 public Builder<G, C> individualCreationRetries(final int retries) { 1380 if (retries < 0) { 1381 throw new IllegalArgumentException(format( 1382 "Retry count must not be negative: %d", 1383 retries 1384 )); 1385 } 1386 _individualCreationRetries = retries; 1387 return this; 1388 } 1389 1390 /** 1391 * The result mapper, which allows to change the evolution result after 1392 * each generation. 1393 * 1394 * @since 4.0 1395 * @see EvolutionResult#toUniquePopulation() 1396 * 1397 * @param mapper the evolution result mapper 1398 * @return {@code this} builder, for command chaining 1399 * @throws NullPointerException if the given {@code resultMapper} is 1400 * {@code null} 1401 */ 1402 public Builder<G, C> mapping( 1403 final Function< 1404 ? super EvolutionResult<G, C>, 1405 EvolutionResult<G, C> 1406 > mapper 1407 ) { 1408 _mapper = requireNonNull(mapper::apply); 1409 return this; 1410 } 1411 1412 /** 1413 * Builds an new {@code Engine} instance from the set properties. 1414 * 1415 * @return an new {@code Engine} instance from the set properties 1416 */ 1417 public Engine<G, C> build() { 1418 return new Engine<>( 1419 _fitnessFunction, 1420 _genotypeFactory, 1421 _fitnessScaler, 1422 _survivorsSelector, 1423 _offspringSelector, 1424 _alterer, 1425 _validator, 1426 _optimize, 1427 getOffspringCount(), 1428 getSurvivorsCount(), 1429 _maximalPhenotypeAge, 1430 _executor, 1431 _evaluator != null 1432 ? _evaluator 1433 : new ConcurrentEvaluator<>(_executor), 1434 _clock, 1435 _individualCreationRetries, 1436 _mapper 1437 ); 1438 } 1439 1440 private int getSurvivorsCount() { 1441 return _populationSize - getOffspringCount(); 1442 } 1443 1444 private int getOffspringCount() { 1445 return (int)round(_offspringFraction*_populationSize); 1446 } 1447 1448 /** 1449 * Return the used {@link Alterer} of the GA. 1450 * 1451 * @return the used {@link Alterer} of the GA. 1452 */ 1453 public Alterer<G, C> getAlterers() { 1454 return _alterer; 1455 } 1456 1457 /** 1458 * Return the {@link Clock} the engine is using for measuring the execution 1459 * time. 1460 * 1461 * @since 3.1 1462 * 1463 * @return the clock used for measuring the execution time 1464 */ 1465 public Clock getClock() { 1466 return _clock; 1467 } 1468 1469 /** 1470 * Return the {@link Executor} the engine is using for executing the 1471 * evolution steps. 1472 * 1473 * @since 3.1 1474 * 1475 * @return the executor used for performing the evolution steps 1476 */ 1477 public Executor getExecutor() { 1478 return _executor; 1479 } 1480 1481 /** 1482 * Return the fitness function of the GA engine. 1483 * 1484 * @since 3.1 1485 * 1486 * @return the fitness function 1487 */ 1488 public Function<? super Genotype<G>, ? extends C> getFitnessFunction() { 1489 return _fitnessFunction; 1490 } 1491 1492 /** 1493 * Return the fitness scaler of the GA engine. 1494 * 1495 * @since 3.1 1496 * 1497 * @return the fitness scaler 1498 */ 1499 public Function<? super C, ? extends C> getFitnessScaler() { 1500 return _fitnessScaler; 1501 } 1502 1503 /** 1504 * Return the used genotype {@link Factory} of the GA. The genotype factory 1505 * is used for creating the initial population and new, random individuals 1506 * when needed (as replacement for invalid and/or died genotypes). 1507 * 1508 * @since 3.1 1509 * 1510 * @return the used genotype {@link Factory} of the GA. 1511 */ 1512 public Factory<Genotype<G>> getGenotypeFactory() { 1513 return _genotypeFactory; 1514 } 1515 1516 /** 1517 * Return the maximal allowed phenotype age. 1518 * 1519 * @since 3.1 1520 * 1521 * @return the maximal allowed phenotype age 1522 */ 1523 public long getMaximalPhenotypeAge() { 1524 return _maximalPhenotypeAge; 1525 } 1526 1527 /** 1528 * Return the offspring fraction. 1529 * 1530 * @return the offspring fraction. 1531 */ 1532 public double getOffspringFraction() { 1533 return _offspringFraction; 1534 } 1535 1536 /** 1537 * Return the used offspring {@link Selector} of the GA. 1538 * 1539 * @since 3.1 1540 * 1541 * @return the used offspring {@link Selector} of the GA. 1542 */ 1543 public Selector<G, C> getOffspringSelector() { 1544 return _offspringSelector; 1545 } 1546 1547 /** 1548 * Return the used survivor {@link Selector} of the GA. 1549 * 1550 * @since 3.1 1551 * 1552 * @return the used survivor {@link Selector} of the GA. 1553 */ 1554 public Selector<G, C> getSurvivorsSelector() { 1555 return _survivorsSelector; 1556 } 1557 1558 /** 1559 * Return the optimization strategy. 1560 * 1561 * @since 3.1 1562 * 1563 * @return the optimization strategy 1564 */ 1565 public Optimize getOptimize() { 1566 return _optimize; 1567 } 1568 1569 /** 1570 * Return the number of individuals of a population. 1571 * 1572 * @since 3.1 1573 * 1574 * @return the number of individuals of a population 1575 */ 1576 public int getPopulationSize() { 1577 return _populationSize; 1578 } 1579 1580 /** 1581 * Return the maximal number of attempt before the {@code Engine} gives 1582 * up creating a valid individual ({@code Phenotype}). 1583 * 1584 * @since 3.1 1585 * 1586 * @return the maximal number of {@code Phenotype} creation attempts 1587 */ 1588 public int getIndividualCreationRetries() { 1589 return _individualCreationRetries; 1590 } 1591 1592 /** 1593 * Return the evolution result mapper. 1594 * 1595 * @since 4.0 1596 * 1597 * @return the evolution result mapper 1598 */ 1599 public UnaryOperator<EvolutionResult<G, C>> getMapper() { 1600 return _mapper; 1601 } 1602 1603 /** 1604 * Create a new builder, with the current configuration. 1605 * 1606 * @since 3.1 1607 * 1608 * @return a new builder, with the current configuration 1609 */ 1610 @Override 1611 public Builder<G, C> copy() { 1612 return new Builder<G, C>(_genotypeFactory, _fitnessFunction) 1613 .alterers(_alterer) 1614 .clock(_clock) 1615 .executor(_executor) 1616 .evaluator(_evaluator) 1617 .fitnessScaler(_fitnessScaler) 1618 .maximalPhenotypeAge(_maximalPhenotypeAge) 1619 .offspringFraction(_offspringFraction) 1620 .offspringSelector(_offspringSelector) 1621 .phenotypeValidator(_validator) 1622 .optimize(_optimize) 1623 .populationSize(_populationSize) 1624 .survivorsSelector(_survivorsSelector) 1625 .individualCreationRetries(_individualCreationRetries) 1626 .mapping(_mapper); 1627 } 1628 1629 } 1630 1631}