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