NumberStatistics.java
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  */
020 package org.jenetics;
021 
022 import static java.lang.Double.NaN;
023 import static java.lang.String.format;
024 import static org.jenetics.util.object.eq;
025 import static org.jenetics.util.object.hashCodeOf;
026 
027 import javolution.xml.XMLFormat;
028 import javolution.xml.stream.XMLStreamException;
029 
030 import org.jscience.mathematics.number.Float64;
031 
032 import org.jenetics.stat.Variance;
033 import org.jenetics.util.accumulators;
034 import 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  */
041 public class NumberStatistics<
042     extends Gene<?, G>,
043     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         extends Gene<?, G>,
057         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         extends Gene<?, G>,
298         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 }