| 
001 /*002  * Java Genetic Algorithm Library (jenetics-4.3.0).
 003  * Copyright (c) 2007-2018 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  */
 020 package io.jenetics.ext.engine;
 021
 022 import static java.util.Objects.requireNonNull;
 023
 024 import java.util.Spliterator;
 025 import java.util.function.Function;
 026 import java.util.function.Supplier;
 027
 028 import io.jenetics.Gene;
 029 import io.jenetics.engine.EvolutionInit;
 030 import io.jenetics.engine.EvolutionResult;
 031 import io.jenetics.engine.EvolutionStart;
 032 import io.jenetics.engine.EvolutionStream;
 033 import io.jenetics.engine.EvolutionStreamable;
 034 import io.jenetics.internal.engine.EvolutionStreamImpl;
 035
 036 import io.jenetics.ext.internal.GeneratorSpliterator;
 037
 038 /**
 039  * The {@code AdaptiveEngine} allows you to dynamically create engines with
 040  * different configurations, depending on the last {@link EvolutionResult} of
 041  * the previous evolution stream. It is therefore possible to increase the
 042  * mutation probability if the population is converging to fast. The sketch
 043  * below shows how the {@code AdaptiveEngine} is working.
 044  *
 045  * <pre> {@code
 046  *                                           +----------+
 047  *                                           |   ES[i]  |
 048  *           +-------------------------------+------+   |
 049  *           |                                      +---+
 050  *   (Start) |  EvolutionResult[i-1] -> Engine[i]   |-----------+-->
 051  *  -----+-->|           ^                          |  Result   |
 052  *       ^   +-----------|--------------------------+           |
 053  *       |               |                                      |
 054  *       +---------------+--------------<-----------------------+
 055  * }</pre>
 056  *
 057  *
 058  * <pre>{@code
 059  *  public static void main(final String[] args) {
 060  *      final Problem<double[], DoubleGene, Double> problem = Problem.of(
 061  *          v -> Math.sin(v[0])*Math.cos(v[1]),
 062  *          Codecs.ofVector(DoubleRange.of(0, 2*Math.PI), 2)
 063  *      );
 064  *
 065  *      final Engine.Builder<DoubleGene, Double> builder = Engine
 066  *          .builder(problem)
 067  *          .minimizing();
 068  *
 069  *      final Genotype<DoubleGene> result =
 070  *          AdaptiveEngine.<DoubleGene, Double>of(er -> engine(er, builder))
 071  *              .stream()
 072  *              .limit(Limits.bySteadyFitness(50))
 073  *              .collect(EvolutionResult.toBestGenotype());
 074  *
 075  *      System.out.println(result + ": " +
 076  *          problem.fitness().apply(problem.codec().decode(result)));
 077  *  }
 078  *
 079  *  private static EvolutionStreamable<DoubleGene, Double> engine(
 080  *      final EvolutionResult<DoubleGene, Double> result,
 081  *      final Engine.Builder<DoubleGene, Double> builder
 082  *  ) {
 083  *      return var(result) < 0.2
 084  *          ? builder
 085  *              .alterers(new Mutator<>(0.5))
 086  *              .build()
 087  *              .limit(5)
 088  *          : builder
 089  *              .alterers(
 090  *                  new Mutator<>(0.05),
 091  *                  new MeanAlterer<>())
 092  *              .selector(new RouletteWheelSelector<>())
 093  *              .build()
 094  *              .limit(15);
 095  *  }
 096  *
 097  *  private static double var(final EvolutionResult<DoubleGene, Double> result) {
 098  *      return result != null
 099  *          ? result.getPopulation().stream()
 100  *              .map(Phenotype::getFitness)
 101  *              .collect(DoubleMoments.toDoubleMoments(Double::doubleValue))
 102  *              .getVariance()
 103  *          : 0.0;
 104  *  }
 105  * }</pre>
 106  *
 107  * @see ConcatEngine
 108  * @see CyclicEngine
 109  *
 110  * @param <G> the gene type
 111  * @param <C> the fitness type
 112  *
 113  * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
 114  * @version 4.1
 115  * @since 4.1
 116  */
 117 public final class AdaptiveEngine<
 118     G extends Gene<?, G>,
 119     C extends Comparable<? super C>
 120 >
 121     implements EvolutionStreamable<G, C>
 122 {
 123
 124     private final Function<
 125         ? super EvolutionResult<G, C>,
 126         ? extends EvolutionStreamable<G, C>> _engine;
 127
 128     /**
 129      * Return a new adaptive evolution engine, with the given engine generation
 130      * function.
 131      *
 132      * @param engine the engine generating function used for adapting the engines.
 133      * @throws NullPointerException if the given {@code engine} is {@code null}
 134      */
 135     public AdaptiveEngine(
 136         final Function<
 137             ? super EvolutionResult<G, C>,
 138             ? extends EvolutionStreamable<G, C>> engine
 139     ) {
 140         _engine = requireNonNull(engine);
 141     }
 142
 143     @Override
 144     public EvolutionStream<G, C>
 145     stream(final Supplier<EvolutionStart<G, C>> start) {
 146         return new EvolutionStreamImpl<G, C>(
 147             new GeneratorSpliterator<>(result -> generate(start, result)),
 148             false
 149         );
 150     }
 151
 152     private Spliterator<EvolutionResult<G, C>>
 153     generate(
 154         final Supplier<EvolutionStart<G, C>> start,
 155         final EvolutionResult<G, C> result
 156     ) {
 157         final EvolutionStart<G, C> es = result == null
 158             ? start.get()
 159             : result.toEvolutionStart();
 160
 161         return _engine.apply(result)
 162             .stream(es)
 163             .spliterator();
 164     }
 165
 166     @Override
 167     public EvolutionStream<G, C> stream(final EvolutionInit<G> init) {
 168         return new EvolutionStreamImpl<G, C>(
 169             new GeneratorSpliterator<>(result -> generate(init, result)),
 170             false
 171         );
 172     }
 173
 174     private Spliterator<EvolutionResult<G, C>>
 175     generate(
 176         final EvolutionInit<G> init,
 177         final EvolutionResult<G, C> result
 178     ) {
 179         return result == null
 180             ? _engine.apply(null)
 181                 .stream(init)
 182                 .spliterator()
 183             : _engine.apply(result)
 184                 .stream(result.toEvolutionStart())
 185                 .spliterator();
 186     }
 187
 188     /**
 189      * Return a new adaptive evolution engine, with the given engine generation
 190      * function.
 191      *
 192      * @param engine the engine generating function used for adapting the engines.
 193      *       <b>Be aware, that the {@code EvolutionResult} for the first created
 194      *       {@code Engine} is {@code null}.</b>
 195      * @param <G> the gene type
 196      * @param <C> the fitness type
 197      * @return a new adaptive evolution engine
 198      * @throws NullPointerException if the given {@code engine} is {@code null}
 199      */
 200     public static <G extends Gene<?, G>, C extends Comparable<? super C>>
 201     AdaptiveEngine<G, C> of(
 202         final Function<
 203             ? super EvolutionResult<G, C>,
 204             ? extends EvolutionStreamable<G, C>> engine
 205     ) {
 206         return new AdaptiveEngine<>(engine);
 207     }
 208
 209 }
 |