001/* 002 * Java Genetic Algorithm Library (jenetics-5.1.0). 003 * Copyright (c) 2007-2019 Franz Wilhelmstötter 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 * 017 * Author: 018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com) 019 */ 020package io.jenetics.engine; 021 022import static java.lang.Math.round; 023import static java.lang.String.format; 024import static java.util.Objects.requireNonNull; 025import static java.util.concurrent.CompletableFuture.supplyAsync; 026import static java.util.concurrent.ForkJoinPool.commonPool; 027import static io.jenetics.internal.util.require.probability; 028 029import java.time.Clock; 030import java.util.Objects; 031import java.util.concurrent.CompletableFuture; 032import java.util.concurrent.Executor; 033import java.util.function.Function; 034import java.util.function.Supplier; 035import java.util.function.UnaryOperator; 036import java.util.stream.Stream; 037 038import io.jenetics.Alterer; 039import io.jenetics.AltererResult; 040import io.jenetics.Chromosome; 041import io.jenetics.Gene; 042import io.jenetics.Genotype; 043import io.jenetics.Mutator; 044import io.jenetics.Optimize; 045import io.jenetics.Phenotype; 046import io.jenetics.Selector; 047import io.jenetics.SinglePointCrossover; 048import io.jenetics.TournamentSelector; 049import io.jenetics.internal.util.require; 050import io.jenetics.util.Copyable; 051import io.jenetics.util.Factory; 052import io.jenetics.util.ISeq; 053import io.jenetics.util.MSeq; 054import io.jenetics.util.NanoClock; 055import io.jenetics.util.Seq; 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 * 100 * @implNote 101 * This class is thread safe: 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 * 106 * @see Engine.Builder 107 * @see EvolutionStart 108 * @see EvolutionResult 109 * @see EvolutionStream 110 * @see EvolutionStatistics 111 * @see Codec 112 * 113 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 114 * @since 3.0 115 * @version 5.1 116 */ 117public final class Engine< 118 G extends Gene<?, G>, 119 C extends Comparable<? super C> 120> 121 implements 122 Evolution<G, C>, 123 Function<EvolutionStart<G, C>, EvolutionResult<G, C>>, 124 EvolutionStreamable<G, C> 125{ 126 127 // Problem definition. 128 private final Evaluator<G, C> _evaluator; 129 private final Factory<Genotype<G>> _genotypeFactory; 130 131 // Evolution parameters. 132 private final Selector<G, C> _survivorsSelector; 133 private final Selector<G, C> _offspringSelector; 134 private final Alterer<G, C> _alterer; 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 Executor _executor; 142 private final Clock _clock; 143 144 // Additional parameters. 145 private final Constraint<G, C> _constraint; 146 private final UnaryOperator<EvolutionResult<G, C>> _mapper; 147 148 149 /** 150 * Create a new GA engine with the given parameters. 151 * 152 * @param genotypeFactory the genotype factory this GA is working with. 153 * @param survivorsSelector the selector used for selecting the survivors 154 * @param offspringSelector the selector used for selecting the offspring 155 * @param alterer the alterer used for altering the offspring 156 * @param constraint phenotype constraint which can override the default 157 * implementation the {@link Phenotype#isValid()} method and repairs 158 * invalid phenotypes when needed. 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 evaluator the population fitness evaluator 165 * @param clock the clock used for calculating the timing results 166 * @throws NullPointerException if one of the arguments is {@code null} 167 * @throws IllegalArgumentException if the given integer values are smaller 168 * than one. 169 */ 170 Engine( 171 final Evaluator<G, C> evaluator, 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 Constraint<G, C> constraint, 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 UnaryOperator<EvolutionResult<G, C>> mapper 184 ) { 185 _evaluator = requireNonNull(evaluator); 186 _genotypeFactory = requireNonNull(genotypeFactory); 187 _survivorsSelector = requireNonNull(survivorsSelector); 188 _offspringSelector = requireNonNull(offspringSelector); 189 _alterer = requireNonNull(alterer); 190 _constraint = requireNonNull(constraint); 191 _optimize = requireNonNull(optimize); 192 193 _offspringCount = require.nonNegative(offspringCount); 194 _survivorsCount = require.nonNegative(survivorsCount); 195 _maximalPhenotypeAge = require.positive(maximalPhenotypeAge); 196 197 _executor = requireNonNull(executor); 198 _clock = requireNonNull(clock); 199 _mapper = requireNonNull(mapper); 200 } 201 202 /** 203 * This method is an <i>alias</i> for the {@link #evolve(EvolutionStart)} 204 * method. 205 * 206 * @since 3.1 207 * 208 * @see Evolution 209 * 210 * @deprecated Will be removed and superseded by {@link #evolve(EvolutionStart)} 211 */ 212 @Deprecated 213 @Override 214 public EvolutionResult<G, C> apply(final EvolutionStart<G, C> start) { 215 return evolve(start); 216 } 217 218 @Override 219 public EvolutionResult<G, C> evolve(final EvolutionStart<G, C> start) { 220 // Create initial population if `start` is empty. 221 final EvolutionStart<G, C> es = start.getPopulation().isEmpty() 222 ? evolutionStart(start) 223 : start; 224 225 final EvolutionTiming timing = new EvolutionTiming(_clock); 226 timing.evolve.start(); 227 228 // Initial evaluation of the population. 229 final ISeq<Phenotype<G, C>> evaluated = timing.evaluation.timing(() -> 230 evaluate(es.getPopulation()) 231 ); 232 233 // Select the offspring population. 234 final CompletableFuture<ISeq<Phenotype<G, C>>> offspring = 235 supplyAsync(() -> 236 timing.offspringSelection.timing(() -> 237 selectOffspring(evaluated) 238 ), 239 _executor 240 ); 241 242 // Select the survivor population. 243 final CompletableFuture<ISeq<Phenotype<G, C>>> survivors = 244 supplyAsync(() -> 245 timing.survivorsSelection.timing(() -> 246 selectSurvivors(evaluated) 247 ), 248 _executor 249 ); 250 251 // Altering the offspring population. 252 final CompletableFuture<AltererResult<G, C>> alteredOffspring = 253 offspring.thenApplyAsync(off -> 254 timing.offspringAlter.timing(() -> 255 _alterer.alter(off, es.getGeneration()) 256 ), 257 _executor 258 ); 259 260 // Filter and replace invalid and old survivor individuals. 261 final CompletableFuture<FilterResult<G, C>> filteredSurvivors = 262 survivors.thenApplyAsync(sur -> 263 timing.survivorFilter.timing(() -> 264 filter(sur, es.getGeneration()) 265 ), 266 _executor 267 ); 268 269 // Filter and replace invalid and old offspring individuals. 270 final CompletableFuture<FilterResult<G, C>> filteredOffspring = 271 alteredOffspring.thenApplyAsync(off -> 272 timing.offspringFilter.timing(() -> 273 filter(off.getPopulation(), es.getGeneration()) 274 ), 275 _executor 276 ); 277 278 // Combining survivors and offspring to the new population. 279 final CompletableFuture<ISeq<Phenotype<G, C>>> population = 280 filteredSurvivors.thenCombineAsync( 281 filteredOffspring, 282 (s, o) -> ISeq.of(s.population.append(o.population)), 283 _executor 284 ); 285 286 // Evaluate the fitness-function and wait for result. 287 final ISeq<Phenotype<G, C>> pop = population.join(); 288 final ISeq<Phenotype<G, C>> result = timing.evaluation.timing(() -> 289 evaluate(pop) 290 ); 291 292 final int killCount = 293 filteredOffspring.join().killCount + 294 filteredSurvivors.join().killCount; 295 296 final int invalidCount = 297 filteredOffspring.join().invalidCount + 298 filteredSurvivors.join().invalidCount; 299 300 final int alterationCount = alteredOffspring.join().getAlterations(); 301 302 EvolutionResult<G, C> er = EvolutionResult.of( 303 _optimize, 304 result, 305 es.getGeneration(), 306 timing.toDurations(), 307 killCount, 308 invalidCount, 309 alterationCount 310 ); 311 if (!UnaryOperator.identity().equals(_mapper)) { 312 final EvolutionResult<G, C> mapped = _mapper.apply(er); 313 er = er.with(timing.evaluation.timing(() -> 314 evaluate(mapped.getPopulation()) 315 )); 316 } 317 318 timing.evolve.stop(); 319 return er.with(timing.toDurations()); 320 } 321 322 // Selects the survivors population. A new population object is returned. 323 private ISeq<Phenotype<G, C>> 324 selectSurvivors(final ISeq<Phenotype<G, C>> population) { 325 return _survivorsCount > 0 326 ?_survivorsSelector.select(population, _survivorsCount, _optimize) 327 : ISeq.empty(); 328 } 329 330 // Selects the offspring population. A new population object is returned. 331 private ISeq<Phenotype<G, C>> 332 selectOffspring(final ISeq<Phenotype<G, C>> population) { 333 return _offspringCount > 0 334 ? _offspringSelector.select(population, _offspringCount, _optimize) 335 : ISeq.empty(); 336 } 337 338 // Filters out invalid and old individuals. Filtering is done in place. 339 private FilterResult<G, C> filter( 340 final Seq<Phenotype<G, C>> population, 341 final long generation 342 ) { 343 int killCount = 0; 344 int invalidCount = 0; 345 346 final MSeq<Phenotype<G, C>> pop = MSeq.of(population); 347 for (int i = 0, n = pop.size(); i < n; ++i) { 348 final Phenotype<G, C> individual = pop.get(i); 349 350 if (!_constraint.test(individual)) { 351 pop.set(i, _constraint.repair(individual, generation)); 352 ++invalidCount; 353 } else if (individual.getAge(generation) > _maximalPhenotypeAge) { 354 pop.set(i, Phenotype.of(_genotypeFactory.newInstance(), generation)); 355 ++killCount; 356 } 357 } 358 359 return new FilterResult<>(pop.toISeq(), killCount, invalidCount); 360 } 361 362 363 /* ************************************************************************* 364 * Evaluation methods. 365 **************************************************************************/ 366 367 /** 368 * Evaluates the fitness function of the given population with the configured 369 * {@link Evaluator} of this engine and returns a new population 370 * with its fitness value assigned. 371 * 372 * @since 5.0 373 * 374 * @see Evaluator 375 * @see Evaluator#eval(Seq) 376 * 377 * @param population the population to evaluate 378 * @return a new population with assigned fitness values 379 * @throws IllegalStateException if the configured fitness function doesn't 380 * return a population with the same size as the input population. 381 * This exception is also thrown if one of the populations 382 * phenotype has no fitness value assigned. 383 */ 384 public ISeq<Phenotype<G, C>> evaluate(final Seq<Phenotype<G, C>> population) { 385 final ISeq<Phenotype<G, C>> evaluated = _evaluator.eval(population); 386 387 if (population.size() != evaluated.size()) { 388 throw new IllegalStateException(format( 389 "Expected %d individuals, but got %d. " + 390 "Check your evaluator function.", 391 population.size(), evaluated.size() 392 )); 393 } 394 if (!evaluated.forAll(Phenotype::isEvaluated)) { 395 throw new IllegalStateException( 396 "Some phenotypes have no assigned fitness value. " + 397 "Check your evaluator function." 398 ); 399 } 400 401 return evaluated; 402 } 403 404 405 /* ************************************************************************* 406 * Evolution Stream creation. 407 **************************************************************************/ 408 409 @Override 410 public EvolutionStream<G, C> 411 stream(final Supplier<EvolutionStart<G, C>> start) { 412 return EvolutionStream.ofEvolution( 413 () -> evolutionStart(start.get()), 414 this 415 ); 416 } 417 418 @Override 419 public EvolutionStream<G, C> stream(final EvolutionInit<G> init) { 420 return stream(evolutionStart(init)); 421 } 422 423 private EvolutionStart<G, C> 424 evolutionStart(final EvolutionStart<G, C> start) { 425 final ISeq<Phenotype<G, C>> population = start.getPopulation(); 426 final long gen = start.getGeneration(); 427 428 final Stream<Phenotype<G, C>> stream = Stream.concat( 429 population.stream(), 430 _genotypeFactory.instances() 431 .map(gt -> Phenotype.of(gt, gen)) 432 ); 433 434 final ISeq<Phenotype<G, C>> pop = stream 435 .limit(getPopulationSize()) 436 .collect(ISeq.toISeq()); 437 438 return EvolutionStart.of(pop, gen); 439 } 440 441 private EvolutionStart<G, C> 442 evolutionStart(final EvolutionInit<G> init) { 443 final ISeq<Genotype<G>> pop = init.getPopulation(); 444 final long gen = init.getGeneration(); 445 446 return evolutionStart( 447 EvolutionStart.of( 448 pop.map(gt -> Phenotype.of(gt, gen)), 449 gen 450 ) 451 ); 452 } 453 454 /* ************************************************************************* 455 * Property access methods. 456 **************************************************************************/ 457 458 /** 459 * Return the used genotype {@link Factory} of the GA. The genotype factory 460 * is used for creating the initial population and new, random individuals 461 * when needed (as replacement for invalid and/or died genotypes). 462 * 463 * @return the used genotype {@link Factory} of the GA. 464 */ 465 public Factory<Genotype<G>> getGenotypeFactory() { 466 return _genotypeFactory; 467 } 468 469 /** 470 * Return the constraint of the evolution problem. 471 * 472 * @since 5.0 473 * 474 * @return the constraint of the evolution problem 475 */ 476 public Constraint<G, C> getConstraint() { 477 return _constraint; 478 } 479 480 /** 481 * Return the used survivor {@link Selector} of the GA. 482 * 483 * @return the used survivor {@link Selector} of the GA. 484 */ 485 public Selector<G, C> getSurvivorsSelector() { 486 return _survivorsSelector; 487 } 488 489 /** 490 * Return the used offspring {@link Selector} of the GA. 491 * 492 * @return the used offspring {@link Selector} of the GA. 493 */ 494 public Selector<G, C> getOffspringSelector() { 495 return _offspringSelector; 496 } 497 498 /** 499 * Return the used {@link Alterer} of the GA. 500 * 501 * @return the used {@link Alterer} of the GA. 502 */ 503 public Alterer<G, C> getAlterer() { 504 return _alterer; 505 } 506 507 /** 508 * Return the number of selected offsprings. 509 * 510 * @return the number of selected offsprings 511 */ 512 public int getOffspringCount() { 513 return _offspringCount; 514 } 515 516 /** 517 * The number of selected survivors. 518 * 519 * @return the number of selected survivors 520 */ 521 public int getSurvivorsCount() { 522 return _survivorsCount; 523 } 524 525 /** 526 * Return the number of individuals of a population. 527 * 528 * @return the number of individuals of a population 529 */ 530 public int getPopulationSize() { 531 return _offspringCount + _survivorsCount; 532 } 533 534 /** 535 * Return the maximal allowed phenotype age. 536 * 537 * @return the maximal allowed phenotype age 538 */ 539 public long getMaximalPhenotypeAge() { 540 return _maximalPhenotypeAge; 541 } 542 543 /** 544 * Return the optimization strategy. 545 * 546 * @return the optimization strategy 547 */ 548 public Optimize getOptimize() { 549 return _optimize; 550 } 551 552 /** 553 * Return the {@link Clock} the engine is using for measuring the execution 554 * time. 555 * 556 * @return the clock used for measuring the execution time 557 */ 558 public Clock getClock() { 559 return _clock; 560 } 561 562 /** 563 * Return the {@link Executor} the engine is using for executing the 564 * evolution steps. 565 * 566 * @return the executor used for performing the evolution steps 567 */ 568 public Executor getExecutor() { 569 return _executor; 570 } 571 572 /** 573 * Return the evolution result mapper. 574 * 575 * @since 4.0 576 * 577 * @return the evolution result mapper 578 */ 579 public UnaryOperator<EvolutionResult<G, C>> getMapper() { 580 return _mapper; 581 } 582 583 /** 584 * Create a new evolution {@code Engine.Builder} initialized with the values 585 * of the current evolution {@code Engine}. With this method, the evolution 586 * engine can serve as a template for a new one. 587 * 588 * @return a new engine builder 589 */ 590 public Builder<G, C> builder() { 591 return new Builder<>(_evaluator, _genotypeFactory) 592 .alterers(_alterer) 593 .clock(_clock) 594 .executor(_executor) 595 .maximalPhenotypeAge(_maximalPhenotypeAge) 596 .offspringFraction((double)_offspringCount/(double)getPopulationSize()) 597 .offspringSelector(_offspringSelector) 598 .optimize(_optimize) 599 .constraint(_constraint) 600 .populationSize(getPopulationSize()) 601 .survivorsSelector(_survivorsSelector) 602 .mapping(_mapper); 603 } 604 605 606 /* ************************************************************************* 607 * Static Builder methods. 608 **************************************************************************/ 609 610 /** 611 * Create a new evolution {@code Engine.Builder} with the given fitness 612 * function and genotype factory. 613 * 614 * @param ff the fitness function 615 * @param gtf the genotype factory 616 * @param <G> the gene type 617 * @param <C> the fitness function result type 618 * @return a new engine builder 619 * @throws java.lang.NullPointerException if one of the arguments is 620 * {@code null}. 621 */ 622 public static <G extends Gene<?, G>, C extends Comparable<? super C>> 623 Builder<G, C> builder( 624 final Function<? super Genotype<G>, ? extends C> ff, 625 final Factory<Genotype<G>> gtf 626 ) { 627 return new Builder<>(Evaluators.concurrent(ff, commonPool()), gtf); 628 } 629 630 /** 631 * Create a new evolution {@code Engine.Builder} with the given fitness 632 * function and problem {@code codec}. 633 * 634 * @since 3.2 635 * 636 * @param ff the fitness evaluator 637 * @param codec the problem codec 638 * @param <T> the fitness function input type 639 * @param <C> the fitness function result type 640 * @param <G> the gene type 641 * @return a new engine builder 642 * @throws java.lang.NullPointerException if one of the arguments is 643 * {@code null}. 644 */ 645 public static <T, G extends Gene<?, G>, C extends Comparable<? super C>> 646 Builder<G, C> builder( 647 final Function<? super T, ? extends C> ff, 648 final Codec<T, G> codec 649 ) { 650 return builder(ff.compose(codec.decoder()), codec.encoding()); 651 } 652 653 /** 654 * Create a new evolution {@code Engine.Builder} for the given 655 * {@link Problem}. 656 * 657 * @since 3.4 658 * 659 * @param problem the problem to be solved by the evolution {@code Engine} 660 * @param <T> the (<i>native</i>) argument type of the problem fitness function 661 * @param <G> the gene type the evolution engine is working with 662 * @param <C> the result type of the fitness function 663 * @return Create a new evolution {@code Engine.Builder} 664 */ 665 public static <T, G extends Gene<?, G>, C extends Comparable<? super C>> 666 Builder<G, C> builder(final Problem<T, G, C> problem) { 667 return builder(problem.fitness(), problem.codec()); 668 } 669 670 /** 671 * Create a new evolution {@code Engine.Builder} with the given fitness 672 * function and chromosome templates. 673 * 674 * @param ff the fitness function 675 * @param chromosome the first chromosome 676 * @param chromosomes the chromosome templates 677 * @param <G> the gene type 678 * @param <C> the fitness function result type 679 * @return a new engine builder 680 * @throws java.lang.NullPointerException if one of the arguments is 681 * {@code null}. 682 */ 683 @SafeVarargs 684 public static <G extends Gene<?, G>, C extends Comparable<? super C>> 685 Builder<G, C> builder( 686 final Function<? super Genotype<G>, ? extends C> ff, 687 final Chromosome<G> chromosome, 688 final Chromosome<G>... chromosomes 689 ) { 690 return builder(ff, Genotype.of(chromosome, chromosomes)); 691 } 692 693 694 /* ************************************************************************* 695 * Inner classes 696 **************************************************************************/ 697 698 699 /** 700 * Builder class for building GA {@code Engine} instances. 701 * 702 * @see Engine 703 * 704 * @param <G> the gene type 705 * @param <C> the fitness function result type 706 * 707 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 708 * @since 3.0 709 * @version 5.1 710 */ 711 public static final class Builder< 712 G extends Gene<?, G>, 713 C extends Comparable<? super C> 714 > 715 implements Copyable<Builder<G, C>> 716 { 717 718 // No default values for this properties. 719 private final Evaluator<G, C> _evaluator; 720 private final Factory<Genotype<G>> _genotypeFactory; 721 722 // This are the properties which default values. 723 private Selector<G, C> _survivorsSelector = new TournamentSelector<>(3); 724 private Selector<G, C> _offspringSelector = new TournamentSelector<>(3); 725 private Alterer<G, C> _alterer = Alterer.of( 726 new SinglePointCrossover<G, C>(0.2), 727 new Mutator<>(0.15) 728 ); 729 private Constraint<G, C> _constraint; 730 private Optimize _optimize = Optimize.MAXIMUM; 731 private double _offspringFraction = 0.6; 732 private int _populationSize = 50; 733 private long _maximalPhenotypeAge = 70; 734 735 // Engine execution environment. 736 private Executor _executor = commonPool(); 737 private Clock _clock = NanoClock.systemUTC(); 738 739 private UnaryOperator<EvolutionResult<G, C>> _mapper = UnaryOperator.identity(); 740 741 /** 742 * Create a new evolution {@code Engine.Builder} with the given fitness 743 * evaluator and genotype factory. This is the most general way for 744 * creating an engine builder. 745 * 746 * @since 5.0 747 * 748 * @see Engine#builder(Function, Codec) 749 * @see Engine#builder(Function, Factory) 750 * @see Engine#builder(Problem) 751 * @see Engine#builder(Function, Chromosome, Chromosome[]) 752 * 753 * @param evaluator the fitness evaluator 754 * @param genotypeFactory the genotype factory 755 * @throws NullPointerException if one of the arguments is {@code null}. 756 */ 757 public Builder( 758 final Evaluator<G, C> evaluator, 759 final Factory<Genotype<G>> genotypeFactory 760 ) { 761 _genotypeFactory = requireNonNull(genotypeFactory); 762 _evaluator = requireNonNull(evaluator); 763 } 764 765 /** 766 * The selector used for selecting the offspring population. <i>Default 767 * values is set to {@code TournamentSelector<>(3)}.</i> 768 * 769 * @param selector used for selecting the offspring population 770 * @return {@code this} builder, for command chaining 771 */ 772 public Builder<G, C> offspringSelector( 773 final Selector<G, C> selector 774 ) { 775 _offspringSelector = requireNonNull(selector); 776 return this; 777 } 778 779 /** 780 * The selector used for selecting the survivors population. <i>Default 781 * values is set to {@code TournamentSelector<>(3)}.</i> 782 * 783 * @param selector used for selecting survivors population 784 * @return {@code this} builder, for command chaining 785 */ 786 public Builder<G, C> survivorsSelector( 787 final Selector<G, C> selector 788 ) { 789 _survivorsSelector = requireNonNull(selector); 790 return this; 791 } 792 793 /** 794 * The selector used for selecting the survivors and offspring 795 * population. <i>Default values is set to 796 * {@code TournamentSelector<>(3)}.</i> 797 * 798 * @param selector used for selecting survivors and offspring population 799 * @return {@code this} builder, for command chaining 800 */ 801 public Builder<G, C> selector(final Selector<G, C> selector) { 802 _offspringSelector = requireNonNull(selector); 803 _survivorsSelector = requireNonNull(selector); 804 return this; 805 } 806 807 /** 808 * The alterers used for alter the offspring population. <i>Default 809 * values is set to {@code new SinglePointCrossover<>(0.2)} followed by 810 * {@code new Mutator<>(0.15)}.</i> 811 * 812 * @param first the first alterer used for alter the offspring 813 * population 814 * @param rest the rest of the alterers used for alter the offspring 815 * population 816 * @return {@code this} builder, for command chaining 817 * @throws java.lang.NullPointerException if one of the alterers is 818 * {@code null}. 819 */ 820 @SafeVarargs 821 public final Builder<G, C> alterers( 822 final Alterer<G, C> first, 823 final Alterer<G, C>... rest 824 ) { 825 requireNonNull(first); 826 Stream.of(rest).forEach(Objects::requireNonNull); 827 828 _alterer = rest.length == 0 829 ? first 830 : Alterer.of(rest).compose(first); 831 832 return this; 833 } 834 835 /** 836 * The phenotype constraint is used for detecting invalid individuals 837 * and repairing them. 838 * 839 * <p><i>Default implementation uses {@code Phenotype::isValid} for 840 * validating the phenotype.</i></p> 841 * 842 * @since 5.0 843 * 844 * @param constraint phenotype constraint which can override the default 845 * implementation the {@link Phenotype#isValid()} method and repairs 846 * invalid phenotypes when needed. 847 * @return {@code this} builder, for command chaining 848 */ 849 public Builder<G, C> constraint(final Constraint<G, C> constraint) { 850 _constraint = constraint; 851 return this; 852 } 853 854 /** 855 * The optimization strategy used by the engine. <i>Default values is 856 * set to {@code Optimize.MAXIMUM}.</i> 857 * 858 * @param optimize the optimization strategy used by the engine 859 * @return {@code this} builder, for command chaining 860 */ 861 public Builder<G, C> optimize(final Optimize optimize) { 862 _optimize = requireNonNull(optimize); 863 return this; 864 } 865 866 /** 867 * Set to a fitness maximizing strategy. 868 * 869 * @since 3.4 870 * 871 * @return {@code this} builder, for command chaining 872 */ 873 public Builder<G, C> maximizing() { 874 return optimize(Optimize.MAXIMUM); 875 } 876 877 /** 878 * Set to a fitness minimizing strategy. 879 * 880 * @since 3.4 881 * 882 * @return {@code this} builder, for command chaining 883 */ 884 public Builder<G, C> minimizing() { 885 return optimize(Optimize.MINIMUM); 886 } 887 888 /** 889 * The offspring fraction. <i>Default values is set to {@code 0.6}.</i> 890 * This method call is equivalent to 891 * {@code survivorsFraction(1 - offspringFraction)} and will override 892 * any previously set survivors-fraction. 893 * 894 * @see #survivorsFraction(double) 895 * 896 * @param fraction the offspring fraction 897 * @return {@code this} builder, for command chaining 898 * @throws java.lang.IllegalArgumentException if the fraction is not 899 * within the range [0, 1]. 900 */ 901 public Builder<G, C> offspringFraction(final double fraction) { 902 _offspringFraction = probability(fraction); 903 return this; 904 } 905 906 /** 907 * The survivors fraction. <i>Default values is set to {@code 0.4}.</i> 908 * This method call is equivalent to 909 * {@code offspringFraction(1 - survivorsFraction)} and will override 910 * any previously set offspring-fraction. 911 * 912 * @since 3.8 913 * 914 * @see #offspringFraction(double) 915 * 916 * @param fraction the survivors fraction 917 * @return {@code this} builder, for command chaining 918 * @throws java.lang.IllegalArgumentException if the fraction is not 919 * within the range [0, 1]. 920 */ 921 public Builder<G, C> survivorsFraction(final double fraction) { 922 _offspringFraction = 1.0 - probability(fraction); 923 return this; 924 } 925 926 /** 927 * The number of offspring individuals. 928 * 929 * @since 3.8 930 * 931 * @param size the number of offspring individuals. 932 * @return {@code this} builder, for command chaining 933 * @throws java.lang.IllegalArgumentException if the size is not 934 * within the range [0, population-size]. 935 */ 936 public Builder<G, C> offspringSize(final int size) { 937 if (size < 0) { 938 throw new IllegalArgumentException(format( 939 "Offspring size must be greater or equal zero, but was %s.", 940 size 941 )); 942 } 943 944 return offspringFraction((double)size/(double)_populationSize); 945 } 946 947 /** 948 * The number of survivors. 949 * 950 * @since 3.8 951 * 952 * @param size the number of survivors. 953 * @return {@code this} builder, for command chaining 954 * @throws java.lang.IllegalArgumentException if the size is not 955 * within the range [0, population-size]. 956 */ 957 public Builder<G, C> survivorsSize(final int size) { 958 if (size < 0) { 959 throw new IllegalArgumentException(format( 960 "Survivors must be greater or equal zero, but was %s.", 961 size 962 )); 963 } 964 965 return survivorsFraction((double)size/(double)_populationSize); 966 } 967 968 /** 969 * The number of individuals which form the population. <i>Default 970 * values is set to {@code 50}.</i> 971 * 972 * @param size the number of individuals of a population 973 * @return {@code this} builder, for command chaining 974 * @throws java.lang.IllegalArgumentException if {@code size < 1} 975 */ 976 public Builder<G, C> populationSize(final int size) { 977 if (size < 1) { 978 throw new IllegalArgumentException(format( 979 "Population size must be greater than zero, but was %s.", 980 size 981 )); 982 } 983 _populationSize = size; 984 return this; 985 } 986 987 /** 988 * The maximal allowed age of a phenotype. <i>Default values is set to 989 * {@code 70}.</i> 990 * 991 * @param age the maximal phenotype age 992 * @return {@code this} builder, for command chaining 993 * @throws java.lang.IllegalArgumentException if {@code age < 1} 994 */ 995 public Builder<G, C> maximalPhenotypeAge(final long age) { 996 if (age < 1) { 997 throw new IllegalArgumentException(format( 998 "Phenotype age must be greater than one, but was %s.", age 999 )); 1000 } 1001 _maximalPhenotypeAge = age; 1002 return this; 1003 } 1004 1005 /** 1006 * The executor used by the engine. 1007 * 1008 * @param executor the executor used by the engine 1009 * @return {@code this} builder, for command chaining 1010 */ 1011 public Builder<G, C> executor(final Executor executor) { 1012 _executor = requireNonNull(executor); 1013 return this; 1014 } 1015 1016 /** 1017 * The clock used for calculating the execution durations. 1018 * 1019 * @param clock the clock used for calculating the execution durations 1020 * @return {@code this} builder, for command chaining 1021 */ 1022 public Builder<G, C> clock(final Clock clock) { 1023 _clock = requireNonNull(clock); 1024 return this; 1025 } 1026 1027 /** 1028 * The result mapper, which allows to change the evolution result after 1029 * each generation. 1030 * 1031 * @since 4.0 1032 * @see EvolutionResult#toUniquePopulation() 1033 * 1034 * @param mapper the evolution result mapper 1035 * @return {@code this} builder, for command chaining 1036 * @throws NullPointerException if the given {@code resultMapper} is 1037 * {@code null} 1038 */ 1039 public Builder<G, C> mapping( 1040 final Function< 1041 ? super EvolutionResult<G, C>, 1042 EvolutionResult<G, C> 1043 > mapper 1044 ) { 1045 _mapper = requireNonNull(mapper::apply); 1046 return this; 1047 } 1048 1049 /** 1050 * Builds an new {@code Engine} instance from the set properties. 1051 * 1052 * @return an new {@code Engine} instance from the set properties 1053 */ 1054 public Engine<G, C> build() { 1055 return new Engine<>( 1056 _evaluator instanceof ConcurrentEvaluator 1057 ? ((ConcurrentEvaluator<G, C>)_evaluator).with(_executor) 1058 : _evaluator, 1059 _genotypeFactory, 1060 _survivorsSelector, 1061 _offspringSelector, 1062 _alterer, 1063 _constraint == null 1064 ? RetryConstraint.of(_genotypeFactory) 1065 : _constraint, 1066 _optimize, 1067 getOffspringCount(), 1068 getSurvivorsCount(), 1069 _maximalPhenotypeAge, 1070 _executor, 1071 _clock, 1072 _mapper 1073 ); 1074 } 1075 1076 private int getSurvivorsCount() { 1077 return _populationSize - getOffspringCount(); 1078 } 1079 1080 private int getOffspringCount() { 1081 return (int)round(_offspringFraction*_populationSize); 1082 } 1083 1084 /** 1085 * Return the used {@link Alterer} of the GA. 1086 * 1087 * @return the used {@link Alterer} of the GA. 1088 */ 1089 public Alterer<G, C> getAlterers() { 1090 return _alterer; 1091 } 1092 1093 /** 1094 * Return the {@link Clock} the engine is using for measuring the execution 1095 * time. 1096 * 1097 * @since 3.1 1098 * 1099 * @return the clock used for measuring the execution time 1100 */ 1101 public Clock getClock() { 1102 return _clock; 1103 } 1104 1105 /** 1106 * Return the {@link Executor} the engine is using for executing the 1107 * evolution steps. 1108 * 1109 * @since 3.1 1110 * 1111 * @return the executor used for performing the evolution steps 1112 */ 1113 public Executor getExecutor() { 1114 return _executor; 1115 } 1116 1117 /** 1118 * Return the used genotype {@link Factory} of the GA. The genotype factory 1119 * is used for creating the initial population and new, random individuals 1120 * when needed (as replacement for invalid and/or died genotypes). 1121 * 1122 * @since 3.1 1123 * 1124 * @return the used genotype {@link Factory} of the GA. 1125 */ 1126 public Factory<Genotype<G>> getGenotypeFactory() { 1127 return _genotypeFactory; 1128 } 1129 1130 /** 1131 * Return the constraint of the evolution problem. 1132 * 1133 * @since 5.0 1134 * 1135 * @return the constraint of the evolution problem 1136 */ 1137 public Constraint<G, C> getConstraint() { 1138 return _constraint; 1139 } 1140 1141 /** 1142 * Return the maximal allowed phenotype age. 1143 * 1144 * @since 3.1 1145 * 1146 * @return the maximal allowed phenotype age 1147 */ 1148 public long getMaximalPhenotypeAge() { 1149 return _maximalPhenotypeAge; 1150 } 1151 1152 /** 1153 * Return the offspring fraction. 1154 * 1155 * @return the offspring fraction. 1156 */ 1157 public double getOffspringFraction() { 1158 return _offspringFraction; 1159 } 1160 1161 /** 1162 * Return the used offspring {@link Selector} of the GA. 1163 * 1164 * @since 3.1 1165 * 1166 * @return the used offspring {@link Selector} of the GA. 1167 */ 1168 public Selector<G, C> getOffspringSelector() { 1169 return _offspringSelector; 1170 } 1171 1172 /** 1173 * Return the used survivor {@link Selector} of the GA. 1174 * 1175 * @since 3.1 1176 * 1177 * @return the used survivor {@link Selector} of the GA. 1178 */ 1179 public Selector<G, C> getSurvivorsSelector() { 1180 return _survivorsSelector; 1181 } 1182 1183 /** 1184 * Return the optimization strategy. 1185 * 1186 * @since 3.1 1187 * 1188 * @return the optimization strategy 1189 */ 1190 public Optimize getOptimize() { 1191 return _optimize; 1192 } 1193 1194 /** 1195 * Return the number of individuals of a population. 1196 * 1197 * @since 3.1 1198 * 1199 * @return the number of individuals of a population 1200 */ 1201 public int getPopulationSize() { 1202 return _populationSize; 1203 } 1204 1205 /** 1206 * Return the evolution result mapper. 1207 * 1208 * @since 4.0 1209 * 1210 * @return the evolution result mapper 1211 */ 1212 public UnaryOperator<EvolutionResult<G, C>> getMapper() { 1213 return _mapper; 1214 } 1215 1216 /** 1217 * Create a new builder, with the current configuration. 1218 * 1219 * @since 3.1 1220 * 1221 * @return a new builder, with the current configuration 1222 */ 1223 @Override 1224 public Builder<G, C> copy() { 1225 return new Builder<G, C>(_evaluator, _genotypeFactory) 1226 .alterers(_alterer) 1227 .clock(_clock) 1228 .executor(_executor) 1229 .maximalPhenotypeAge(_maximalPhenotypeAge) 1230 .offspringFraction(_offspringFraction) 1231 .offspringSelector(_offspringSelector) 1232 .constraint(_constraint) 1233 .optimize(_optimize) 1234 .populationSize(_populationSize) 1235 .survivorsSelector(_survivorsSelector) 1236 .mapping(_mapper); 1237 } 1238 1239 } 1240 1241}