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