Example #1
0
    /**
     * 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;
    }
Example #2
0
  /**
   * 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);
    }
  }
Example #3
0
 // Alters the given population. The altering is done in place.
 private AlterResult<G, C> alter(final Population<G, C> population, final long generation) {
   return new AlterResult<>(population, _alterer.alter(population, generation));
 }