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