001 /*
002 * Java Genetic Algorithm Library (jenetics-6.3.0).
003 * Copyright (c) 2007-2021 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 6.0
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 * Return the minimum value recorded, or {@code Double.POSITIVE_INFINITY} if
098 * no values have been recorded.
099 *
100 * @return the minimum value, or {@code Integer.MAX_VALUE} if none
101 */
102 public double min() {
103 return _min;
104 }
105
106 /**
107 * Return the maximum value recorded, or {@code Double.NEGATIVE_INFINITY} if
108 * no values have been recorded.
109 *
110 * @return the maximum value, or {@code Integer.MIN_VALUE} if none
111 */
112 public double max() {
113 return _max;
114 }
115
116 /**
117 * Return the sum of values recorded, or zero if no values have been
118 * recorded.
119 *
120 * @return the sum of values, or zero if none
121 */
122 public double sum() {
123 return _sum;
124 }
125
126 /**
127 * Return the arithmetic mean of values recorded, or zero if no values have
128 * been recorded.
129 *
130 * @return the arithmetic mean of values, or zero if none
131 */
132 public double mean() {
133 return _mean;
134 }
135
136 /**
137 * Return the variance of values recorded, or {@code Double.NaN} if no
138 * values have been recorded.
139 *
140 * @return the variance of values, or {@code NaN} if none
141 */
142 public double variance() {
143 return _variance;
144 }
145
146 /**
147 * Return the skewness of values recorded, or {@code Double.NaN} if less
148 * than two values have been recorded.
149 *
150 * @see <a href="https://en.wikipedia.org/wiki/Skewness">Skewness</a>
151 *
152 * @return the skewness of values, or {@code NaN} if less than two values
153 * have been recorded
154 */
155 public double skewness() {
156 return _skewness;
157 }
158
159 /**
160 * Return the kurtosis of values recorded, or {@code Double.NaN} if less
161 * than four values have been recorded.
162 *
163 * @see <a href="https://en.wikipedia.org/wiki/Kurtosis">Kurtosis</a>
164 *
165 * @return the kurtosis of values, or {@code NaN} if less than four values
166 * have been recorded
167 */
168 public double kurtosis() {
169 return _kurtosis;
170 }
171
172 @Override
173 public int hashCode() {
174 return
175 hash(_count,
176 hash(_sum,
177 hash(_min,
178 hash(_max,
179 hash(_mean,
180 hash(_variance,
181 hash(_skewness,
182 hash(_kurtosis))))))));
183 }
184
185 @Override
186 public boolean equals(final Object obj) {
187 return obj == this ||
188 obj instanceof DoubleMoments &&
189 _count == ((DoubleMoments)obj)._count &&
190 Double.compare(_sum, ((DoubleMoments)obj)._sum) == 0 &&
191 Double.compare(_min, ((DoubleMoments)obj)._min) == 0 &&
192 Double.compare(_max, ((DoubleMoments)obj)._max) == 0 &&
193 Double.compare(_mean, ((DoubleMoments)obj)._mean) == 0 &&
194 Double.compare(_variance, ((DoubleMoments)obj)._variance) == 0 &&
195 Double.compare(_skewness, ((DoubleMoments)obj)._skewness) == 0&&
196 Double.compare(_kurtosis, ((DoubleMoments)obj)._kurtosis) == 0;
197 }
198
199 @Override
200 public String toString() {
201 return String.format(
202 "DoubleMoments[N=%d, ∧=%s, ∨=%s, Σ=%s, μ=%s, s²=%s, S=%s, K=%s]",
203 count(), min(), max(), sum(),
204 mean(), variance(), skewness(), kurtosis()
205 );
206 }
207
208 /**
209 * Create an immutable object which contains statistical values.
210 *
211 * @param count the count of values recorded
212 * @param min the minimum value
213 * @param max the maximum value
214 * @param sum the sum of the recorded values
215 * @param mean the arithmetic mean of values
216 * @param variance the variance of values
217 * @param skewness the skewness of values
218 * @param kurtosis the kurtosis of values
219 * @return an immutable object which contains statistical values
220 */
221 public static DoubleMoments of(
222 final long count,
223 final double min,
224 final double max,
225 final double sum,
226 final double mean,
227 final double variance,
228 final double skewness,
229 final double kurtosis
230 ) {
231 return new DoubleMoments(
232 count,
233 min,
234 max,
235 sum,
236 mean,
237 variance,
238 skewness,
239 kurtosis
240 );
241 }
242
243 /**
244 * Return a new value object of the statistical moments, currently
245 * represented by the {@code statistics} object.
246 *
247 * @param statistics the creating (mutable) statistics class
248 * @return the statistical moments
249 */
250 public static DoubleMoments of(final DoubleMomentStatistics statistics) {
251 return new DoubleMoments(
252 statistics.count(),
253 statistics.min(),
254 statistics.max(),
255 statistics.sum(),
256 statistics.mean(),
257 statistics.variance(),
258 statistics.skewness(),
259 statistics.kurtosis()
260 );
261 }
262
263 /**
264 * Return a {@code Collector} which returns moments-statistics for the
265 * resulting values.
266 *
267 * <pre>{@code
268 * final Stream<Double> stream = ...
269 * final DoubleMoments moments = stream.collect(toDoubleMoments()));
270 * }</pre>
271 *
272 * @since 4.1
273 *
274 * @param <N> the type of the input elements
275 * @return a {@code Collector} implementing the moments-statistics reduction
276 */
277 public static <N extends Number> Collector<N, ?, DoubleMoments>
278 toDoubleMoments() {
279 return toDoubleMoments(Number::doubleValue);
280 }
281
282 /**
283 * Return a {@code Collector} which applies an double-producing mapping
284 * function to each input element, and returns moments-statistics for the
285 * resulting values.
286 *
287 * <pre>{@code
288 * final Stream<SomeObject> stream = ...
289 * final DoubleMoments moments = stream
290 * .collect(toDoubleMoments(v -> v.doubleValue()));
291 * }</pre>
292 *
293 * @param mapper a mapping function to apply to each element
294 * @param <T> the type of the input elements
295 * @return a {@code Collector} implementing the moments-statistics reduction
296 * @throws java.lang.NullPointerException if the given {@code mapper} is
297 * {@code null}
298 */
299 public static <T> Collector<T, ?, DoubleMoments>
300 toDoubleMoments(final ToDoubleFunction<? super T> mapper) {
301 requireNonNull(mapper);
302 return Collector.of(
303 DoubleMomentStatistics::new,
304 (a, b) -> a.accept(mapper.applyAsDouble(b)),
305 DoubleMomentStatistics::combine,
306 DoubleMoments::of
307 );
308 }
309
310 }
|