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 G extends Gene<?, G>,
054 C 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 }
|