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