001 /*
002 * Java Genetic Algorithm Library (jenetics-2.0.2).
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;
021
022 import static java.lang.Double.NaN;
023 import static java.lang.String.format;
024 import static java.util.Objects.requireNonNull;
025 import static org.jenetics.internal.util.object.eq;
026
027 import java.io.Serializable;
028 import java.util.concurrent.Executor;
029
030 import org.jenetics.internal.util.HashBuilder;
031
032 import org.jenetics.stat.Variance;
033 import org.jenetics.util.Duration;
034 import org.jenetics.util.FinalReference;
035 import org.jenetics.util.accumulators;
036 import org.jenetics.util.accumulators.MinMax;
037
038 /**
039 * Data object which holds performance indicators of a given {@link Population}.
040 *
041 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
042 * @since 1.0
043 * @version 2.0 — <em>$Date: 2014-04-05 $</em>
044 */
045 public class Statistics<G extends Gene<?, G>, C extends Comparable<? super C>>
046 implements Serializable
047 {
048
049 /**
050 * Builder for the Statistics class.
051 *
052 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
053 * @since 1.0
054 * @version 2.0 — <em>$Date: 2014-04-05 $</em>
055 */
056 public static class Builder<
057 G extends Gene<?, G>,
058 C extends Comparable<? super C>
059 >
060 {
061 protected Optimize _optimize = Optimize.MAXIMUM;
062 protected int _generation = 0;
063 protected Phenotype<G, C> _best = null;
064 protected Phenotype<G, C> _worst = null;
065 protected int _samples = 0;
066 protected double _ageMean = NaN;
067 protected double _ageVariance = NaN;
068 protected int _killed = 0;
069 protected int _invalid = 0;
070
071 /**
072 * Create a new Statistics builder.
073 */
074 public Builder() {
075 }
076
077 /**
078 * Set the values of this builder with the values of the given
079 * {@code statistics}.
080 *
081 * @param statistics the statistics values. If the {@code statistics}
082 * is {@code null} nothing is set.
083 * @return this builder instance.
084 */
085 public Builder<G, C> statistics(final Statistics<G, C> statistics) {
086 if (statistics != null) {
087 _optimize = statistics._optimize;
088 _generation = statistics._generation;
089 _best = statistics._best;
090 _worst = statistics._worst;
091 _samples = statistics._samples;
092 _ageMean = statistics._ageMean;
093 _ageVariance = statistics._ageVariance;
094 _killed = statistics._killed;
095 _invalid = statistics._invalid;
096 }
097 return this;
098 }
099
100 public Builder<G, C> optimize(final Optimize optimize) {
101 _optimize = requireNonNull(optimize, "Optimize strategy");
102 return this;
103 }
104
105 /**
106 * @see Statistics#getGeneration()
107 *
108 * @param generation the current GA generation
109 * @return this builder instance
110 */
111 public Builder<G, C> generation(final int generation) {
112 _generation = generation;
113 return this;
114 }
115
116 /**
117 * @see Statistics#getBestPhenotype()
118 *
119 * @param best the best phenotype
120 * @return this builder instance
121 */
122 public Builder<G, C> bestPhenotype(final Phenotype<G, C> best) {
123 _best = best;
124 return this;
125 }
126
127 /**
128 * @see Statistics#getWorstPhenotype()
129 *
130 * @param worst the worst phenotype
131 * @return this builder instance
132 */
133 public Builder<G, C> worstPhenotype(final Phenotype<G, C> worst) {
134 _worst = worst;
135 return this;
136 }
137
138 /**
139 * @see Statistics#getSamples()
140 *
141 * @param samples the number of samples for the statistics object.
142 * @return this builder instance
143 */
144 public Builder<G, C> samples(final int samples) {
145 _samples = samples;
146 return this;
147 }
148
149 /**
150 * @see Statistics#getAgeMean()
151 *
152 * @param ageMean the mean of the population age
153 * @return this builder instance
154 */
155 public Builder<G, C> ageMean(final double ageMean) {
156 _ageMean = ageMean;
157 return this;
158 }
159
160 /**
161 * @see Statistics#getAgeVariance()
162 *
163 * @param ageVariance the variance of the population age
164 * @return this builder instance
165 */
166 public Builder<G, C> ageVariance(final double ageVariance) {
167 _ageVariance = ageVariance;
168 return this;
169 }
170
171 /**
172 * @see Statistics#getInvalid()
173 *
174 * @param invalid the number of valid individuals
175 * @return this builder instance
176 */
177 public Builder<G, C> invalid(final int invalid) {
178 _invalid = invalid;
179 return this;
180 }
181
182 /**
183 * @see Statistics#getKilled()
184 *
185 * @param killed the number of killed individuals
186 * @return this builder instance
187 */
188 public Builder<G, C> killed(final int killed) {
189 _killed = killed;
190 return this;
191 }
192
193 /**
194 * Return a new Statistics object with the builder values.
195 *
196 * @return new Statistics object with the builder values.
197 */
198 public Statistics<G, C> build() {
199 return new Statistics<>(
200 _optimize,
201 _generation,
202 _best,
203 _worst,
204 _samples,
205 _ageMean,
206 _ageVariance,
207 _killed,
208 _invalid
209 );
210 }
211 }
212
213 private static final long serialVersionUID = 3L;
214
215 protected final Optimize _optimize;
216 protected final int _generation;
217 protected final Phenotype<G, C> _best;
218 protected final Phenotype<G, C> _worst;
219 protected final int _samples;
220 protected final double _ageMean;
221 protected final double _ageVariance;
222 protected final int _killed;
223 protected final int _invalid;
224
225 private final FinalReference<Time> _time = new FinalReference<>(new Time());
226
227
228 /**
229 * Evaluates statistic values from a given population. The given phenotypes
230 * may be {@code null}
231 *
232 * @param optimize the optimization strategy used
233 * @param generation the generation for this statistics
234 * @param best best phenotype
235 * @param worst worst phenotype
236 * @param samples number of samples of this statistics
237 * @param ageMean the mean value of the individuals age
238 * @param ageVariance the variance value of the individuals ages
239 * @param killed the number of killed individuals
240 * @param invalid the number of invalid individuals
241 */
242 protected Statistics(
243 final Optimize optimize,
244 final int generation,
245 final Phenotype<G, C> best,
246 final Phenotype<G, C> worst,
247 final int samples,
248 final double ageMean,
249 final double ageVariance,
250 final int killed,
251 final int invalid
252 ) {
253 _optimize = optimize;
254 _generation = generation;
255 _best = best;
256 _worst = worst;
257 _samples = samples;
258 _ageMean = ageMean;
259 _ageVariance = ageVariance;
260 _killed = killed;
261 _invalid = invalid;
262 }
263
264 /**
265 * Return the optimize strategy of the GA.
266 *
267 * @return the optimize strategy of the GA.
268 */
269 public Optimize getOptimize() {
270 return _optimize;
271 }
272
273 /**
274 * Return the generation of this statistics.
275 *
276 * @return the generation of this statistics.
277 */
278 public int getGeneration() {
279 return _generation;
280 }
281
282 /**
283 * Return the time statistic object which contains the durations of the
284 * different GA execution steps.
285 *
286 * @return the time statistic object.
287 */
288 public Time getTime() {
289 return _time.get();
290 }
291
292 /**
293 * Return the best population Phenotype.
294 *
295 * @return The best population Phenotype.
296 */
297 public Phenotype<G, C> getBestPhenotype() {
298 return _best;
299 }
300
301 /**
302 * Return the worst population Phenotype.
303 *
304 * @return The worst population Phenotype.
305 */
306 public Phenotype<G, C> getWorstPhenotype() {
307 return _worst;
308 }
309
310 /**
311 * Return the best population fitness.
312 *
313 * @return The best population fitness.
314 */
315 public C getBestFitness() {
316 return _best != null ? _best.getFitness() : null;
317 }
318
319 /**
320 * Return the worst population fitness.
321 *
322 * @return The worst population fitness.
323 */
324 public C getWorstFitness() {
325 return _worst != null ? _worst.getFitness() : null;
326 }
327
328 /**
329 * Return the number of samples this statistics has aggregated.
330 *
331 * @return the number of samples this statistics has aggregated.
332 */
333 public int getSamples() {
334 return _samples;
335 }
336
337 /**
338 * Return the average (mean) age of the individuals of the aggregated
339 * population.
340 *
341 * @return the average population age.
342 */
343 public double getAgeMean() {
344 return _ageMean;
345 }
346
347 /**
348 * Return the age variance of the individuals of the aggregated population.
349 *
350 * @return the age variance of the individuals of the aggregated population.
351 */
352 public double getAgeVariance() {
353 return _ageVariance;
354 }
355
356 /**
357 * Return the number of invalid individuals.
358 *
359 * @return the number of invalid individuals.
360 */
361 public int getInvalid() {
362 return _invalid;
363 }
364
365 /**
366 * Return the number of killed individuals.
367 *
368 * @return the number of killed individuals.
369 */
370 public int getKilled() {
371 return _killed;
372 }
373
374 @Override
375 public int hashCode() {
376 return HashBuilder.of(getClass()).
377 and(_optimize).
378 and(_generation).
379 and(_ageMean).
380 and(_ageVariance).
381 and(_best).
382 and(_worst).
383 and(_invalid).
384 and(_samples).
385 and(_killed).value();
386 }
387
388 @Override
389 public boolean equals(final Object obj) {
390 if (obj == this) {
391 return true;
392 }
393 if (obj == null || getClass() != obj.getClass()) {
394 return false;
395 }
396
397 final Statistics<?, ?> statistics = (Statistics<?, ?>)obj;
398 return eq(_optimize, statistics._optimize) &&
399 eq(_generation, statistics._generation) &&
400 eq(_ageMean, statistics._ageMean) &&
401 eq(_ageVariance, statistics._ageVariance) &&
402 eq(_best, statistics._best) &&
403 eq(_worst, statistics._worst) &&
404 eq(_invalid, statistics._invalid) &&
405 eq(_samples, statistics._samples) &&
406 eq(_killed, statistics._killed);
407 }
408
409 @Override
410 public String toString() {
411 final String spattern = "| %28s: %-26s|\n";
412 final String fpattern = "| %28s: %-26.11f|\n";
413 final String ipattern = "| %28s: %-26d|\n";
414
415 final StringBuilder out = new StringBuilder();
416 out.append("+---------------------------------------------------------+\n");
417 out.append("| Population Statistics |\n");
418 out.append("+---------------------------------------------------------+\n");
419 out.append(format(fpattern, "Age mean", _ageMean));
420 out.append(format(fpattern, "Age variance", _ageVariance));
421 out.append(format(ipattern, "Samples", _samples));
422 out.append(format(spattern, "Best fitness", getBestFitness()));
423 out.append(format(spattern, "Worst fitness", getWorstFitness()));
424 out.append("+---------------------------------------------------------+");
425
426 return out.toString();
427 }
428
429 /**
430 * Class which holds time statistic values.
431 *
432 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
433 * @since 1.0
434 * @version 2.0 — <em>$Date: 2014-04-05 $</em>
435 */
436 public static final class Time implements Serializable {
437 private static final long serialVersionUID = 2L;
438
439 private static final Duration ZERO = Duration.ofNanos(0);
440
441 /**
442 * Create a new time object with zero time values. The time references
443 * can only be set once. If you try to set the values twice an
444 * {@link IllegalStateException} is thrown.
445 */
446 public Time() {
447 }
448
449 /**
450 * The overall execution time.
451 * The time can be set only once, otherwise an IllegalArgumentException
452 * is thrown.
453 */
454 public final FinalReference<Duration>
455 execution = new FinalReference<>(ZERO);
456
457 /**
458 * The selection time.
459 * The time can be set only once, otherwise an IllegalArgumentException
460 * is thrown.
461 */
462 public final FinalReference<Duration>
463 selection = new FinalReference<>(ZERO);
464
465 /**
466 * The alter time.
467 * The time can be set only once, otherwise an IllegalArgumentException
468 * is thrown.
469 */
470 public final FinalReference<Duration>
471 alter = new FinalReference<>(ZERO);
472
473 /**
474 * Combination time between offspring and survivors.
475 * The time can be set only once, otherwise an IllegalArgumentException
476 * is thrown.
477 */
478 public final FinalReference<Duration>
479 combine = new FinalReference<>(ZERO);
480
481 /**
482 * The evaluation time.
483 * The time can be set only once, otherwise an IllegalArgumentException
484 * is thrown.
485 */
486 public final FinalReference<Duration>
487 evaluation = new FinalReference<>(ZERO);
488
489 /**
490 * The statistics time.
491 * The time can be set only once, otherwise an IllegalArgumentException
492 * is thrown.
493 */
494 public final FinalReference<Duration>
495 statistics = new FinalReference<>(ZERO);
496
497
498 @Override
499 public int hashCode() {
500 return HashBuilder.of(getClass()).
501 and(alter).
502 and(combine).
503 and(evaluation).
504 and(execution).
505 and(selection).
506 and(statistics).value();
507 }
508
509 @Override
510 public boolean equals(final Object object) {
511 if (object == this) {
512 return true;
513 }
514 if (object == null || object.getClass() != getClass()) {
515 return false;
516 }
517
518 final Statistics.Time time = (Statistics.Time)object;
519 return eq(alter.get(), time.alter.get()) &&
520 eq(combine.get(), time.combine.get()) &&
521 eq(evaluation.get(), time.evaluation.get()) &&
522 eq(execution.get(), time.execution.get()) &&
523 eq(selection.get(), time.selection.get()) &&
524 eq(statistics.get(), time.statistics.get());
525 }
526
527 @Override
528 public String toString() {
529 final String pattern = "| %28s: %-26.11f|\n";
530
531 final StringBuilder out = new StringBuilder();
532 out.append("+---------------------------------------------------------+\n");
533 out.append("| Time Statistics |\n");
534 out.append("+---------------------------------------------------------+\n");
535 out.append(format(pattern, "Select time", selection.get().toSeconds()));
536 out.append(format(pattern, "Alter time", alter.get().toSeconds()));
537 out.append(format(pattern, "Combine time", combine.get().toSeconds()));
538 out.append(format(pattern, "Fitness calculation time", evaluation.get().toSeconds()));
539 out.append(format(pattern, "Statistics calculation time", statistics.get().toSeconds()));
540 out.append(format(pattern, "Overall execution time", execution.get().toSeconds()));
541 out.append("+---------------------------------------------------------+");
542
543 return out.toString();
544 }
545 }
546
547
548 /**
549 * Class for calculating the statistics. This class serves also as factory
550 * for the Statistics class.
551 *
552 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
553 * @since 1.0
554 * @version 2.0 — <em>$Date: 2014-04-05 $</em>
555 */
556 public static class Calculator<
557 G extends Gene<?, G>,
558 C extends Comparable<? super C>
559 >
560 {
561
562 /**
563 * Create a new calculator object.
564 */
565 public Calculator() {
566 }
567
568 /**
569 * Create a new statistics object from the given {@code population} at
570 * the given {@code generation}.
571 *
572 * @param population the population to aggregate.
573 * @param generation the current GA generation.
574 * @param opt the optimization <i>direction</i>.
575 * @return a new statistics object generated from the given arguments.
576 */
577 public Statistics.Builder<G, C> evaluate(
578 final Executor executor,
579 final Iterable<? extends Phenotype<G, C>> population,
580 final int generation,
581 final Optimize opt
582 ) {
583 final Builder<G, C> builder = new Builder<>();
584 builder.generation(generation);
585 builder.optimize(opt);
586
587 final MinMax<Phenotype<G, C>> minMax = new MinMax<>();
588 final Variance<Integer> age = new Variance<>();
589
590 accumulators.<Phenotype<G, C>>accumulate(
591 executor,
592 population,
593 minMax,
594 age.map(Phenotype.Age(generation))
595 );
596
597 builder.bestPhenotype(opt.best(minMax.getMax(), minMax.getMin()));
598 builder.worstPhenotype(opt.worst(minMax.getMax(), minMax.getMin()));
599 builder.samples((int)minMax.getSamples());
600 builder.ageMean(age.getMean());
601 builder.ageVariance(age.getVariance());
602
603 return builder;
604 }
605
606 }
607
608 }
|