001/* 002 * Java Genetic Algorithm Library (jenetics-3.8.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 // 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.8 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 // Engine execution environment. 1077 private Executor _executor = ForkJoinPool.commonPool(); 1078 private Clock _clock = NanoClock.systemUTC(); 1079 1080 private int _individualCreationRetries = 10; 1081 1082 private Builder( 1083 final Factory<Genotype<G>> genotypeFactory, 1084 final Function<? super Genotype<G>, ? extends C> fitnessFunction 1085 ) { 1086 _genotypeFactory = requireNonNull(genotypeFactory); 1087 _fitnessFunction = requireNonNull(fitnessFunction); 1088 } 1089 1090 /** 1091 * Set the fitness function of the evolution {@code Engine}. 1092 * 1093 * @param function the fitness function to use in the GA {@code Engine} 1094 * @return {@code this} builder, for command chaining 1095 */ 1096 public Builder<G, C> fitnessFunction( 1097 Function<? super Genotype<G>, ? extends C> function 1098 ) { 1099 _fitnessFunction = requireNonNull(function); 1100 return this; 1101 } 1102 1103 /** 1104 * Set the fitness scaler of the evolution {@code Engine}. <i>Default 1105 * value is set to the identity function.</i> 1106 * 1107 * @param scaler the fitness scale to use in the GA {@code Engine} 1108 * @return {@code this} builder, for command chaining 1109 */ 1110 public Builder<G, C> fitnessScaler( 1111 final Function<? super C, ? extends C> scaler 1112 ) { 1113 _fitnessScaler = requireNonNull(scaler); 1114 return this; 1115 } 1116 1117 /** 1118 * The genotype factory used for creating new individuals. 1119 * 1120 * @param genotypeFactory the genotype factory for creating new 1121 * individuals. 1122 * @return {@code this} builder, for command chaining 1123 */ 1124 public Builder<G, C> genotypeFactory( 1125 final Factory<Genotype<G>> genotypeFactory 1126 ) { 1127 _genotypeFactory = requireNonNull(genotypeFactory); 1128 return this; 1129 } 1130 1131 /** 1132 * The selector used for selecting the offspring population. <i>Default 1133 * values is set to {@code TournamentSelector<>(3)}.</i> 1134 * 1135 * @param selector used for selecting the offspring population 1136 * @return {@code this} builder, for command chaining 1137 */ 1138 public Builder<G, C> offspringSelector( 1139 final Selector<G, C> selector 1140 ) { 1141 _offspringSelector = requireNonNull(selector); 1142 return this; 1143 } 1144 1145 /** 1146 * The selector used for selecting the survivors population. <i>Default 1147 * values is set to {@code TournamentSelector<>(3)}.</i> 1148 * 1149 * @param selector used for selecting survivors population 1150 * @return {@code this} builder, for command chaining 1151 */ 1152 public Builder<G, C> survivorsSelector( 1153 final Selector<G, C> selector 1154 ) { 1155 _survivorsSelector = requireNonNull(selector); 1156 return this; 1157 } 1158 1159 /** 1160 * The selector used for selecting the survivors and offspring 1161 * population. <i>Default values is set to 1162 * {@code TournamentSelector<>(3)}.</i> 1163 * 1164 * @param selector used for selecting survivors and offspring population 1165 * @return {@code this} builder, for command chaining 1166 */ 1167 public Builder<G, C> selector(final Selector<G, C> selector) { 1168 _offspringSelector = requireNonNull(selector); 1169 _survivorsSelector = requireNonNull(selector); 1170 return this; 1171 } 1172 1173 /** 1174 * The alterers used for alter the offspring population. <i>Default 1175 * values is set to {@code new SinglePointCrossover<>(0.2)} followed by 1176 * {@code new Mutator<>(0.15)}.</i> 1177 * 1178 * @param first the first alterer used for alter the offspring 1179 * population 1180 * @param rest the rest of the alterers used for alter the offspring 1181 * population 1182 * @return {@code this} builder, for command chaining 1183 * @throws java.lang.NullPointerException if one of the alterers is 1184 * {@code null}. 1185 */ 1186 @SafeVarargs 1187 public final Builder<G, C> alterers( 1188 final Alterer<G, C> first, 1189 final Alterer<G, C>... rest 1190 ) { 1191 requireNonNull(first); 1192 Stream.of(rest).forEach(Objects::requireNonNull); 1193 1194 _alterer = rest.length == 0 ? 1195 first : 1196 Alterer.of(rest).compose(first); 1197 1198 return this; 1199 } 1200 1201 /** 1202 * The phenotype validator used for detecting invalid individuals. 1203 * Alternatively it is also possible to set the genotype validator with 1204 * {@link #genotypeFactory(Factory)}, which will replace any 1205 * previously set phenotype validators. 1206 * 1207 * <p><i>Default value is set to {@code Phenotype::isValid}.</i></p> 1208 * 1209 * @since 3.1 1210 * 1211 * @see #genotypeValidator(Predicate) 1212 * 1213 * @param validator the {@code validator} used for validating the 1214 * individuals (phenotypes). 1215 * @return {@code this} builder, for command chaining 1216 * @throws java.lang.NullPointerException if the {@code validator} is 1217 * {@code null}. 1218 */ 1219 public Builder<G, C> phenotypeValidator( 1220 final Predicate<? super Phenotype<G, C>> validator 1221 ) { 1222 _validator = requireNonNull(validator); 1223 return this; 1224 } 1225 1226 /** 1227 * The genotype validator used for detecting invalid individuals. 1228 * Alternatively it is also possible to set the phenotype validator with 1229 * {@link #phenotypeValidator(Predicate)}, which will replace any 1230 * previously set genotype validators. 1231 * 1232 * <p><i>Default value is set to {@code Genotype::isValid}.</i></p> 1233 * 1234 * @since 3.1 1235 * 1236 * @see #phenotypeValidator(Predicate) 1237 * 1238 * @param validator the {@code validator} used for validating the 1239 * individuals (genotypes). 1240 * @return {@code this} builder, for command chaining 1241 * @throws java.lang.NullPointerException if the {@code validator} is 1242 * {@code null}. 1243 */ 1244 public Builder<G, C> genotypeValidator( 1245 final Predicate<? super Genotype<G>> validator 1246 ) { 1247 requireNonNull(validator); 1248 1249 _validator = pt -> validator.test(pt.getGenotype()); 1250 return this; 1251 } 1252 1253 /** 1254 * The optimization strategy used by the engine. <i>Default values is 1255 * set to {@code Optimize.MAXIMUM}.</i> 1256 * 1257 * @param optimize the optimization strategy used by the engine 1258 * @return {@code this} builder, for command chaining 1259 */ 1260 public Builder<G, C> optimize(final Optimize optimize) { 1261 _optimize = requireNonNull(optimize); 1262 return this; 1263 } 1264 1265 /** 1266 * Set to a fitness maximizing strategy. 1267 * 1268 * @since 3.4 1269 * 1270 * @return {@code this} builder, for command chaining 1271 */ 1272 public Builder<G, C> maximizing() { 1273 return optimize(Optimize.MAXIMUM); 1274 } 1275 1276 /** 1277 * Set to a fitness minimizing strategy. 1278 * 1279 * @since 3.4 1280 * 1281 * @return {@code this} builder, for command chaining 1282 */ 1283 public Builder<G, C> minimizing() { 1284 return optimize(Optimize.MINIMUM); 1285 } 1286 1287 /** 1288 * The offspring fraction. <i>Default values is set to {@code 0.6}.</i> 1289 * This method call is equivalent to 1290 * {@code survivorsFraction(1 - offspringFraction)} and will override 1291 * any previously set survivors-fraction. 1292 * 1293 * @see #survivorsFraction(double) 1294 * 1295 * @param fraction the offspring fraction 1296 * @return {@code this} builder, for command chaining 1297 * @throws java.lang.IllegalArgumentException if the fraction is not 1298 * within the range [0, 1]. 1299 */ 1300 public Builder<G, C> offspringFraction(final double fraction) { 1301 _offspringFraction = probability(fraction); 1302 return this; 1303 } 1304 1305 /** 1306 * The survivors fraction. <i>Default values is set to {@code 0.4}.</i> 1307 * This method call is equivalent to 1308 * {@code offspringFraction(1 - survivorsFraction)} and will override 1309 * any previously set offspring-fraction. 1310 * 1311 * @since 3.8 1312 * 1313 * @see #offspringFraction(double) 1314 * 1315 * @param fraction the survivors fraction 1316 * @return {@code this} builder, for command chaining 1317 * @throws java.lang.IllegalArgumentException if the fraction is not 1318 * within the range [0, 1]. 1319 */ 1320 public Builder<G, C> survivorsFraction(final double fraction) { 1321 _offspringFraction = 1.0 - probability(fraction); 1322 return this; 1323 } 1324 1325 /** 1326 * The number of offspring individuals. 1327 * 1328 * @since 3.8 1329 * 1330 * @param size the number of offspring individuals. 1331 * @return {@code this} builder, for command chaining 1332 * @throws java.lang.IllegalArgumentException if the size is not 1333 * within the range [0, population-size]. 1334 */ 1335 public Builder<G, C> offspringSize(final int size) { 1336 if (size < 0) { 1337 throw new IllegalArgumentException(format( 1338 "Offspring size must be greater or equal zero, but was %s.", 1339 size 1340 )); 1341 } 1342 1343 return offspringFraction((double)size/(double)_populationSize); 1344 } 1345 1346 /** 1347 * The number of survivors. 1348 * 1349 * @since 3.8 1350 * 1351 * @param size the number of survivors. 1352 * @return {@code this} builder, for command chaining 1353 * @throws java.lang.IllegalArgumentException if the size is not 1354 * within the range [0, population-size]. 1355 */ 1356 public Builder<G, C> survivorsSize(final int size) { 1357 if (size < 0) { 1358 throw new IllegalArgumentException(format( 1359 "Survivors must be greater or equal zero, but was %s.", 1360 size 1361 )); 1362 } 1363 1364 return survivorsFraction((double)size/(double)_populationSize); 1365 } 1366 1367 /** 1368 * The number of individuals which form the population. <i>Default 1369 * values is set to {@code 50}.</i> 1370 * 1371 * @param size the number of individuals of a population 1372 * @return {@code this} builder, for command chaining 1373 * @throws java.lang.IllegalArgumentException if {@code size < 1} 1374 */ 1375 public Builder<G, C> populationSize(final int size) { 1376 if (size < 1) { 1377 throw new IllegalArgumentException(format( 1378 "Population size must be greater than zero, but was %s.", 1379 size 1380 )); 1381 } 1382 _populationSize = size; 1383 return this; 1384 } 1385 1386 /** 1387 * The maximal allowed age of a phenotype. <i>Default values is set to 1388 * {@code 70}.</i> 1389 * 1390 * @param age the maximal phenotype age 1391 * @return {@code this} builder, for command chaining 1392 * @throws java.lang.IllegalArgumentException if {@code age < 1} 1393 */ 1394 public Builder<G, C> maximalPhenotypeAge(final long age) { 1395 if (age < 1) { 1396 throw new IllegalArgumentException(format( 1397 "Phenotype age must be greater than one, but was %s.", age 1398 )); 1399 } 1400 _maximalPhenotypeAge = age; 1401 return this; 1402 } 1403 1404 /** 1405 * The executor used by the engine. 1406 * 1407 * @param executor the executor used by the engine 1408 * @return {@code this} builder, for command chaining 1409 */ 1410 public Builder<G, C> executor(final Executor executor) { 1411 _executor = requireNonNull(executor); 1412 return this; 1413 } 1414 1415 /** 1416 * The clock used for calculating the execution durations. 1417 * 1418 * @param clock the clock used for calculating the execution durations 1419 * @return {@code this} builder, for command chaining 1420 */ 1421 public Builder<G, C> clock(final Clock clock) { 1422 _clock = requireNonNull(clock); 1423 return this; 1424 } 1425 1426 /** 1427 * The maximal number of attempt before the {@code Engine} gives up 1428 * creating a valid individual ({@code Phenotype}). <i>Default values is 1429 * set to {@code 10}.</i> 1430 * 1431 * @since 3.1 1432 * 1433 * @param retries the maximal retry count 1434 * @throws IllegalArgumentException if the given retry {@code count} is 1435 * smaller than zero. 1436 * @return {@code this} builder, for command chaining 1437 */ 1438 public Builder<G, C> individualCreationRetries(final int retries) { 1439 if (retries < 0) { 1440 throw new IllegalArgumentException(format( 1441 "Retry count must not be negative: %d", 1442 retries 1443 )); 1444 } 1445 _individualCreationRetries = retries; 1446 return this; 1447 } 1448 1449 /** 1450 * Builds an new {@code Engine} instance from the set properties. 1451 * 1452 * @return an new {@code Engine} instance from the set properties 1453 */ 1454 public Engine<G, C> build() { 1455 return new Engine<>( 1456 _fitnessFunction, 1457 _fitnessScaler, 1458 _genotypeFactory, 1459 _survivorsSelector, 1460 _offspringSelector, 1461 _alterer, 1462 _validator, 1463 _optimize, 1464 getOffspringCount(), 1465 getSurvivorsCount(), 1466 _maximalPhenotypeAge, 1467 _executor, 1468 _clock, 1469 _individualCreationRetries 1470 ); 1471 } 1472 1473 private int getSurvivorsCount() { 1474 return _populationSize - getOffspringCount(); 1475 } 1476 1477 private int getOffspringCount() { 1478 return (int)round(_offspringFraction*_populationSize); 1479 } 1480 1481 /** 1482 * Return the used {@link Alterer} of the GA. 1483 * 1484 * @return the used {@link Alterer} of the GA. 1485 */ 1486 public Alterer<G, C> getAlterers() { 1487 return _alterer; 1488 } 1489 1490 /** 1491 * Return the {@link Clock} the engine is using for measuring the execution 1492 * time. 1493 * 1494 * @since 3.1 1495 * 1496 * @return the clock used for measuring the execution time 1497 */ 1498 public Clock getClock() { 1499 return _clock; 1500 } 1501 1502 /** 1503 * Return the {@link Executor} the engine is using for executing the 1504 * evolution steps. 1505 * 1506 * @since 3.1 1507 * 1508 * @return the executor used for performing the evolution steps 1509 */ 1510 public Executor getExecutor() { 1511 return _executor; 1512 } 1513 1514 /** 1515 * Return the fitness function of the GA engine. 1516 * 1517 * @since 3.1 1518 * 1519 * @return the fitness function 1520 */ 1521 public Function<? super Genotype<G>, ? extends C> getFitnessFunction() { 1522 return _fitnessFunction; 1523 } 1524 1525 /** 1526 * Return the fitness scaler of the GA engine. 1527 * 1528 * @since 3.1 1529 * 1530 * @return the fitness scaler 1531 */ 1532 public Function<? super C, ? extends C> getFitnessScaler() { 1533 return _fitnessScaler; 1534 } 1535 1536 /** 1537 * Return the used genotype {@link Factory} of the GA. The genotype factory 1538 * is used for creating the initial population and new, random individuals 1539 * when needed (as replacement for invalid and/or died genotypes). 1540 * 1541 * @since 3.1 1542 * 1543 * @return the used genotype {@link Factory} of the GA. 1544 */ 1545 public Factory<Genotype<G>> getGenotypeFactory() { 1546 return _genotypeFactory; 1547 } 1548 1549 /** 1550 * Return the maximal allowed phenotype age. 1551 * 1552 * @since 3.1 1553 * 1554 * @return the maximal allowed phenotype age 1555 */ 1556 public long getMaximalPhenotypeAge() { 1557 return _maximalPhenotypeAge; 1558 } 1559 1560 /** 1561 * Return the offspring fraction. 1562 * 1563 * @return the offspring fraction. 1564 */ 1565 public double getOffspringFraction() { 1566 return _offspringFraction; 1567 } 1568 1569 /** 1570 * Return the used offspring {@link Selector} of the GA. 1571 * 1572 * @since 3.1 1573 * 1574 * @return the used offspring {@link Selector} of the GA. 1575 */ 1576 public Selector<G, C> getOffspringSelector() { 1577 return _offspringSelector; 1578 } 1579 1580 /** 1581 * Return the used survivor {@link Selector} of the GA. 1582 * 1583 * @since 3.1 1584 * 1585 * @return the used survivor {@link Selector} of the GA. 1586 */ 1587 public Selector<G, C> getSurvivorsSelector() { 1588 return _survivorsSelector; 1589 } 1590 1591 /** 1592 * Return the optimization strategy. 1593 * 1594 * @since 3.1 1595 * 1596 * @return the optimization strategy 1597 */ 1598 public Optimize getOptimize() { 1599 return _optimize; 1600 } 1601 1602 /** 1603 * Return the number of individuals of a population. 1604 * 1605 * @since 3.1 1606 * 1607 * @return the number of individuals of a population 1608 */ 1609 public int getPopulationSize() { 1610 return _populationSize; 1611 } 1612 1613 /** 1614 * Return the maximal number of attempt before the {@code Engine} gives 1615 * up creating a valid individual ({@code Phenotype}). 1616 * 1617 * @since 3.1 1618 * 1619 * @return the maximal number of {@code Phenotype} creation attempts 1620 */ 1621 public int getIndividualCreationRetries() { 1622 return _individualCreationRetries; 1623 } 1624 1625 /** 1626 * Create a new builder, with the current configuration. 1627 * 1628 * @since 3.1 1629 * 1630 * @return a new builder, with the current configuration 1631 */ 1632 @Override 1633 public Builder<G, C> copy() { 1634 return new Builder<G, C>(_genotypeFactory, _fitnessFunction) 1635 .alterers(_alterer) 1636 .clock(_clock) 1637 .executor(_executor) 1638 .fitnessScaler(_fitnessScaler) 1639 .maximalPhenotypeAge(_maximalPhenotypeAge) 1640 .offspringFraction(_offspringFraction) 1641 .offspringSelector(_offspringSelector) 1642 .phenotypeValidator(_validator) 1643 .optimize(_optimize) 1644 .populationSize(_populationSize) 1645 .survivorsSelector(_survivorsSelector) 1646 .individualCreationRetries(_individualCreationRetries); 1647 } 1648 1649 } 1650}