EvolutionResult.java
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.util.Objects.requireNonNull;
023 import static org.jenetics.internal.util.Equality.eq;
024 import static org.jenetics.internal.util.require.safe;
025 
026 import java.io.Serializable;
027 import java.util.function.Supplier;
028 import java.util.stream.Collector;
029 
030 import org.jenetics.internal.util.Equality;
031 import org.jenetics.internal.util.Hash;
032 import org.jenetics.internal.util.Lazy;
033 
034 import org.jenetics.Gene;
035 import org.jenetics.Genotype;
036 import org.jenetics.Optimize;
037 import org.jenetics.Phenotype;
038 import org.jenetics.Population;
039 import org.jenetics.stat.MinMax;
040 
041 /**
042  * Represents a state of the GA after an evolution step.
043  *
044  @param <G> the gene type
045  @param <C> the fitness type
046  *
047  @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
048  @since 3.0
049  @version 3.0 &mdash; <em>$Date: 2014-12-28 $</em>
050  */
051 public final class EvolutionResult<
052     extends Gene<?, G>,
053     extends Comparable<? super C>
054 >
055     implements Comparable<EvolutionResult<G, C>>, Serializable
056 {
057     private static final long serialVersionUID = 1L;
058 
059     private final Optimize _optimize;
060     private final Population<G, C> _population;
061     private final long _generation;
062     private final long _totalGenerations;
063 
064     private final EvolutionDurations _durations;
065     private final int _killCount;
066     private final int _invalidCount;
067     private final int _alterCount;
068 
069     private final Lazy<Phenotype<G, C>> _best;
070     private final Lazy<Phenotype<G, C>> _worst;
071 
072     private EvolutionResult(
073         final Optimize optimize,
074         final Population<G, C> population,
075         final long generation,
076         final long totalGenerations,
077         final EvolutionDurations durations,
078         final int killCount,
079         final int invalidCount,
080         final int alterCount
081     ) {
082         _optimize = requireNonNull(optimize);
083         _population = requireNonNull(population);
084         _generation = generation;
085         _totalGenerations = totalGenerations;
086         _durations = requireNonNull(durations);
087         _killCount = killCount;
088         _invalidCount = invalidCount;
089         _alterCount = alterCount;
090 
091         _best = Lazy.of((Supplier<Phenotype<G, C>> & Serializable)this::best);
092         _worst = Lazy.of((Supplier<Phenotype<G, C>> & Serializable)this::worst);
093     }
094 
095     private Phenotype<G, C> best() {
096         return _population.stream().max(_optimize.ascending()).orElse(null);
097     }
098 
099     private Phenotype<G, C> worst() {
100         return _population.stream().min(_optimize.ascending()).orElse(null);
101     }
102 
103     /**
104      * Return the optimization strategy used.
105      *
106      @return the optimization strategy used
107      */
108     public Optimize getOptimize() {
109         return _optimize;
110     }
111 
112     /**
113      * Return the population after the evolution step.
114      *
115      @return the population after the evolution step
116      */
117     public Population<G, C> getPopulation() {
118         return _population;
119     }
120 
121     /**
122      * The current generation.
123      *
124      @return the current generation
125      */
126     public long getGeneration() {
127         return _generation;
128     }
129 
130     /**
131      * Return the generation count evaluated so far.
132      *
133      @return the total number of generations evaluated so far
134      */
135     public long getTotalGenerations() {
136         return _totalGenerations;
137     }
138 
139     /**
140      * Return the timing (meta) information of the evolution step.
141      *
142      @return the timing (meta) information of the evolution step
143      */
144     public EvolutionDurations getDurations() {
145         return _durations;
146     }
147 
148     /**
149      * Return the number of killed individuals.
150      *
151      @return the number of killed individuals
152      */
153     public int getKillCount() {
154         return _killCount;
155     }
156 
157     /**
158      * Return the number of invalid individuals.
159      *
160      @return the number of invalid individuals
161      */
162     public int getInvalidCount() {
163         return _invalidCount;
164     }
165 
166     /**
167      * The number of altered individuals.
168      *
169      @return the number of altered individuals
170      */
171     public int getAlterCount() {
172         return _alterCount;
173     }
174 
175     /**
176      * Return the best {@code Phenotype} of the result population.
177      *
178      @return the best {@code Phenotype} of the result population
179      */
180     public Phenotype<G, C> getBestPhenotype() {
181         return _best.get();
182     }
183 
184     /**
185      * Return the worst {@code Phenotype} of the result population.
186      *
187      @return the worst {@code Phenotype} of the result population
188      */
189     public Phenotype<G, C> getWorstPhenotype() {
190         return _worst.get();
191     }
192 
193     /**
194      * Return the best population fitness.
195      *
196      @return The best population fitness.
197      */
198     public C getBestFitness() {
199         return _best.get() != null ? _best.get().getFitness() null;
200     }
201 
202     /**
203      * Return the worst population fitness.
204      *
205      @return The worst population fitness.
206      */
207     public C getWorstFitness() {
208         return _worst.get() != null ? _worst.get().getFitness() null;
209     }
210 
211     /**
212      * Return the next evolution start object with the current population and
213      * the incremented generation.
214      *
215      @return the next evolution start object
216      */
217     EvolutionStart<G, C> next() {
218         return new EvolutionStart<>(_population, _generation + 1);
219     }
220 
221     /**
222      * Compare {@code this} evolution result with another one, according the
223      * populations best individual.
224      *
225      @param other the other evolution result to compare
226      @return  a negative integer, zero, or a positive integer as this result
227      *          is less than, equal to, or greater than the specified result.
228      */
229     @Override
230     public int compareTo(final EvolutionResult<G, C> other) {
231         return _optimize.compare(_best.get(), other._best.get());
232     }
233 
234     private EvolutionResult<G, C> withTotalGenerations(final long total) {
235         return of(
236             _optimize,
237             _population,
238             _generation,
239             total,
240             _durations,
241             _killCount,
242             _invalidCount,
243             _alterCount
244         );
245     }
246 
247     @Override
248     public int hashCode() {
249         return Hash.of(getClass())
250             .and(_optimize)
251             .and(_population)
252             .and(_generation)
253             .and(_totalGenerations)
254             .and(_durations)
255             .and(_killCount)
256             .and(_invalidCount)
257             .and(_alterCount)
258             .and(getBestFitness()).value();
259     }
260 
261     @Override
262     public boolean equals(final Object obj) {
263         return Equality.of(this, obj).test(result ->
264             eq(_optimize, result._optimize&&
265             eq(_population, result._population&&
266             eq(_generation, result._generation&&
267             eq(_totalGenerations, result._totalGenerations&&
268             eq(_durations, result._durations&&
269             eq(_killCount, result._killCount&&
270             eq(_invalidCount, result._invalidCount&&
271             eq(_alterCount, result._alterCount&&
272             eq(getBestFitness(), result.getBestFitness())
273         );
274     }
275 
276 
277 
278     /* *************************************************************************
279      *  Some static collector/factory methods.
280      * ************************************************************************/
281 
282     /**
283      * Return a collector which collects the best result of an evolution stream.
284      *
285      @param <G> the gene type
286      @param <C> the fitness type
287      @return a collector which collects the best result of an evolution stream
288      */
289     public static <G extends Gene<?, G>, C extends Comparable<? super C>>
290     Collector<EvolutionResult<G, C>, ?, EvolutionResult<G, C>>
291     toBestEvolutionResult() {
292         return Collector.of(
293             MinMax::<EvolutionResult<G, C>>of,
294             MinMax::accept,
295             MinMax::combine,
296             mm -> mm.getMax().withTotalGenerations(mm.getCount())
297         );
298     }
299 
300     /**
301      * Return a collector which collects the best phenotype of an evolution
302      * stream.
303      *
304      @param <G> the gene type
305      @param <C> the fitness type
306      @return a collector which collects the best phenotype of an evolution
307      *         stream
308      */
309     public static <G extends Gene<?, G>, C extends Comparable<? super C>>
310     Collector<EvolutionResult<G, C>, ?, Phenotype<G, C>>
311     toBestPhenotype() {
312         return Collector.of(
313             MinMax::<EvolutionResult<G, C>>of,
314             MinMax::accept,
315             MinMax::combine,
316             mm -> safe(() -> mm.getMax().getBestPhenotype())
317         );
318     }
319 
320     /**
321      * Return a collector which collects the best genotype of an evolution
322      * stream.
323      *
324      @param <G> the gene type
325      @param <C> the fitness type
326      @return a collector which collects the best genotype of an evolution
327      *         stream
328      */
329     public static <G extends Gene<?, G>, C extends Comparable<? super C>>
330     Collector<EvolutionResult<G, C>, ?, Genotype<G>>
331     toBestGenotype() {
332         return Collector.of(
333             MinMax::<EvolutionResult<G, C>>of,
334             MinMax::accept,
335             MinMax::combine,
336             mm -> safe(() -> mm.getMax().getBestPhenotype().getGenotype())
337         );
338     }
339 
340     /**
341      * Return an new {@code EvolutionResult} object with the given values.
342      *
343      @param optimize the optimization strategy used
344      @param population the population after the evolution step
345      @param generation the current generation
346      @param totalGenerations the overall number of generations
347      @param durations the timing (meta) information
348      @param killCount the number of individuals which has been killed
349      @param invalidCount the number of individuals which has been removed as
350      *        invalid
351      @param alterCount the number of individuals which has been altered
352      @param <G> the gene type
353      @param <C> the fitness type
354      @return an new evolution result object
355      @throws java.lang.NullPointerException if one of the parameters is
356      *         {@code null}
357      */
358     public static <G extends Gene<?, G>, C extends Comparable<? super C>>
359     EvolutionResult<G, C> of(
360         final Optimize optimize,
361         final Population<G, C> population,
362         final long generation,
363         final long totalGenerations,
364         final EvolutionDurations durations,
365         final int killCount,
366         final int invalidCount,
367         final int alterCount
368     ) {
369         return new EvolutionResult<>(
370             optimize,
371             population,
372             generation,
373             totalGenerations,
374             durations,
375             killCount,
376             invalidCount,
377             alterCount
378         );
379     }
380 
381     /**
382      * Return an new {@code EvolutionResult} object with the given values.
383      *
384      @param optimize the optimization strategy used
385      @param population the population after the evolution step
386      @param generation the current generation
387      @param durations the timing (meta) information
388      @param killCount the number of individuals which has been killed
389      @param invalidCount the number of individuals which has been removed as
390      *        invalid
391      @param alterCount the number of individuals which has been altered
392      @param <G> the gene type
393      @param <C> the fitness type
394      @return an new evolution result object
395      @throws java.lang.NullPointerException if one of the parameters is
396      *         {@code null}
397      */
398     public static <G extends Gene<?, G>, C extends Comparable<? super C>>
399     EvolutionResult<G, C> of(
400         final Optimize optimize,
401         final Population<G, C> population,
402         final long generation,
403         final EvolutionDurations durations,
404         final int killCount,
405         final int invalidCount,
406         final int alterCount
407     ) {
408         return new EvolutionResult<>(
409             optimize,
410             population,
411             generation,
412             generation,
413             durations,
414             killCount,
415             invalidCount,
416             alterCount
417         );
418     }
419 
420 }