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