001/* 002 * Java Genetic Algorithm Library (jenetics-3.0.0). 003 * Copyright (c) 2007-2014 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.stream.Stream; 036import java.util.stream.StreamSupport; 037 038import org.jenetics.internal.util.Concurrency; 039import org.jenetics.internal.util.NanoClock; 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.Factory; 054 055/** 056 * Genetic algorithm <em>engine</em> which is the main class. The following 057 * example shows the main steps in initializing and executing the GA. 058 * 059 *091 * 092 * The architecture allows to decouple the configuration of the engine from the 093 * execution. The {@code Engine} is configured via the {@code Engine.Builder} 094 * class and can't be changed after creation. The actual <i>evolution</i> is 095 * performed by the {@link EvolutionStream}, which is created by the 096 * {@code Engine}. 097 * <p> 098 * <em> 099 * <b>This class is thread safe:</b> 100 * No mutable state is maintained by the engine. Therefore it is save to 101 * create multiple evolution streams with one engine, which may be actually 102 * used in different threads. 103 * </em> 104 * 105 * @see Engine.Builder 106 * @see EvolutionResult 107 * @see EvolutionStream 108 * @see EvolutionStatistics 109 * 110 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a> 111 * @since 3.0 112 * @version 3.0 — <em>$Date: 2014-12-28 $</em> 113 */ 114public final class Engine< 115 G extends Gene<?, G>, 116 C extends Comparable<? super C> 117> 118{ 119 120 // Needed context for population evolving. 121 private final Function<? super Genotype<G>, ? extends C> _fitnessFunction; 122 private final Function<? super C, ? extends C> _fitnessScaler; 123 private final Factory<Genotype<G>> _genotypeFactory; 124 private final Selector<G, C> _survivorsSelector; 125 private final Selector<G, C> _offspringSelector; 126 private final Alterer<G, C> _alterer; 127 private final Optimize _optimize; 128 private final int _offspringCount; 129 private final int _survivorsCount; 130 private final long _maximalPhenotypeAge; 131 132 // Execution context for concurrent execution of evolving steps. 133 private final TimedExecutor _executor; 134 private final Clock _clock; 135 136 137 /** 138 * Create a new GA engine with the given parameters. 139 * 140 * @param genotypeFactory the genotype factory this GA is working with. 141 * @param fitnessFunction the fitness function this GA is using. 142 * @param fitnessScaler the fitness scaler this GA is using. 143 * @param survivorsSelector the selector used for selecting the survivors 144 * @param offspringSelector the selector used for selecting the offspring 145 * @param alterer the alterer used for altering the offspring 146 * @param optimize the kind of optimization (minimize or maximize) 147 * @param offspringCount the number of the offspring individuals 148 * @param survivorsCount the number of the survivor individuals 149 * @param maximalPhenotypeAge the maximal age of an individual 150 * @param executor the executor used for executing the single evolve steps 151 * @param clock the clock used for calculating the timing results 152 * @throws NullPointerException if one of the arguments is {@code null} 153 * @throws IllegalArgumentException if the given integer values are smaller 154 * than one. 155 */ 156 Engine( 157 final Function<? super Genotype<G>, ? extends C> fitnessFunction, 158 final Function<? super C, ? extends C> fitnessScaler, 159 final Factory<Genotype<G>> genotypeFactory, 160 final Selector<G, C> survivorsSelector, 161 final Selector<G, C> offspringSelector, 162 final Alterer<G, C> alterer, 163 final Optimize optimize, 164 final int offspringCount, 165 final int survivorsCount, 166 final long maximalPhenotypeAge, 167 final Executor executor, 168 final Clock clock 169 ) { 170 _fitnessFunction = requireNonNull(fitnessFunction); 171 _fitnessScaler = requireNonNull(fitnessScaler); 172 _genotypeFactory = requireNonNull(genotypeFactory); 173 _survivorsSelector = requireNonNull(survivorsSelector); 174 _offspringSelector = requireNonNull(offspringSelector); 175 _alterer = requireNonNull(alterer); 176 _optimize = requireNonNull(optimize); 177 178 _offspringCount = require.positive(offspringCount); 179 _survivorsCount = require.positive(survivorsCount); 180 _maximalPhenotypeAge = require.positive(maximalPhenotypeAge); 181 182 _executor = new TimedExecutor(requireNonNull(executor)); 183 _clock = requireNonNull(clock); 184 } 185 186 /** 187 * Perform one evolution step with the given {@code population} and 188 * {@code generation}. New phenotypes are created with the fitness function 189 * and fitness scaler defined by this <em>engine</em>. 190 * <p> 191 * <em>This method is thread-safe.</em> 192 * 193 * @param population the population to evolve 194 * @param generation the current generation; used for calculating the 195 * phenotype age. 196 * @return the evolution result 197 * @throws java.lang.NullPointerException if the given {@code population} is 198 * {@code null} 199 */ 200 public EvolutionResult<G, C> evolve( 201 final Population<G, C> population, 202 final long generation 203 ) { 204 return evolve(new EvolutionStart<>(population, generation)); 205 } 206 207 /** 208 * Performs one generation step. 209 * 210 * @param start the evolution start state 211 * @return the resulting evolution state 212 */ 213 EvolutionResult<G, C> evolve(final EvolutionStart<G, C> start) { 214 final Timer timer = Timer.of().start(); 215 216 // Select the offspring population. 217 final CompletableFuture<TimedResult<Population<G, C>>> offspring = 218 _executor.async(() -> 219 selectOffspring(start.population), 220 _clock 221 ); 222 223 // Select the survivor population. 224 final CompletableFuture<TimedResult<Population<G, C>>> survivors = 225 _executor.async(() -> 226 selectSurvivors(start.population), 227 _clock 228 ); 229 230 // Altering the offspring population. 231 final CompletableFuture<TimedResult<AlterResult<G, C>>> alteredOffspring = 232 _executor.thenApply(offspring, p -> 233 alter(p.result, start.generation), 234 _clock 235 ); 236 237 // Filter and replace invalid and to old survivor individuals. 238 final CompletableFuture<TimedResult<FilterResult<G, C>>> filteredSurvivors = 239 _executor.thenApply(survivors, pop -> 240 filter(pop.result, start.generation), 241 _clock 242 ); 243 244 // Filter and replace invalid and to old offspring individuals. 245 final CompletableFuture<TimedResult<FilterResult<G, C>>> filteredOffspring = 246 _executor.thenApply(alteredOffspring, pop -> 247 filter(pop.result.population, start.generation), 248 _clock 249 ); 250 251 // Combining survivors and offspring to the new population. 252 final CompletableFuture<Population<G, C>> population = 253 filteredSurvivors.thenCombineAsync(filteredOffspring, (s, o) -> { 254 final Population<G, C> pop = s.result.population; 255 pop.addAll(o.result.population); 256 return pop; 257 }, 258 _executor.get() 259 ); 260 261 // Evaluate the fitness-function and wait for result. 262 final TimedResult<Population<G, C>> result = population 263 .thenApply(TimedResult.of(this::evaluate, _clock)) 264 .join(); 265 266 final EvolutionDurations durations = EvolutionDurations.of( 267 offspring.join().duration, 268 survivors.join().duration, 269 alteredOffspring.join().duration, 270 filteredOffspring.join().duration, 271 filteredSurvivors.join().duration, 272 result.duration, 273 timer.stop().getTime() 274 ); 275 276 final int killCount = 277 filteredOffspring.join().result.killCount + 278 filteredSurvivors.join().result.killCount; 279 280 final int invalidCount = 281 filteredOffspring.join().result.invalidCount + 282 filteredSurvivors.join().result.invalidCount; 283 284 return EvolutionResult.of( 285 _optimize, 286 result.result, 287 start.generation, 288 durations, 289 killCount, 290 invalidCount, 291 alteredOffspring.join().result.alterCount 292 ); 293 } 294 295 // Selects the survivors population. A new population object is returned. 296 private Population<G, C> selectSurvivors(final Population<G, C> population) { 297 return _survivorsSelector.select(population, _survivorsCount, _optimize); 298 } 299 300 // Selects the offspring population. A new population object is returned. 301 private Population<G, C> selectOffspring(final Population<G, C> population) { 302 return _offspringSelector.select(population, _offspringCount, _optimize); 303 } 304 305 // Filters out invalid and to old individuals. Filtering is done in place. 306 private FilterResult<G, C> filter( 307 final Population<G, C> population, 308 final long generation 309 ) { 310 int killCount = 0; 311 int invalidCount = 0; 312 313 for (int i = 0, n = population.size(); i < n; ++i) { 314 final Phenotype<G, C> individual = population.get(i); 315 316 if (!individual.isValid()) { 317 population.set(i, newPhenotype(generation)); 318 ++invalidCount; 319 } else if (individual.getAge(generation) > _maximalPhenotypeAge) { 320 population.set(i, newPhenotype(generation)); 321 ++killCount; 322 } 323 } 324 325 return new FilterResult<>(population, killCount, invalidCount); 326 } 327 328 // Create a new phenotype 329 private Phenotype<G, C> newPhenotype(final long generation) { 330 return Phenotype.of( 331 _genotypeFactory.newInstance(), 332 generation, 333 _fitnessFunction, 334 _fitnessScaler 335 ); 336 } 337 338 // Alters the given population. The altering is done in place. 339 private AlterResult<G, C> alter( 340 final Population<G,C> population, 341 final long generation 342 ) { 343 return new AlterResult<>( 344 population, 345 _alterer.alter(population, generation) 346 ); 347 } 348 349 // Evaluates the fitness function of the give population concurrently. 350 private Population<G, C> evaluate(final Population<G, C> population) { 351 try (Concurrency c = Concurrency.with(_executor.get())) { 352 c.execute(population); 353 } 354 return population; 355 } 356 357 /** 358 * Create a new <b>infinite</b> evolution iterator with a newly created 359 * population. This is an alternative way for evolution. It lets the user 360 * start, stop and resume the evolution process whenever desired. 361 * 362 * @return a new <b>infinite</b> evolution iterator 363 */ 364 public Iterator<EvolutionResult<G, C>> iterator() { 365 return new EvolutionIterator<>( 366 this::evolve, 367 this::evolutionStart 368 ); 369 } 370 371 /** 372 * Create a new <b>infinite</b> evolution stream with a newly created 373 * population. 374 * 375 * @return a new evolution stream. 376 */ 377 public EvolutionStream<G, C> stream() { 378 return new EvolutionStreamImpl<>( 379 this::evolve, 380 this::evolutionStart 381 ); 382 } 383 384 private EvolutionStart<G, C> evolutionStart() { 385 final int generation = 1; 386 final int size = _offspringCount + _survivorsCount; 387 388 final Population<G, C> population = new Population<G, C>(size) 389 .fill(() -> newPhenotype(generation), size); 390 evaluate(population); 391 392 return new EvolutionStart<>(population, generation); 393 } 394 395 /** 396 * Create a new <b>infinite</b> evolution stream with the given initial 397 * individuals. If an empty {@code Iterable} is given, the engines genotype 398 * factory is used for creating the population. 399 * 400 * @param genotypes the initial individuals used for the evolution stream. 401 * Missing individuals are created and individuals not needed are 402 * skipped. 403 * @return a new evolution stream. 404 * @throws java.lang.NullPointerException if the given {@code genotypes} is 405 * {@code null}. 406 */ 407 public EvolutionStream<G, C> stream( 408 final Iterable<Genotype<G>> genotypes 409 ) { 410 requireNonNull(genotypes); 411 412 return new EvolutionStreamImpl<>( 413 this::evolve, 414 () -> evolutionStart(genotypes, 1) 415 ); 416 } 417 418 /** 419 * Create a new <b>infinite</b> evolution iterator with the given initial 420 * individuals. If an empty {@code Iterable} is given, the engines genotype 421 * factory is used for creating the population. 422 * 423 * @param genotypes the initial individuals used for the evolution iterator. 424 * Missing individuals are created and individuals not needed are 425 * skipped. 426 * @return a new <b>infinite</b> evolution iterator 427 * @throws java.lang.NullPointerException if the given {@code genotypes} is 428 * {@code null}. 429 */ 430 public Iterator<EvolutionResult<G, C>> iterator( 431 final Iterable<Genotype<G>> genotypes 432 ) { 433 requireNonNull(genotypes); 434 435 return new EvolutionIterator<>( 436 this::evolve, 437 () -> evolutionStart(genotypes, 1) 438 ); 439 } 440 441 private EvolutionStart<G, C> evolutionStart( 442 final Iterable<Genotype<G>> genotypes, 443 final long generation 444 ) { 445 final Stream<Phenotype<G, C>> stream = Stream.concat( 446 StreamSupport.stream(genotypes.spliterator(), false) 447 .map(gt -> Phenotype.of( 448 gt, generation, _fitnessFunction, _fitnessScaler)), 449 Stream.generate(() -> newPhenotype(generation)) 450 ); 451 452 final Population<G, C> population = stream 453 .limit(getPopulationSize()) 454 .collect(toPopulation()); 455 evaluate(population); 456 457 return new EvolutionStart<>(population, generation); 458 } 459 460 /** 461 * Create a new <b>infinite</b> evolution stream with the given initial 462 * population. If an empty {@code Population} is given, the engines genotype 463 * factory is used for creating the population. The given population might 464 * be the result of an other engine and this method allows to start the 465 * evolution with the outcome of an different engine. The fitness function 466 * and the fitness scaler are replaced by the one defined for this engine. 467 * 468 * @param population the initial individuals used for the evolution stream. 469 * Missing individuals are created and individuals not needed are 470 * skipped. 471 * @param generation the generation the stream starts from; must be greater 472 * than zero. 473 * @return a new evolution stream. 474 * @throws java.lang.NullPointerException if the given {@code population} is 475 * {@code null}. 476 * @throws IllegalArgumentException if the given {@code generation} is smaller 477 * then one 478 */ 479 public EvolutionStream<G, C> stream( 480 final Population<G, C> population, 481 final long generation 482 ) { 483 requireNonNull(population); 484 require.positive(generation); 485 486 return new EvolutionStreamImpl<>( 487 this::evolve, 488 () -> evolutionStart(population, generation) 489 ); 490 } 491 492 /** 493 * Create a new <b>infinite</b> evolution iterator with the given initial 494 * population. If an empty {@code Population} is given, the engines genotype 495 * factory is used for creating the population. The given population might 496 * be the result of an other engine and this method allows to start the 497 * evolution with the outcome of an different engine. The fitness function 498 * and the fitness scaler are replaced by the one defined for this engine. 499 * 500 * @param population the initial individuals used for the evolution iterator. 501 * Missing individuals are created and individuals not needed are 502 * skipped. 503 * @param generation the generation the iterator starts from; must be greater 504 * than zero. 505 * @return a new <b>infinite</b> evolution iterator 506 * @throws java.lang.NullPointerException if the given {@code population} is 507 * {@code null}. 508 * @throws IllegalArgumentException if the given {@code generation} is smaller 509 * then one 510 */ 511 public Iterator<EvolutionResult<G, C>> iterator( 512 final Population<G, C> population, 513 final long generation 514 ) { 515 requireNonNull(population); 516 require.positive(generation); 517 518 return new EvolutionIterator<>( 519 this::evolve, 520 () -> evolutionStart(population, generation) 521 ); 522 } 523 524 private EvolutionStart<G, C> evolutionStart( 525 final Population<G, C> population, 526 final long generation 527 ) { 528 final Stream<Phenotype<G, C>> stream = Stream.concat( 529 population.stream() 530 .map(p -> p.newInstance( 531 p.getGeneration(), 532 _fitnessFunction, 533 _fitnessScaler)), 534 Stream.generate(() -> newPhenotype(generation)) 535 ); 536 537 final Population<G, C> pop = stream 538 .limit(getPopulationSize()) 539 .collect(toPopulation()); 540 evaluate(pop); 541 542 return new EvolutionStart<>(pop, generation); 543 } 544 545 546 547 /* ************************************************************************* 548 * Property access methods. 549 **************************************************************************/ 550 551 /** 552 * Return the fitness function of the GA engine. 553 * 554 * @return the fitness function 555 */ 556 public Function<? super Genotype<G>, ? extends C> getFitnessFunction() { 557 return _fitnessFunction; 558 } 559 560 /** 561 * Return the fitness scaler of the GA engine. 562 * 563 * @return the fitness scaler 564 */ 565 public Function<? super C, ? extends C> getFitnessScaler() { 566 return _fitnessScaler; 567 } 568 569 /** 570 * Return the used genotype {@link Factory} of the GA. The genotype factory 571 * is used for creating the initial population and new, random individuals 572 * when needed (as replacement for invalid and/or died genotypes). 573 * 574 * @return the used genotype {@link Factory} of the GA. 575 */ 576 public Factory<Genotype<G>> getGenotypeFactory() { 577 return _genotypeFactory; 578 } 579 580 /** 581 * Return the used survivor {@link Selector} of the GA. 582 * 583 * @return the used survivor {@link Selector} of the GA. 584 */ 585 public Selector<G, C> getSurvivorsSelector() { 586 return _survivorsSelector; 587 } 588 589 /** 590 * Return the used offspring {@link Selector} of the GA. 591 * 592 * @return the used offspring {@link Selector} of the GA. 593 */ 594 public Selector<G, C> getOffspringSelector() { 595 return _offspringSelector; 596 } 597 598 /** 599 * Return the used {@link Alterer} of the GA. 600 * 601 * @return the used {@link Alterer} of the GA. 602 */ 603 public Alterer<G, C> getAlterer() { 604 return _alterer; 605 } 606 607 /** 608 * Return the number of selected offsprings. 609 * 610 * @return the number of selected offsprings 611 */ 612 public int getOffspringCount() { 613 return _offspringCount; 614 } 615 616 /** 617 * The number of selected survivors. 618 * 619 * @return the number of selected survivors 620 */ 621 public int getSurvivorsCount() { 622 return _survivorsCount; 623 } 624 625 /** 626 * Return the number of individuals of a population. 627 * 628 * @return the number of individuals of a population 629 */ 630 public int getPopulationSize() { 631 return _offspringCount + _survivorsCount; 632 } 633 634 /** 635 * Return the maximal allowed phenotype age. 636 * 637 * @return the maximal allowed phenotype age 638 */ 639 public long getMaximalPhenotypeAge() { 640 return _maximalPhenotypeAge; 641 } 642 643 /** 644 * Return the optimization strategy. 645 * 646 * @return the optimization strategy 647 */ 648 public Optimize getOptimize() { 649 return _optimize; 650 } 651 652 653 /* ************************************************************************* 654 * Builder methods. 655 **************************************************************************/ 656 657 /** 658 * Create a new evolution {@code Engine.Builder} initialized with the values 659 * of the current evolution {@code Engine}. With this method, the evolution 660 * engine can serve as a template for an new one. 661 * 662 * @return a new engine builder 663 */ 664 public Builder<G, C> builder() { 665 return new Builder<>(_genotypeFactory, _fitnessFunction) 666 .alterers(_alterer) 667 .clock(_clock) 668 .executor(_executor.get()) 669 .fitnessScaler(_fitnessScaler) 670 .maximalPhenotypeAge(_maximalPhenotypeAge) 671 .offspringFraction((double)_offspringCount/(double)getPopulationSize()) 672 .offspringSelector(_offspringSelector) 673 .optimize(_optimize) 674 .populationSize(getPopulationSize()) 675 .survivorsSelector(_survivorsSelector); 676 } 677 678 /** 679 * Create a new evolution {@code Engine.Builder} with the given fitness 680 * function and genotype factory. 681 * 682 * @param fitnessFunction the fitness function 683 * @param genotypeFactory the genotype factory 684 * @param <G> the gene type 685 * @param <C> the fitness function result type 686 * @return a new engine builder 687 * @throws java.lang.NullPointerException if one of the arguments is 688 * {@code null}. 689 */ 690 public static <G extends Gene<?, G>, C extends Comparable<? super C>> 691 Builder<G, C> builder( 692 final Function<? super Genotype<G>, ? extends C> fitnessFunction, 693 final Factory<Genotype<G>> genotypeFactory 694 ) { 695 return new Builder<>(genotypeFactory, fitnessFunction); 696 } 697 698 /** 699 * Create a new evolution {@code Engine.Builder} with the given fitness 700 * function and chromosome templates. 701 * 702 * @param fitnessFunction the fitness function 703 * @param chromosome the first chromosome 704 * @param chromosomes the chromosome templates 705 * @param <G> the gene type 706 * @param <C> the fitness function result type 707 * @return a new engine builder 708 * @throws java.lang.NullPointerException if one of the arguments is 709 * {@code null}. 710 */ 711 @SafeVarargs 712 public static <G extends Gene<?, G>, C extends Comparable<? super C>> 713 Builder<G, C> builder( 714 final Function<? super Genotype<G>, ? extends C> fitnessFunction, 715 final Chromosome<G> chromosome, 716 final Chromosome<G>... chromosomes 717 ) { 718 return new Builder<>( 719 Genotype.of(chromosome, chromosomes), 720 fitnessFunction 721 ); 722 } 723 724 725 726 /* ************************************************************************* 727 * Inner classes 728 **************************************************************************/ 729 730 /** 731 * Builder class for building GA {@code Engine} instances. 732 * 733 * @see Engine 734 * 735 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a> 736 * @since 3.0 737 * @version 3.0 — <em>$Date: 2014-12-28 $</em> 738 */ 739 public static final class Builder< 740 G extends Gene<?, G>, 741 C extends Comparable<? super C> 742 > 743 { 744 745 // No default values for this properties. 746 private Function<? super Genotype<G>, ? extends C> _fitnessFunction; 747 private Factory<Genotype<G>> _genotypeFactory; 748 749 // This are the properties which default values. 750 private Function<? super C, ? extends C> _fitnessScaler = a -> a; 751 private Selector<G, C> _survivorsSelector = new TournamentSelector<>(3); 752 private Selector<G, C> _offspringSelector = new TournamentSelector<>(3); 753 private Alterer<G, C> _alterer = Alterer.of( 754 new SinglePointCrossover<G, C>(0.2), 755 new Mutator<>(0.15) 756 ); 757 private Optimize _optimize = Optimize.MAXIMUM; 758 private double _offspringFraction = 0.6; 759 private int _populationSize = 50; 760 private long _maximalPhenotypeAge = 70; 761 762 private Executor _executor = ForkJoinPool.commonPool(); 763 private Clock _clock = NanoClock.INSTANCE; 764 765 private Builder( 766 final Factory<Genotype<G>> genotypeFactory, 767 final Function<? super Genotype<G>, ? extends C> fitnessFunction 768 ) { 769 _genotypeFactory = requireNonNull(genotypeFactory); 770 _fitnessFunction = requireNonNull(fitnessFunction); 771 } 772 773 /** 774 * Set the fitness function of the evolution {@code Engine}. 775 * 776 * @param function the fitness function to use in the GA {@code Engine} 777 * @return {@code this} builder, for command chaining 778 */ 779 public Builder<G, C> fitnessFunction( 780 Function<? super Genotype<G>, ? extends C> function 781 ) { 782 _fitnessFunction = requireNonNull(function); 783 return this; 784 } 785 786 /** 787 * Set the fitness scaler of the evolution {@code Engine}. <i>Default 788 * value is set to the identity function.</i> 789 * 790 * @param scaler the fitness scale to use in the GA {@code Engine} 791 * @return {@code this} builder, for command chaining 792 */ 793 public Builder<G, C> fitnessScaler( 794 final Function<? super C, ? extends C> scaler 795 ) { 796 _fitnessScaler = requireNonNull(scaler); 797 return this; 798 } 799 800 /** 801 * The genotype factory used for creating new individuals. 802 * 803 * @param genotypeFactory the genotype factory for creating new 804 * individuals. 805 * @return {@code this} builder, for command chaining 806 */ 807 public Builder<G, C> genotypeFactory( 808 final Factory<Genotype<G>> genotypeFactory 809 ) { 810 _genotypeFactory = requireNonNull(genotypeFactory); 811 return this; 812 } 813 814 /** 815 * The selector used for selecting the offspring population. <i>Default 816 * values is set to {@code TournamentSelector<>(3)}.</i> 817 * 818 * @param selector used for selecting the offspring population 819 * @return {@code this} builder, for command chaining 820 */ 821 public Builder<G, C> offspringSelector( 822 final Selector<G, C> selector 823 ) { 824 _offspringSelector = requireNonNull(selector); 825 return this; 826 } 827 828 /** 829 * The selector used for selecting the survivors population. <i>Default 830 * values is set to {@code TournamentSelector<>(3)}.</i> 831 * 832 * @param selector used for selecting survivors population 833 * @return {@code this} builder, for command chaining 834 */ 835 public Builder<G, C> survivorsSelector( 836 final Selector<G, C> selector 837 ) { 838 _survivorsSelector = requireNonNull(selector); 839 return this; 840 } 841 842 /** 843 * The selector used for selecting the survivors and offspring 844 * population. <i>Default values is set to 845 * {@code TournamentSelector<>(3)}.</i> 846 * 847 * @param selector used for selecting survivors and offspring population 848 * @return {@code this} builder, for command chaining 849 */ 850 public Builder<G, C> selector(final Selector<G, C> selector) { 851 _offspringSelector = requireNonNull(selector); 852 _survivorsSelector = requireNonNull(selector); 853 return this; 854 } 855 856 /** 857 * The alterers used for alter the offspring population. <i>Default 858 * values is set to {@code new SinglePointCrossover<>(0.2)} followed by 859 * {@code new Mutator<>(0.15)}.</i> 860 * 861 * @param first the first alterer used for alter the offspring 862 * population 863 * @param rest the rest of the alterers used for alter the offspring 864 * population 865 * @return {@code this} builder, for command chaining 866 * @throws java.lang.NullPointerException if one of the alterers is 867 * {@code null}. 868 */ 869 @SafeVarargs 870 public final Builder<G, C> alterers( 871 final Alterer<G, C> first, 872 final Alterer<G, C>... rest 873 ) { 874 requireNonNull(first); 875 Stream.of(rest).forEach(Objects::requireNonNull); 876 877 _alterer = rest.length == 0 ? 878 first : 879 Alterer.of(rest).compose(first); 880 881 return this; 882 } 883 884 /** 885 * The optimization strategy used by the engine. <i>Default values is 886 * set to {@code Optimize.MAXIMUM}.</i> 887 * 888 * @param optimize the optimization strategy used by the engine 889 * @return {@code this} builder, for command chaining 890 */ 891 public Builder<G, C> optimize(final Optimize optimize) { 892 _optimize = requireNonNull(optimize); 893 return this; 894 } 895 896 /** 897 * The offspring fraction. <i>Default values is set to {@code 0.6}.</i> 898 * 899 * @param fraction the offspring fraction 900 * @return {@code this} builder, for command chaining 901 * @throws java.lang.IllegalArgumentException if the fraction is not 902 * within the range [0, 1]. 903 */ 904 public Builder<G, C> offspringFraction(final double fraction) { 905 _offspringFraction = probability(fraction); 906 return this; 907 } 908 909 /** 910 * The number of individuals which form the population. <i>Default 911 * values is set to {@code 50}.</i> 912 * 913 * @param size the number of individuals of a population 914 * @return {@code this} builder, for command chaining 915 * @throws java.lang.IllegalArgumentException if {@code size < 1} 916 */ 917 public Builder<G, C> populationSize(final int size) { 918 if (size < 1) { 919 throw new IllegalArgumentException(format( 920 "Population size must be greater than zero, but was %s.", size 921 )); 922 } 923 _populationSize = size; 924 return this; 925 } 926 927 /** 928 * The maximal allowed age of a phenotype. <i>Default values is set to 929 * {@code 70}.</i> 930 * 931 * @param age the maximal phenotype age 932 * @return {@code this} builder, for command chaining 933 * @throws java.lang.IllegalArgumentException if {@code age < 1} 934 */ 935 public Builder<G, C> maximalPhenotypeAge(final long age) { 936 if (age < 1) { 937 throw new IllegalArgumentException(format( 938 "Phenotype age must be greater than one, but was %s.", age 939 )); 940 } 941 _maximalPhenotypeAge = age; 942 return this; 943 } 944 945 /** 946 * The executor used by the engine. 947 * 948 * @param executor the executor used by the engine 949 * @return {@code this} builder, for command chaining 950 */ 951 public Builder<G, C> executor(final Executor executor) { 952 _executor = requireNonNull(executor); 953 return this; 954 } 955 956 /** 957 * The clock used for calculating the execution durations. 958 * 959 * @param clock the clock used for calculating the execution durations 960 * @return {@code this} builder, for command chaining 961 */ 962 public Builder<G, C> clock(final Clock clock) { 963 _clock = requireNonNull(clock); 964 return this; 965 } 966 967 /** 968 * Builds an new {@code Engine} instance from the set properties. 969 * 970 * @return an new {@code Engine} instance from the set properties 971 */ 972 public Engine<G, C> build() { 973 return new Engine<>( 974 _fitnessFunction, 975 _fitnessScaler, 976 _genotypeFactory, 977 _survivorsSelector, 978 _offspringSelector, 979 _alterer, 980 _optimize, 981 getOffspringCount(), 982 getSurvivorsCount(), 983 _maximalPhenotypeAge, 984 _executor, 985 _clock 986 ); 987 } 988 989 private int getSurvivorsCount() { 990 return _populationSize - getOffspringCount(); 991 } 992 993 private int getOffspringCount() { 994 return (int)round(_offspringFraction*_populationSize); 995 } 996 997 } 998}"line.59"> class="sourceLineNo">060 * public class RealFunction {"line.60"> class="sourceLineNo">061 * // Definition of the fitness function. class="sourceLineNo">062 * private static Double evaluate(final Genotype<DoubleGene> gt) {"line.62"> class="sourceLineNo">063 * final double x = gt.getGene().doubleValue();"line.63"> class="sourceLineNo">064 * return cos(0.5 + sin(x)) * cos(x);"line.64"> class="sourceLineNo">065 * }"line.65"> class="sourceLineNo">066 *"line.66"> class="sourceLineNo">067 * public static void main(String[] args) {"line.67"> class="sourceLineNo">068 * // Create/configuring the engine via its builder. class="sourceLineNo">069 * final Engine<DoubleGene, Double> engine = Engine"line.69"> class="sourceLineNo">070 * .builder("line.70"> class="sourceLineNo">071 * RealFunction::evaluate,"line.71"> class="sourceLineNo">072 * DoubleChromosome.of(0.0, 2.0*PI))"line.72"> class="sourceLineNo">073 * .populationSize(500)"line.73"> class="sourceLineNo">074 * .optimize(Optimize.MINIMUM)"line.74"> class="sourceLineNo">075 * .alterers("line.75"> class="sourceLineNo">076 * new Mutator<>(0.03),"line.76"> class="sourceLineNo">077 * new MeanAlterer<>(0.6))"line.77"> class="sourceLineNo">078 * .build();"line.78"> class="sourceLineNo">079 *"line.79"> class="sourceLineNo">080 * // Execute the GA (engine). class="sourceLineNo">081 * final Phenotype<DoubleGene, Double> result = engine.stream()"line.81"> class="sourceLineNo">082 * // Truncate the evolution stream if no better individual could class="sourceLineNo">083 * // be found after 5 consecutive generations. class="sourceLineNo">084 * .limit(bySteadyFitness(5))"line.84"> class="sourceLineNo">085 * // Terminate the evolution after maximal 100 generations. class="sourceLineNo">086 * .limit(100)"line.86"> class="sourceLineNo">087 * .collect(toBestPhenotype());"line.87"> class="sourceLineNo">088 * }"line.88"> class="sourceLineNo">089 * }"line.89">