/** * The alterers used for alter the offspring population. <i>Default values is set to {@code new * SinglePointCrossover<>(0.2)} followed by {@code new Mutator<>(0.15)}.</i> * * @param first the first alterer used for alter the offspring population * @param rest the rest of the alterers used for alter the offspring population * @return {@code this} builder, for command chaining * @throws java.lang.NullPointerException if one of the alterers is {@code null}. */ @SafeVarargs public final Builder<G, C> alterers(final Alterer<G, C> first, final Alterer<G, C>... rest) { requireNonNull(first); Stream.of(rest).forEach(Objects::requireNonNull); _alterer = rest.length == 0 ? first : Alterer.of(rest).compose(first); return this; }
/** * Builder class for building GA {@code Engine} instances. * * @see Engine * @author <a href="mailto:[email protected]">Franz Wilhelmstötter</a> * @since 3.0 * @version 3.0 */ public static final class Builder<G extends Gene<?, G>, C extends Comparable<? super C>> implements Copyable<Builder<G, C>> { // No default values for this properties. private Function<? super Genotype<G>, ? extends C> _fitnessFunction; private Factory<Genotype<G>> _genotypeFactory; // This are the properties which default values. private Function<? super C, ? extends C> _fitnessScaler = a -> a; private Selector<G, C> _survivorsSelector = new TournamentSelector<>(3); private Selector<G, C> _offspringSelector = new TournamentSelector<>(3); private Alterer<G, C> _alterer = Alterer.of(new SinglePointCrossover<G, C>(0.2), new Mutator<>(0.15)); private Predicate<? super Phenotype<G, C>> _validator = Phenotype::isValid; private Optimize _optimize = Optimize.MAXIMUM; private double _offspringFraction = 0.6; private int _populationSize = 50; private long _maximalPhenotypeAge = 70; private Executor _executor = ForkJoinPool.commonPool(); private Clock _clock = NanoClock.systemUTC(); private int _individualCreationRetries = 10; private Builder( final Factory<Genotype<G>> genotypeFactory, final Function<? super Genotype<G>, ? extends C> fitnessFunction) { _genotypeFactory = requireNonNull(genotypeFactory); _fitnessFunction = requireNonNull(fitnessFunction); } /** * Set the fitness function of the evolution {@code Engine}. * * @param function the fitness function to use in the GA {@code Engine} * @return {@code this} builder, for command chaining */ public Builder<G, C> fitnessFunction(Function<? super Genotype<G>, ? extends C> function) { _fitnessFunction = requireNonNull(function); return this; } /** * Set the fitness scaler of the evolution {@code Engine}. <i>Default value is set to the * identity function.</i> * * @param scaler the fitness scale to use in the GA {@code Engine} * @return {@code this} builder, for command chaining */ public Builder<G, C> fitnessScaler(final Function<? super C, ? extends C> scaler) { _fitnessScaler = requireNonNull(scaler); return this; } /** * The genotype factory used for creating new individuals. * * @param genotypeFactory the genotype factory for creating new individuals. * @return {@code this} builder, for command chaining */ public Builder<G, C> genotypeFactory(final Factory<Genotype<G>> genotypeFactory) { _genotypeFactory = requireNonNull(genotypeFactory); return this; } /** * The selector used for selecting the offspring population. <i>Default values is set to {@code * TournamentSelector<>(3)}.</i> * * @param selector used for selecting the offspring population * @return {@code this} builder, for command chaining */ public Builder<G, C> offspringSelector(final Selector<G, C> selector) { _offspringSelector = requireNonNull(selector); return this; } /** * The selector used for selecting the survivors population. <i>Default values is set to {@code * TournamentSelector<>(3)}.</i> * * @param selector used for selecting survivors population * @return {@code this} builder, for command chaining */ public Builder<G, C> survivorsSelector(final Selector<G, C> selector) { _survivorsSelector = requireNonNull(selector); return this; } /** * The selector used for selecting the survivors and offspring population. <i>Default values is * set to {@code TournamentSelector<>(3)}.</i> * * @param selector used for selecting survivors and offspring population * @return {@code this} builder, for command chaining */ public Builder<G, C> selector(final Selector<G, C> selector) { _offspringSelector = requireNonNull(selector); _survivorsSelector = requireNonNull(selector); return this; } /** * The alterers used for alter the offspring population. <i>Default values is set to {@code new * SinglePointCrossover<>(0.2)} followed by {@code new Mutator<>(0.15)}.</i> * * @param first the first alterer used for alter the offspring population * @param rest the rest of the alterers used for alter the offspring population * @return {@code this} builder, for command chaining * @throws java.lang.NullPointerException if one of the alterers is {@code null}. */ @SafeVarargs public final Builder<G, C> alterers(final Alterer<G, C> first, final Alterer<G, C>... rest) { requireNonNull(first); Stream.of(rest).forEach(Objects::requireNonNull); _alterer = rest.length == 0 ? first : Alterer.of(rest).compose(first); return this; } /** * The phenotype validator used for detecting invalid individuals. Alternatively it is also * possible to set the genotype validator with {@link #genotypeFactory(Factory)}, which will * replace any previously set phenotype validators. * * <p><i>Default value is set to {@code Phenotype::isValid}.</i> * * @since 3.1 * @see #genotypeValidator(Predicate) * @param validator the {@code validator} used for validating the individuals (phenotypes). * @return {@code this} builder, for command chaining * @throws java.lang.NullPointerException if the {@code validator} is {@code null}. */ public Builder<G, C> phenotypeValidator(final Predicate<? super Phenotype<G, C>> validator) { _validator = requireNonNull(validator); return this; } /** * The genotype validator used for detecting invalid individuals. Alternatively it is also * possible to set the phenotype validator with {@link #phenotypeValidator(Predicate)}, which * will replace any previously set genotype validators. * * <p><i>Default value is set to {@code Genotype::isValid}.</i> * * @since 3.1 * @see #phenotypeValidator(Predicate) * @param validator the {@code validator} used for validating the individuals (genotypes). * @return {@code this} builder, for command chaining * @throws java.lang.NullPointerException if the {@code validator} is {@code null}. */ public Builder<G, C> genotypeValidator(final Predicate<? super Genotype<G>> validator) { requireNonNull(validator); _validator = pt -> validator.test(pt.getGenotype()); return this; } /** * The optimization strategy used by the engine. <i>Default values is set to {@code * Optimize.MAXIMUM}.</i> * * @param optimize the optimization strategy used by the engine * @return {@code this} builder, for command chaining */ public Builder<G, C> optimize(final Optimize optimize) { _optimize = requireNonNull(optimize); return this; } /** * Set to a fitness maximizing strategy. * * @since 3.4 * @return {@code this} builder, for command chaining */ public Builder<G, C> maximizing() { return optimize(Optimize.MAXIMUM); } /** * Set to a fitness minimizing strategy. * * @since 3.4 * @return {@code this} builder, for command chaining */ public Builder<G, C> minimizing() { return optimize(Optimize.MINIMUM); } /** * The offspring fraction. <i>Default values is set to {@code 0.6}.</i> * * @param fraction the offspring fraction * @return {@code this} builder, for command chaining * @throws java.lang.IllegalArgumentException if the fraction is not within the range [0, 1]. */ public Builder<G, C> offspringFraction(final double fraction) { _offspringFraction = probability(fraction); return this; } /** * The number of individuals which form the population. <i>Default values is set to {@code * 50}.</i> * * @param size the number of individuals of a population * @return {@code this} builder, for command chaining * @throws java.lang.IllegalArgumentException if {@code size < 1} */ public Builder<G, C> populationSize(final int size) { if (size < 1) { throw new IllegalArgumentException( format("Population size must be greater than zero, but was %s.", size)); } _populationSize = size; return this; } /** * The maximal allowed age of a phenotype. <i>Default values is set to {@code 70}.</i> * * @param age the maximal phenotype age * @return {@code this} builder, for command chaining * @throws java.lang.IllegalArgumentException if {@code age < 1} */ public Builder<G, C> maximalPhenotypeAge(final long age) { if (age < 1) { throw new IllegalArgumentException( format("Phenotype age must be greater than one, but was %s.", age)); } _maximalPhenotypeAge = age; return this; } /** * The executor used by the engine. * * @param executor the executor used by the engine * @return {@code this} builder, for command chaining */ public Builder<G, C> executor(final Executor executor) { _executor = requireNonNull(executor); return this; } /** * The clock used for calculating the execution durations. * * @param clock the clock used for calculating the execution durations * @return {@code this} builder, for command chaining */ public Builder<G, C> clock(final Clock clock) { _clock = requireNonNull(clock); return this; } /** * The maximal number of attempt before the {@code Engine} gives up creating a valid individual * ({@code Phenotype}). <i>Default values is set to {@code 10}.</i> * * @since 3.1 * @param retries the maximal retry count * @throws IllegalArgumentException if the given retry {@code count} is smaller than zero. * @return {@code this} builder, for command chaining */ public Builder<G, C> individualCreationRetries(final int retries) { if (retries < 0) { throw new IllegalArgumentException(format("Retry count must not be negative: %d", retries)); } _individualCreationRetries = retries; return this; } /** * Builds an new {@code Engine} instance from the set properties. * * @return an new {@code Engine} instance from the set properties */ public Engine<G, C> build() { return new Engine<>( _fitnessFunction, _fitnessScaler, _genotypeFactory, _survivorsSelector, _offspringSelector, _alterer, _validator, _optimize, getOffspringCount(), getSurvivorsCount(), _maximalPhenotypeAge, _executor, _clock, _individualCreationRetries); } private int getSurvivorsCount() { return _populationSize - getOffspringCount(); } private int getOffspringCount() { return (int) round(_offspringFraction * _populationSize); } /** * Return the used {@link Alterer} of the GA. * * @return the used {@link Alterer} of the GA. */ public Alterer<G, C> getAlterers() { return _alterer; } /** * Return the {@link Clock} the engine is using for measuring the execution time. * * @since 3.1 * @return the clock used for measuring the execution time */ public Clock getClock() { return _clock; } /** * Return the {@link Executor} the engine is using for executing the evolution steps. * * @since 3.1 * @return the executor used for performing the evolution steps */ public Executor getExecutor() { return _executor; } /** * Return the fitness function of the GA engine. * * @since 3.1 * @return the fitness function */ public Function<? super Genotype<G>, ? extends C> getFitnessFunction() { return _fitnessFunction; } /** * Return the fitness scaler of the GA engine. * * @since 3.1 * @return the fitness scaler */ public Function<? super C, ? extends C> getFitnessScaler() { return _fitnessScaler; } /** * Return the used genotype {@link Factory} of the GA. The genotype factory is used for creating * the initial population and new, random individuals when needed (as replacement for invalid * and/or died genotypes). * * @since 3.1 * @return the used genotype {@link Factory} of the GA. */ public Factory<Genotype<G>> getGenotypeFactory() { return _genotypeFactory; } /** * Return the maximal allowed phenotype age. * * @since 3.1 * @return the maximal allowed phenotype age */ public long getMaximalPhenotypeAge() { return _maximalPhenotypeAge; } /** * Return the offspring fraction. * * @return the offspring fraction. */ public double getOffspringFraction() { return _offspringFraction; } /** * Return the used offspring {@link Selector} of the GA. * * @since 3.1 * @return the used offspring {@link Selector} of the GA. */ public Selector<G, C> getOffspringSelector() { return _offspringSelector; } /** * Return the used survivor {@link Selector} of the GA. * * @since 3.1 * @return the used survivor {@link Selector} of the GA. */ public Selector<G, C> getSurvivorsSelector() { return _survivorsSelector; } /** * Return the optimization strategy. * * @since 3.1 * @return the optimization strategy */ public Optimize getOptimize() { return _optimize; } /** * Return the number of individuals of a population. * * @since 3.1 * @return the number of individuals of a population */ public int getPopulationSize() { return _populationSize; } /** * Return the maximal number of attempt before the {@code Engine} gives up creating a valid * individual ({@code Phenotype}). * * @since 3.1 * @return the maximal number of {@code Phenotype} creation attempts */ public int getIndividualCreationRetries() { return _individualCreationRetries; } /** * Create a new builder, with the current configuration. * * @since 3.1 * @return a new builder, with the current configuration */ @Override public Builder<G, C> copy() { return new Builder<>(_genotypeFactory, _fitnessFunction) .alterers(_alterer) .clock(_clock) .executor(_executor) .fitnessScaler(_fitnessScaler) .maximalPhenotypeAge(_maximalPhenotypeAge) .offspringFraction(_offspringFraction) .offspringSelector(_offspringSelector) .phenotypeValidator(_validator) .optimize(_optimize) .populationSize(_populationSize) .survivorsSelector(_survivorsSelector) .individualCreationRetries(_individualCreationRetries); } }