EvolutionStream.java
001 /*
002  * Java Genetic Algorithm Library (jenetics-5.2.0).
003  * Copyright (c) 2007-2020 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.engine;
021 
022 import java.util.function.Function;
023 import java.util.function.Predicate;
024 import java.util.function.Supplier;
025 import java.util.stream.Stream;
026 
027 import io.jenetics.Gene;
028 import io.jenetics.internal.engine.EvolutionStreamImpl;
029 
030 /**
031  * The {@code EvolutionStream} class extends the Java {@link Stream} and adds a
032  * method for limiting the evolution by a given predicate.
033  *
034  * @implNote Collecting an <em>empty</em> {@code EvolutionStream} will return
035  *           {@code null}.
036  <pre>{@code
037  * final EvolutionResult<DoubleGene, Double> result = engine.stream()
038  *     .limit(0)
039  *     .collect(toBestEvolutionResult());
040  *
041  * assert result == null;
042  * }</pre>
043  *
044  @see java.util.stream.Stream
045  @see Engine
046  @see EvolutionStreamable
047  *
048  @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
049  @since 3.0
050  @version 5.1
051  */
052 public interface EvolutionStream<
053     extends Gene<?, G>,
054     extends Comparable<? super C>
055 >
056     extends Stream<EvolutionResult<G, C>>
057 {
058 
059     /**
060      * Returns a stream consisting of the elements of this stream, truncated
061      * when the given {@code proceed} predicate returns {@code false}.
062      <p>
063      <i>General usage example:</i>
064      <pre>{@code
065      * final Phenotype<DoubleGene, Double> result = engine.stream()
066      *      // Truncate the evolution stream after 5 "steady" generations.
067      *     .limit(bySteadyFitness(5))
068      *      // The evolution will stop after maximal 100 generations.
069      *     .limit(100)
070      *     .collect(toBestPhenotype());
071      * }</pre>
072      *
073      <b>Note:</b>
074      * The evolution result may be {@code null}, if your <em>truncation</em>
075      * predicate returns {@code false} for the initial population.
076      <pre>{@code
077      * final EvolutionResult<DoubleGene, Double> result = engine.stream()
078      *     .limit(er -> false)
079      *     .collect(toBestEvolutionResult());
080      *
081      * assert result == null;
082      * }</pre>
083      *
084      @see Limits
085      *
086      @param proceed the predicate which determines whether the stream is
087      *        truncated or not. <i>If the predicate returns {@code false}, the
088      *        evolution stream is truncated.</i>
089      @return the new stream
090      @throws NullPointerException if the given predicate is {@code null}.
091      */
092     EvolutionStream<G, C>
093     limit(final Predicate<? super EvolutionResult<G, C>> proceed);
094 
095     /**
096      * Create a new {@code EvolutionStream} from the given {@code start}
097      * population and {@code evolution} function. The main purpose of this
098      * factory method is to simplify the creation of an {@code EvolutionStream}
099      * from an own evolution (GA) engine.
100      *
101      @since 3.1
102      *
103      @see #ofEvolution(Supplier, Evolution)
104      *
105      @param <G> the gene type
106      @param <C> the fitness type
107      @param start the evolution start
108      @param evolution the evolution function
109      @return a new {@code EvolutionStream} with the given {@code start} and
110      *         {@code evolution} function
111      @throws java.lang.NullPointerException if one of the arguments is
112      *         {@code null}
113      *
114      @deprecated Will be removed, use {@link #ofEvolution(Supplier, Evolution)}
115      *             instead
116      */
117     @Deprecated
118     static <G extends Gene<?, G>, C extends Comparable<? super C>>
119     EvolutionStream<G, C> of(
120         final Supplier<EvolutionStart<G, C>> start,
121         final Function<? super EvolutionStart<G, C>, EvolutionResult<G, C>> evolution
122     ) {
123         return new EvolutionStreamImpl<>(start, evolution::apply);
124     }
125 
126     /**
127      * Create a new {@code EvolutionStream} from the given {@code start}
128      * population and {@code evolution} function. The main purpose of this
129      * factory method is to simplify the creation of an {@code EvolutionStream}
130      * from an own evolution (GA) engine.
131      *
132      <pre>{@code
133      * final Supplier<EvolutionStart<DoubleGene, Double>> start = ...
134      * final EvolutionStream<DoubleGene, Double> stream =
135      *     EvolutionStream.of(start, new MySpecialEngine());
136      * }</pre>
137      *
138      * A more complete example for would look like as:
139      *
140      <pre>{@code
141      * public final class SpecialEngine {
142      *
143      *     // The fitness function.
144      *     private static Double fitness(final Genotype<DoubleGene> gt) {
145      *         return gt.gene().allele();
146      *     }
147      *
148      *     // Create new evolution start object.
149      *     private static EvolutionStart<DoubleGene, Double>
150      *     start(final int populationSize, final long generation) {
151      *         final Population<DoubleGene, Double> population =
152      *             Genotype.of(DoubleChromosome.of(0, 1)).instances()
153      *                 .map(gt -> Phenotype.of(gt, generation, SpecialEngine::fitness))
154      *                 .limit(populationSize)
155      *                 .collect(Population.toPopulation());
156      *
157      *         return EvolutionStart.of(population, generation);
158      *     }
159      *
160      *     // The special evolution function.
161      *     private static EvolutionResult<DoubleGene, Double>
162      *     evolve(final EvolutionStart<DoubleGene, Double> start) {
163      *         // Your special evolution implementation comes here!
164      *         return null;
165      *     }
166      *
167      *     public static void main(final String[] args) {
168      *         final Genotype<DoubleGene> best = EvolutionStream
169      *             .ofEvolution(() -> start(50, 0), SpecialEngine::evolve)
170      *             .limit(Limits.bySteadyFitness(10))
171      *             .limit(1000)
172      *             .collect(EvolutionResult.toBestGenotype());
173      *
174      *         System.out.println(String.format("Best Genotype: %s", best));
175      *     }
176      * }
177      * }</pre>
178      *
179      *
180      @since 5.1
181      *
182      @see #ofAdjustableEvolution(Supplier, Function)
183      *
184      @param <G> the gene type
185      @param <C> the fitness type
186      @param start the evolution start
187      @param evolution the evolution function
188      @return a new {@code EvolutionStream} with the given {@code start} and
189      *         {@code evolution} function
190      @throws java.lang.NullPointerException if one of the arguments is
191      *         {@code null}
192      */
193     static <G extends Gene<?, G>, C extends Comparable<? super C>>
194     EvolutionStream<G, C> ofEvolution(
195         final Supplier<EvolutionStart<G, C>> start,
196         final Evolution<G, C> evolution
197     ) {
198         return new EvolutionStreamImpl<>(start, evolution);
199     }
200 
201     /**
202      * Create a new evolution stream with an <em>adjustable</em> evolution
203      * function.
204      *
205      <pre>{@code
206      * public static void main(final String[] args) {
207      *     final Problem<double[], DoubleGene, Double> problem = Problem.of(
208      *         v -> Math.sin(v[0])*Math.cos(v[1]),
209      *         Codecs.ofVector(DoubleRange.of(0, 2*Math.PI), 2)
210      *     );
211      *
212      *     // Engine builder template.
213      *     final Engine.Builder<DoubleGene, Double> builder = Engine
214      *         .builder(problem)
215      *         .minimizing();
216      *
217      *     // Evolution used for low fitness variance.
218      *     final Evolution<DoubleGene, Double> lowVar = builder.copy()
219      *         .alterers(new Mutator<>(0.5))
220      *         .selector(new MonteCarloSelector<>())
221      *         .build();
222      *
223      *     // Evolution used for high fitness variance.
224      *     final Evolution<DoubleGene, Double> highVar = builder.copy()
225      *         .alterers(
226      *             new Mutator<>(0.05),
227      *             new MeanAlterer<>())
228      *         .selector(new RouletteWheelSelector<>())
229      *         .build();
230      *
231      *     final EvolutionStream<DoubleGene, Double> stream =
232      *         EvolutionStream.ofAdjustableEvolution(
233      *             EvolutionStart::empty,
234      *             er -> var(er) < 0.2 ? lowVar : highVar
235      *         );
236      *
237      *     final Genotype<DoubleGene> result = stream
238      *         .limit(Limits.bySteadyFitness(50))
239      *         .collect(EvolutionResult.toBestGenotype());
240      *
241      *     System.out.println(result + ": " +
242      *         problem.fitness().apply(problem.codec().decode(result)));
243      * }
244      *
245      * private static double var(final EvolutionStart<DoubleGene, Double> result) {
246      *     return result != null
247      *         ? result.getPopulation().stream()
248      *             .map(Phenotype::fitness)
249      *             .collect(DoubleMoments.toDoubleMoments())
250      *             .variance()
251      *         : 0.0;
252      * }
253      * }</pre>
254      *
255      @see #ofEvolution(Supplier, Evolution)
256      *
257      @param start the evolution start object
258      @param evolution the adaptable evolution function
259      @param <G> the gene type
260      @param <C> the fitness type
261      @return a new {@code EvolutionStream} with the given {@code start} and
262      *         {@code evolution} function
263      @throws java.lang.NullPointerException if one of the arguments is
264      *         {@code null}
265      */
266     static <G extends Gene<?, G>, C extends Comparable<? super C>>
267     EvolutionStream<G, C> ofAdjustableEvolution(
268         final Supplier<EvolutionStart<G, C>> start,
269         final Function<
270             super EvolutionStart<G, C>,
271             extends Evolution<G, C>> evolution
272     ) {
273         return EvolutionStreamImpl.of(start, evolution);
274     }
275 
276 }