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 */
020package org.jenetics;
021
022import static java.lang.Double.NaN;
023import static java.lang.String.format;
024import static org.jenetics.internal.util.object.eq;
025
026import java.util.concurrent.Executor;
027
028import org.jenetics.internal.util.HashBuilder;
029
030import org.jenetics.stat.Variance;
031import org.jenetics.util.accumulators;
032import org.jenetics.util.accumulators.MinMax;
033
034/**
035 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
036 * @since 1.0
037 * @version 2.0 &mdash; <em>$Date: 2014-04-11 $</em>
038 */
039public class NumberStatistics<
040        G extends Gene<?, G>,
041        R extends Number & Comparable<? super R>
042>
043        extends Statistics<G, R>
044{
045
046        /**
047         * Builder for the NumberStatistics class.
048         *
049         * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
050         * @since 1.0
051         * @version 2.0 &mdash; <em>$Date: 2014-04-11 $</em>
052         */
053        public static class Builder<
054                G extends Gene<?, G>,
055                R extends Number & Comparable<? super R>
056        >
057                extends Statistics.Builder<G, R>
058        {
059                protected double _fitnessMean = NaN;
060                protected double _fitnessVariance = NaN;
061                protected double _standardError = NaN;
062
063                /**
064                 * Create a new NumberStatistics builder.
065                 */
066                public Builder() {
067                }
068
069                @Override
070                public Builder<G, R> statistics(final Statistics<G, R> statistics) {
071                        super.statistics(statistics);
072                        return this;
073                }
074
075                /**
076                 * Set the values of this builder with the values of the given
077                 * {@code statistics}.
078                 *
079                 * @param statistics the statistics values. If the {@code statistics}
080                 *         is {@code null} nothing is set.
081                 * @return this builder instance.
082                 */
083                public Builder<G, R> statistics(final NumberStatistics<G, R> statistics) {
084                        if (statistics != null) {
085                                super.statistics(statistics);
086                                _fitnessMean = statistics._fitnessMean;
087                                _fitnessVariance = statistics._fitnessVariance;
088                                _standardError = statistics._standardError;
089                        }
090                        return this;
091                }
092
093                /**
094                 * @see NumberStatistics#getFitnessMean()
095                 *
096                 * @param fitnessMean the mean of the fitness value
097                 * @return this builder instance
098                 */
099                public Builder<G, R> fitnessMean(final double fitnessMean) {
100                        _fitnessMean = fitnessMean;
101                        return this;
102                }
103
104                /**
105                 * @see NumberStatistics#getFitnessVariance()
106                 *
107                 * @param fitnessVariance the variance of the fitness value
108                 * @return this builder instance
109                 */
110                public Builder<G, R> fitnessVariance(final double fitnessVariance) {
111                        _fitnessVariance = fitnessVariance;
112                        return this;
113                }
114
115                /**
116                 * @see NumberStatistics#getStandardError()
117                 *
118                 * @param standardError the standard error of the fitness mean value
119                 * @return this builder instancett
120                 */
121                public Builder<G, R> standardError(final double standardError) {
122                        _standardError = standardError;
123                        return this;
124                }
125
126                @Override
127                public NumberStatistics<G, R> build() {
128                        return new NumberStatistics<>(
129                                _optimize,
130                                _generation,
131                                _best,
132                                _worst,
133                                _fitnessMean,
134                                _fitnessVariance,
135                                _samples,
136                                _ageMean,
137                                _ageVariance,
138                                _standardError,
139                                _killed,
140                                _invalid
141                        );
142                }
143        }
144
145        private static final long serialVersionUID = 3L;
146
147        protected final double _fitnessMean;
148        protected final double _fitnessVariance;
149        protected final double _standardError;
150
151        protected NumberStatistics(
152                final Optimize optimize,
153                final int generation,
154                final Phenotype<G, R> best,
155                final Phenotype<G, R> worst,
156                final double fitnessMean,
157                final double fitnessVariance,
158                final int samples,
159                final double ageMean,
160                final double ageVariance,
161                final double errorOfMean,
162                final int killed,
163                final int invalid
164        ) {
165                super(
166                        optimize,
167                        generation,
168                        best,
169                        worst,
170                        samples,
171                        ageMean,
172                        ageVariance,
173                        killed,
174                        invalid
175                );
176
177                _fitnessMean = fitnessMean;
178                _fitnessVariance = fitnessVariance;
179                _standardError = errorOfMean;
180        }
181
182        /**
183         * Return the mean of the fitness values.
184         *
185         * @return the mean of the fitness values.
186         */
187        public double getFitnessMean() {
188                return _fitnessMean;
189        }
190
191        /**
192         * Return the variance of the fitness values.
193         *
194         * @return the variance of the fitness values.
195         */
196        public double getFitnessVariance() {
197                return _fitnessVariance;
198        }
199
200        /**
201         * Return the <a href="https://secure.wikimedia.org/wikipedia/en/wiki/Standard_error_%28statistics%29">
202         * Standard error
203         * </a> of the calculated fitness mean.
204         *
205         * @return the standard error of the calculated fitness mean.
206         */
207        public double getStandardError() {
208                return _standardError;
209        }
210
211        @Override
212        public int hashCode() {
213                return HashBuilder.of(getClass()).
214                                and(super.hashCode()).
215                                and(_fitnessMean).
216                                and(_fitnessVariance).
217                                and(_standardError).value();
218        }
219
220        @Override
221        public boolean equals(final Object obj) {
222                if (obj == this) {
223                        return true;
224                }
225                if (!(obj instanceof NumberStatistics<?, ?>)) {
226                        return false;
227                }
228
229                final NumberStatistics<?, ?> statistics = (NumberStatistics<?, ?>) obj;
230                return eq(statistics._fitnessMean, _fitnessMean) &&
231                                eq(statistics._fitnessVariance, _fitnessVariance) &&
232                                eq(statistics._standardError, _standardError) &&
233                                super.equals(obj);
234        }
235
236        @Override
237        public String toString() {
238                final String fpattern = "| %28s: %-26.11f|\n";
239
240                final StringBuilder out = new StringBuilder();
241                out.append(super.toString()).append("\n");
242                out.append("+---------------------------------------------------------+\n");
243                out.append("|  Fitness Statistics                                     |\n");
244                out.append("+---------------------------------------------------------+\n");
245                out.append(format(fpattern, "Fitness mean", _fitnessMean));
246                out.append(format(fpattern, "Fitness variance", _fitnessVariance));
247                out.append(format(fpattern, "Fitness error of mean", _standardError));
248                out.append("+---------------------------------------------------------+");
249
250                return out.toString();
251        }
252
253        /**
254         * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
255         * @since 1.0
256         * @version 2.0 &mdash; <em>$Date: 2014-04-11 $</em>
257         */
258        public static class Calculator<
259                G extends Gene<?, G>,
260                R extends Number & Comparable<? super R>
261        >
262                extends Statistics.Calculator<G, R>
263        {
264
265                public Calculator() {
266                }
267
268                @Override
269                public NumberStatistics.Builder<G, R> evaluate(
270                        final Executor executor,
271                        final Iterable<? extends Phenotype<G, R>> population,
272                        final int generation,
273                        final Optimize opt
274                ) {
275                        final Builder<G, R> builder = new Builder<>();
276                        builder.generation(generation);
277                        builder.optimize(opt);
278
279                        final MinMax<Phenotype<G, R>> minMax = new MinMax<>();
280                        final Variance<Integer> age = new Variance<>();
281                        final Variance<R> fitness = new Variance<>();
282
283                        accumulators.accumulate(
284                                        executor,
285                                        population,
286                                        minMax,
287                                        age.map(Phenotype.Age(generation)),
288                                        fitness.map(Phenotype.<R>Fitness())
289                                );
290                        builder.bestPhenotype(opt.best(minMax.getMax(), minMax.getMin()));
291                        builder.worstPhenotype(opt.worst(minMax.getMax(), minMax.getMin()));
292                        builder.fitnessMean(fitness.getMean());
293                        builder.fitnessVariance(fitness.getVariance());
294                        builder.samples((int)minMax.getSamples());
295                        builder.ageMean(age.getMean());
296                        builder.ageVariance(age.getVariance());
297                        builder.standardError(fitness.getStandardError());
298
299                        return builder;
300                }
301        }
302
303}