001/* 002 * Java Genetic Algorithm Library (jenetics-7.2.0). 003 * Copyright (c) 2007-2023 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 */ 020package io.jenetics.stat; 021 022import static java.util.Objects.requireNonNull; 023 024import java.io.Serial; 025import java.io.Serializable; 026import java.util.function.ToDoubleFunction; 027import java.util.stream.Collector; 028 029/** 030 * <i>Value</i> objects which contains statistical moments. 031 * 032 * @see io.jenetics.stat.DoubleMomentStatistics 033 * 034 * @param count the count of values recorded 035 * @param min the minimum value recorded, or {@link Double#POSITIVE_INFINITY} if 036 * no values have been recorded. 037 * @param max the maximum value recorded, or {@link Double#NEGATIVE_INFINITY} if 038 * no values have been recorded 039 * @param sum the sum of values recorded, or zero if no values have been 040 * recorded 041 * @param mean the arithmetic mean of values recorded, or zero if no values have 042 * been recorded 043 * @param variance the variance of values recorded, or {@link Double#NaN} if no 044 * values have been recorded 045 * @param skewness the <a href="https://en.wikipedia.org/wiki/Skewness">Skewness</a> 046 * of values recorded, or {@link Double#NaN} if less than two values have 047 * been recorded 048 * @param kurtosis the <a href="https://en.wikipedia.org/wiki/Kurtosis">Kurtosis</a> 049 * of values recorded, or {@link Double#NaN} if less than four values 050 * have been recorded 051 * 052 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a> 053 * @since 3.0 054 * @version 7.0 055 */ 056public record DoubleMoments( 057 long count, 058 double min, 059 double max, 060 double sum, 061 double mean, 062 double variance, 063 double skewness, 064 double kurtosis 065) 066 implements Serializable 067{ 068 069 @Serial 070 private static final long serialVersionUID = 2L; 071 072 @Override 073 public String toString() { 074 return String.format( 075 "DoubleMoments[N=%d, ∧=%s, ∨=%s, Σ=%s, μ=%s, s²=%s, S=%s, K=%s]", 076 count(), min(), max(), sum(), 077 mean(), variance(), skewness(), kurtosis() 078 ); 079 } 080 081 /** 082 * Return a new value object of the statistical moments, currently 083 * represented by the {@code statistics} object. 084 * 085 * @param statistics the creating (mutable) statistics class 086 * @return the statistical moments 087 */ 088 public static DoubleMoments of(final DoubleMomentStatistics statistics) { 089 return new DoubleMoments( 090 statistics.count(), 091 statistics.min(), 092 statistics.max(), 093 statistics.sum(), 094 statistics.mean(), 095 statistics.variance(), 096 statistics.skewness(), 097 statistics.kurtosis() 098 ); 099 } 100 101 /** 102 * Return a {@code Collector} which returns moments-statistics for the 103 * resulting values. 104 * 105 * <pre>{@code 106 * final Stream<Double> stream = ... 107 * final DoubleMoments moments = stream.collect(toDoubleMoments())); 108 * }</pre> 109 * 110 * @since 4.1 111 * 112 * @param <N> the type of the input elements 113 * @return a {@code Collector} implementing the moments-statistics reduction 114 */ 115 public static <N extends Number> Collector<N, ?, DoubleMoments> 116 toDoubleMoments() { 117 return toDoubleMoments(Number::doubleValue); 118 } 119 120 /** 121 * Return a {@code Collector} which applies a double-producing mapping 122 * function to each input element, and returns moments-statistics for the 123 * resulting values. 124 * 125 * <pre>{@code 126 * final Stream<SomeObject> stream = ... 127 * final DoubleMoments moments = stream 128 * .collect(toDoubleMoments(v -> v.doubleValue())); 129 * }</pre> 130 * 131 * @param mapper a mapping function to apply to each element 132 * @param <T> the type of the input elements 133 * @return a {@code Collector} implementing the moments-statistics reduction 134 * @throws java.lang.NullPointerException if the given {@code mapper} is 135 * {@code null} 136 */ 137 public static <T> Collector<T, ?, DoubleMoments> 138 toDoubleMoments(final ToDoubleFunction<? super T> mapper) { 139 requireNonNull(mapper); 140 return Collector.of( 141 DoubleMomentStatistics::new, 142 (a, b) -> a.accept(mapper.applyAsDouble(b)), 143 DoubleMomentStatistics::combine, 144 DoubleMoments::of 145 ); 146 } 147 148}