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