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