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