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 — <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 — <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 — <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}