001 /*
002 * Java Genetic Algorithm Library (jenetics-5.2.0).
003 * Copyright (c) 2007-2020 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@gmail.com)
019 */
020 package io.jenetics.stat;
021
022 import static java.util.Objects.requireNonNull;
023 import static io.jenetics.internal.util.Hashes.hash;
024
025 import java.io.Serializable;
026 import java.util.function.ToDoubleFunction;
027 import java.util.stream.Collector;
028
029 /**
030 * <i>Value</i> objects which contains statistical moments.
031 *
032 * @see io.jenetics.stat.DoubleMomentStatistics
033 *
034 * @implNote
035 * This class is immutable and thread-safe.
036 *
037 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
038 * @since 3.0
039 * @version 5.2
040 */
041 public final /*record*/ class DoubleMoments implements Serializable {
042
043 private static final long serialVersionUID = 1L;
044
045 private final long _count;
046 private final double _min;
047 private final double _max;
048 private final double _sum;
049 private final double _mean;
050 private final double _variance;
051 private final double _skewness;
052 private final double _kurtosis;
053
054
055 /**
056 * Create an immutable object which contains statistical values.
057 *
058 * @param count the count of values recorded
059 * @param min the minimum value
060 * @param max the maximum value
061 * @param sum the sum of the recorded values
062 * @param mean the arithmetic mean of values
063 * @param variance the variance of values
064 * @param skewness the skewness of values
065 * @param kurtosis the kurtosis of values
066 */
067 private DoubleMoments(
068 final long count,
069 final double min,
070 final double max,
071 final double sum,
072 final double mean,
073 final double variance,
074 final double skewness,
075 final double kurtosis
076 ) {
077 _count = count;
078 _min = min;
079 _max = max;
080 _sum = sum;
081 _mean = mean;
082 _variance = variance;
083 _skewness = skewness;
084 _kurtosis = kurtosis;
085 }
086
087 /**
088 * Returns the count of values recorded.
089 *
090 * @return the count of recorded values
091 */
092 public long count() {
093 return _count;
094 }
095
096 /**
097 * Returns the count of values recorded.
098 *
099 * @return the count of recorded values
100 * @deprecated Use {@link #count()} instead
101 */
102 @Deprecated
103 public long getCount() {
104 return _count;
105 }
106
107 /**
108 * Return the minimum value recorded, or {@code Double.POSITIVE_INFINITY} if
109 * no values have been recorded.
110 *
111 * @return the minimum value, or {@code Integer.MAX_VALUE} if none
112 */
113 public double min() {
114 return _min;
115 }
116
117 /**
118 * Return the minimum value recorded, or {@code Double.POSITIVE_INFINITY} if
119 * no values have been recorded.
120 *
121 * @return the minimum value, or {@code Integer.MAX_VALUE} if none
122 * @deprecated Use {@link #min()} instead
123 */
124 @Deprecated
125 public double getMin() {
126 return _min;
127 }
128
129 /**
130 * Return the maximum value recorded, or {@code Double.NEGATIVE_INFINITY} if
131 * no values have been recorded.
132 *
133 * @return the maximum value, or {@code Integer.MIN_VALUE} if none
134 */
135 public double max() {
136 return _max;
137 }
138
139 /**
140 * Return the maximum value recorded, or {@code Double.NEGATIVE_INFINITY} if
141 * no values have been recorded.
142 *
143 * @return the maximum value, or {@code Integer.MIN_VALUE} if none
144 * @deprecated Use {@link #max()} instead
145 */
146 @Deprecated
147 public double getMax() {
148 return _max;
149 }
150
151 /**
152 * Return the sum of values recorded, or zero if no values have been
153 * recorded.
154 *
155 * @return the sum of values, or zero if none
156 */
157 public double sum() {
158 return _sum;
159 }
160
161 /**
162 * Return the sum of values recorded, or zero if no values have been
163 * recorded.
164 *
165 * @return the sum of values, or zero if none
166 * @deprecated Use {@link #sum()} instead
167 */
168 @Deprecated
169 public double getSum() {
170 return _sum;
171 }
172
173 /**
174 * Return the arithmetic mean of values recorded, or zero if no values have
175 * been recorded.
176 *
177 * @return the arithmetic mean of values, or zero if none
178 */
179 public double mean() {
180 return _mean;
181 }
182
183 /**
184 * Return the arithmetic mean of values recorded, or zero if no values have
185 * been recorded.
186 *
187 * @return the arithmetic mean of values, or zero if none
188 * @deprecated Use {@link #mean()} instead
189 */
190 @Deprecated
191 public double getMean() {
192 return _mean;
193 }
194
195 /**
196 * Return the variance of values recorded, or {@code Double.NaN} if no
197 * values have been recorded.
198 *
199 * @return the variance of values, or {@code NaN} if none
200 */
201 public double variance() {
202 return _variance;
203 }
204
205 /**
206 * Return the variance of values recorded, or {@code Double.NaN} if no
207 * values have been recorded.
208 *
209 * @return the variance of values, or {@code NaN} if none
210 * @deprecated Use {@link #variance()} instead
211 */
212 @Deprecated
213 public double getVariance() {
214 return _variance;
215 }
216
217 /**
218 * Return the skewness of values recorded, or {@code Double.NaN} if less
219 * than two values have been recorded.
220 *
221 * @see <a href="https://en.wikipedia.org/wiki/Skewness">Skewness</a>
222 *
223 * @return the skewness of values, or {@code NaN} if less than two values
224 * have been recorded
225 */
226 public double skewness() {
227 return _skewness;
228 }
229
230 /**
231 * Return the skewness of values recorded, or {@code Double.NaN} if less
232 * than two values have been recorded.
233 *
234 * @see <a href="https://en.wikipedia.org/wiki/Skewness">Skewness</a>
235 *
236 * @return the skewness of values, or {@code NaN} if less than two values
237 * have been recorded
238 * @deprecated Use {@link #skewness()} instead
239 */
240 @Deprecated
241 public double getSkewness() {
242 return _skewness;
243 }
244
245 /**
246 * Return the kurtosis of values recorded, or {@code Double.NaN} if less
247 * than four values have been recorded.
248 *
249 * @see <a href="https://en.wikipedia.org/wiki/Kurtosis">Kurtosis</a>
250 *
251 * @return the kurtosis of values, or {@code NaN} if less than four values
252 * have been recorded
253 */
254 public double kurtosis() {
255 return _kurtosis;
256 }
257
258 /**
259 * Return the kurtosis of values recorded, or {@code Double.NaN} if less
260 * than four values have been recorded.
261 *
262 * @see <a href="https://en.wikipedia.org/wiki/Kurtosis">Kurtosis</a>
263 *
264 * @return the kurtosis of values, or {@code NaN} if less than four values
265 * have been recorded
266 * @deprecated Use {@link #kurtosis()} instead
267 */
268 @Deprecated
269 public double getKurtosis() {
270 return _kurtosis;
271 }
272
273 @Override
274 public int hashCode() {
275 return
276 hash(_count,
277 hash(_sum,
278 hash(_min,
279 hash(_max,
280 hash(_mean,
281 hash(_variance,
282 hash(_skewness,
283 hash(_kurtosis))))))));
284 }
285
286 @Override
287 public boolean equals(final Object obj) {
288 return obj == this ||
289 obj instanceof DoubleMoments &&
290 _count == ((DoubleMoments)obj)._count &&
291 Double.compare(_sum, ((DoubleMoments)obj)._sum) == 0 &&
292 Double.compare(_min, ((DoubleMoments)obj)._min) == 0 &&
293 Double.compare(_max, ((DoubleMoments)obj)._max) == 0 &&
294 Double.compare(_mean, ((DoubleMoments)obj)._mean) == 0 &&
295 Double.compare(_variance, ((DoubleMoments)obj)._variance) == 0 &&
296 Double.compare(_skewness, ((DoubleMoments)obj)._skewness) == 0&&
297 Double.compare(_kurtosis, ((DoubleMoments)obj)._kurtosis) == 0;
298 }
299
300 @Override
301 public String toString() {
302 return String.format(
303 "DoubleMoments[N=%d, ∧=%s, ∨=%s, Σ=%s, μ=%s, s²=%s, S=%s, K=%s]",
304 count(), min(), max(), sum(),
305 mean(), variance(), skewness(), kurtosis()
306 );
307 }
308
309 /**
310 * Create an immutable object which contains statistical values.
311 *
312 * @param count the count of values recorded
313 * @param min the minimum value
314 * @param max the maximum value
315 * @param sum the sum of the recorded values
316 * @param mean the arithmetic mean of values
317 * @param variance the variance of values
318 * @param skewness the skewness of values
319 * @param kurtosis the kurtosis of values
320 * @return an immutable object which contains statistical values
321 */
322 public static DoubleMoments of(
323 final long count,
324 final double min,
325 final double max,
326 final double sum,
327 final double mean,
328 final double variance,
329 final double skewness,
330 final double kurtosis
331 ) {
332 return new DoubleMoments(
333 count,
334 min,
335 max,
336 sum,
337 mean,
338 variance,
339 skewness,
340 kurtosis
341 );
342 }
343
344 /**
345 * Return a new value object of the statistical moments, currently
346 * represented by the {@code statistics} object.
347 *
348 * @param statistics the creating (mutable) statistics class
349 * @return the statistical moments
350 */
351 public static DoubleMoments of(final DoubleMomentStatistics statistics) {
352 return new DoubleMoments(
353 statistics.count(),
354 statistics.min(),
355 statistics.max(),
356 statistics.sum(),
357 statistics.mean(),
358 statistics.variance(),
359 statistics.skewness(),
360 statistics.kurtosis()
361 );
362 }
363
364 /**
365 * Return a {@code Collector} which returns moments-statistics for the
366 * resulting values.
367 *
368 * <pre>{@code
369 * final Stream<Double> stream = ...
370 * final DoubleMoments moments = stream.collect(toDoubleMoments()));
371 * }</pre>
372 *
373 * @since 4.1
374 *
375 * @param <N> the type of the input elements
376 * @return a {@code Collector} implementing the moments-statistics reduction
377 */
378 public static <N extends Number> Collector<N, ?, DoubleMoments>
379 toDoubleMoments() {
380 return toDoubleMoments(Number::doubleValue);
381 }
382
383 /**
384 * Return a {@code Collector} which applies an double-producing mapping
385 * function to each input element, and returns moments-statistics for the
386 * resulting values.
387 *
388 * <pre>{@code
389 * final Stream<SomeObject> stream = ...
390 * final DoubleMoments moments = stream
391 * .collect(toDoubleMoments(v -> v.doubleValue()));
392 * }</pre>
393 *
394 * @param mapper a mapping function to apply to each element
395 * @param <T> the type of the input elements
396 * @return a {@code Collector} implementing the moments-statistics reduction
397 * @throws java.lang.NullPointerException if the given {@code mapper} is
398 * {@code null}
399 */
400 public static <T> Collector<T, ?, DoubleMoments>
401 toDoubleMoments(final ToDoubleFunction<? super T> mapper) {
402 requireNonNull(mapper);
403 return Collector.of(
404 DoubleMomentStatistics::new,
405 (a, b) -> a.accept(mapper.applyAsDouble(b)),
406 DoubleMomentStatistics::combine,
407 DoubleMoments::of
408 );
409 }
410
411 }
|