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.lang.String.format;
023
024 import java.text.NumberFormat;
025 import java.time.Duration;
026 import java.util.function.Consumer;
027
028 import org.jenetics.Phenotype;
029 import org.jenetics.stat.DoubleMomentStatistics;
030 import org.jenetics.stat.IntMomentStatistics;
031 import org.jenetics.stat.LongMomentStatistics;
032 import org.jenetics.stat.MinMax;
033
034 /**
035 * This class can be used to gather additional statistic information of an
036 * evolution process. The additional information can be useful during the
037 * development phase of the GA or while testing the GA's performance. The
038 * following example shows how to integrate the <i>statistics</i> object into
039 * your evolution <i>stream</i>.
040 *
041 * [code]
042 * final Engine<DoubleGene, Double> engine = ...
043 * final EvolutionStatistics<Double, DoubleMomentStatistics> statistics =
044 * EvolutionStatistics.ofNumber();
045 *
046 * final Phenotype<DoubleGene, Double> result = engine.stream()
047 * .limit(bySteadyFitness(7))
048 * .limit(100)
049 * .peek(statistics)
050 * .collect(toBestPhenotype());
051 *
052 * System.println(statistics);
053 * [/code]
054 *
055 * <b>Example output</b>
056 *
057 * [code]
058 +---------------------------------------------------------------------------+
059 | Time statistics |
060 +---------------------------------------------------------------------------+
061 | Selection: sum=0.046538278000 s; mean=0.003878189833 s |
062 | Altering: sum=0.086155457000 s; mean=0.007179621417 s |
063 | Fitness calculation: sum=0.022901606000 s; mean=0.001908467167 s |
064 | Overall execution: sum=0.147298067000 s; mean=0.012274838917 s |
065 +---------------------------------------------------------------------------+
066 | Evolution statistics |
067 +---------------------------------------------------------------------------+
068 | Generations: 12 |
069 | Altered: sum=7,331; mean=610.916666667 |
070 | Killed: sum=0; mean=0.000000000 |
071 | Invalids: sum=0; mean=0.000000000 |
072 +---------------------------------------------------------------------------+
073 | Population statistics |
074 +---------------------------------------------------------------------------+
075 | Age: max=11; mean=1.951000; var=5.545190 |
076 | Fitness: |
077 | min = 0.000000000000 |
078 | max = 481.748227114537 |
079 | mean = 384.430345078660 |
080 | var = 13006.132537301528 |
081 +---------------------------------------------------------------------------+
082 * [/code]
083 *
084 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
085 * @since 3.0
086 * @version 3.0 — <em>$Date: 2014-12-28 $</em>
087 */
088 public abstract class EvolutionStatistics<
089 C extends Comparable<? super C>,
090 FitnessStatistics
091 >
092 implements Consumer<EvolutionResult<?, C>>
093 {
094
095 // The duration statistics values.
096 private final DoubleMomentStatistics
097 _selectionDuration = new DoubleMomentStatistics();
098 private final DoubleMomentStatistics
099 _alterDuration = new DoubleMomentStatistics();
100 private final DoubleMomentStatistics
101 _evaluationDuration = new DoubleMomentStatistics();
102 private final DoubleMomentStatistics
103 _evolveDuration = new DoubleMomentStatistics();
104
105 // The evolution statistics values.
106 private final IntMomentStatistics _killed = new IntMomentStatistics();
107 private final IntMomentStatistics _invalids = new IntMomentStatistics();
108 private final IntMomentStatistics _altered = new IntMomentStatistics();
109
110 // The population statistics values.
111 final LongMomentStatistics _age = new LongMomentStatistics();
112 FitnessStatistics _fitness = null;
113
114 EvolutionStatistics() {
115 }
116
117 @Override
118 public void accept(final EvolutionResult<?, C> result) {
119 accept(result.getDurations());
120
121 _killed.accept(result.getKillCount());
122 _invalids.accept(result.getInvalidCount());
123 _altered.accept(result.getAlterCount());
124
125 result.getPopulation()
126 .forEach(pt -> accept(pt, result.getGeneration()));
127 }
128
129 void accept(final Phenotype<?, C> pt, final long generation) {
130 _age.accept(pt.getAge(generation));
131 }
132
133 // Calculate duration statistics
134 private void accept(final EvolutionDurations durations) {
135 final double selection =
136 toSeconds(durations.getOffspringSelectionDuration()) +
137 toSeconds(durations.getSurvivorsSelectionDuration());
138 final double alter =
139 toSeconds(durations.getOffspringAlterDuration()) +
140 toSeconds(durations.getOffspringFilterDuration());
141
142 _selectionDuration.accept(selection);
143 _alterDuration.accept(alter);
144 _evaluationDuration
145 .accept(toSeconds(durations.getEvaluationDuration()));
146 _evolveDuration
147 .accept(toSeconds(durations.getEvolveDuration()));
148 }
149
150 private static double toSeconds(final Duration duration) {
151 return duration.toNanos()/1_000_000_000.0;
152 }
153
154 /* *************************************************************************
155 * Evaluation timing statistics
156 * ************************************************************************/
157
158 /**
159 * Return the duration statistics needed for selecting the population, in
160 * seconds.
161 *
162 * @return the duration statistics needed for selecting the population
163 */
164 public DoubleMomentStatistics getSelectionDuration() {
165 return _selectionDuration;
166 }
167
168 /**
169 * Return the duration statistics needed for altering the population, in
170 * seconds.
171 *
172 * @return the duration statistics needed for altering the population
173 */
174 public DoubleMomentStatistics getAlterDuration() {
175 return _alterDuration;
176 }
177
178 /**
179 * Return the duration statistics needed for evaluating the fitness function
180 * of the new individuals, in seconds.
181 *
182 * @return the duration statistics needed for evaluating the fitness
183 * function of the new individuals
184 */
185 public DoubleMomentStatistics getEvaluationDuration() {
186 return _evaluationDuration;
187 }
188
189 /**
190 * Return the duration statistics needed for the whole evolve step, in
191 * seconds.
192 *
193 * @return the duration statistics needed for the whole evolve step
194 */
195 public DoubleMomentStatistics getEvolveDuration() {
196 return _evolveDuration;
197 }
198
199
200
201 /* *************************************************************************
202 * Evolution statistics
203 * ************************************************************************/
204
205 /**
206 * Return the statistics about the killed individuals during the evolution
207 * process.
208 *
209 * @return killed individual statistics
210 */
211 public IntMomentStatistics getKilled() {
212 return _killed;
213 }
214
215 /**
216 * Return the statistics about the invalid individuals during the evolution
217 * process.
218 *
219 * @return invalid individual statistics
220 */
221 public IntMomentStatistics getInvalids() {
222 return _invalids;
223 }
224
225 /**
226 * Return the statistics about the altered individuals during the evolution
227 * process.
228 *
229 * @return altered individual statistics
230 */
231 public IntMomentStatistics getAltered() {
232 return _altered;
233 }
234
235 /**
236 * Return the statistics about the individuals age.
237 *
238 * @return individual age statistics
239 */
240 public LongMomentStatistics getPhenotypeAge() {
241 return _age;
242 }
243
244 /**
245 * Return the minimal and maximal fitness.
246 *
247 * @return minimal and maximal fitness
248 */
249 public FitnessStatistics getFitness() {
250 return _fitness;
251 }
252
253 final String cpattern = "| %22s %-51s|\n";
254 final String spattern = "| %27s %-46s|\n";
255
256 @Override
257 public String toString() {
258 return
259 "+---------------------------------------------------------------------------+\n" +
260 "| Time statistics |\n" +
261 "+---------------------------------------------------------------------------+\n" +
262 format(cpattern, "Selection:", d(_selectionDuration)) +
263 format(cpattern, "Altering:", d(_alterDuration)) +
264 format(cpattern, "Fitness calculation:", d(_evaluationDuration)) +
265 format(cpattern, "Overall execution:", d(_evolveDuration)) +
266 "+---------------------------------------------------------------------------+\n" +
267 "| Evolution statistics |\n" +
268 "+---------------------------------------------------------------------------+\n" +
269 format(cpattern, "Generations:", i(_altered.getCount())) +
270 format(cpattern, "Altered:", i(_altered)) +
271 format(cpattern, "Killed:", i(_killed)) +
272 format(cpattern, "Invalids:", i(_invalids));
273 }
274
275 private static String d(final DoubleMomentStatistics statistics) {
276 return format(
277 "sum=%3.12f s; mean=%3.12f s",
278 statistics.getSum(), statistics.getMean()
279 );
280 }
281
282 private static String i(final IntMomentStatistics statistics) {
283 final NumberFormat nf = NumberFormat.getIntegerInstance();
284 return format(
285 "sum=%s; mean=%6.9f",
286 nf.format(statistics.getSum()), statistics.getMean()
287 );
288 }
289
290 private static String i(final long value) {
291 final NumberFormat nf = NumberFormat.getIntegerInstance();
292 return nf.format(value);
293 }
294
295 private static String p(final IntMomentStatistics statistics) {
296 final NumberFormat nf = NumberFormat.getIntegerInstance();
297 return format(
298 "max=%s; mean=%6.6f; var=%6.6f",
299 nf.format(statistics.getMax()),
300 statistics.getMean(),
301 statistics.getVariance()
302 );
303 }
304
305 private static String p(final LongMomentStatistics statistics) {
306 final NumberFormat nf = NumberFormat.getIntegerInstance();
307 return format(
308 "max=%s; mean=%6.6f; var=%6.6f",
309 nf.format(statistics.getMax()),
310 statistics.getMean(),
311 statistics.getVariance()
312 );
313 }
314
315 private static final class Comp<
316 C extends Comparable<? super C>
317 >
318 extends EvolutionStatistics<C, MinMax<C>>
319 {
320 private Comp() {
321 _fitness = MinMax.of();
322 }
323
324 @Override
325 public void accept(final EvolutionResult<?, C> result) {
326 if (_fitness.getMax() == null) {
327 _fitness = MinMax.of(result.getOptimize().ascending());
328 }
329
330 super.accept(result);
331 }
332
333 @Override
334 void accept(final Phenotype<?, C> pt, final long generation) {
335 super.accept(pt, generation);
336 _fitness.accept(pt.getFitness());
337 }
338
339 @Override
340 public String toString() {
341 return super.toString() +
342 "+---------------------------------------------------------------------------+\n" +
343 "| Population statistics |\n" +
344 "+---------------------------------------------------------------------------+\n" +
345 format(cpattern, "Age:", p(_age)) +
346 format(cpattern, "Fitness", "") +
347 format(spattern, "min =", _fitness.getMin()) +
348 format(spattern, "max =", _fitness.getMax()) +
349 "+---------------------------------------------------------------------------+";
350 }
351 }
352
353 private static final class Num<N extends Number & Comparable<? super N>>
354 extends EvolutionStatistics<N, DoubleMomentStatistics>
355 {
356 private Num() {
357 _fitness = new DoubleMomentStatistics();
358 }
359
360 @Override
361 void accept(final Phenotype<?, N> pt, final long generation) {
362 super.accept(pt, generation);
363 _fitness.accept(pt.getFitness().doubleValue());
364 }
365
366 @Override
367 public String toString() {
368 return super.toString() +
369 "+---------------------------------------------------------------------------+\n" +
370 "| Population statistics |\n" +
371 "+---------------------------------------------------------------------------+\n" +
372 format(cpattern, "Age:", p(_age)) +
373 format(cpattern, "Fitness:", "") +
374 format(spattern, "min =", d(_fitness.getMin())) +
375 format(spattern, "max =", d(_fitness.getMax())) +
376 format(spattern, "mean =", d(_fitness.getMean())) +
377 format(spattern, "var =", d(_fitness.getVariance())) +
378 "+---------------------------------------------------------------------------+";
379 }
380
381 private static String d(final double value) {
382 return format("%3.12f", value);
383 }
384 }
385
386 public static <C extends Comparable<? super C>>
387 EvolutionStatistics<C, MinMax<C>> ofComparable() {
388 return new Comp<>();
389 }
390
391 public static <N extends Number & Comparable<? super N>>
392 EvolutionStatistics<N, DoubleMomentStatistics> ofNumber() {
393 return new Num<>();
394 }
395
396 }
|