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 — <em>$Date: 2014-12-28 $</em>
050 */
051 public final class EvolutionResult<
052 G extends Gene<?, G>,
053 C 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 }
|