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