001/* 002 * Java Genetic Algorithm Library (jenetics-8.1.0). 003 * Copyright (c) 2007-2024 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 * {@snippet lang="java": 105 * final Stream<Double> stream = null; // @replace substring='null' replacement="..." 106 * final DoubleMoments moments = stream.collect(toDoubleMoments()); 107 * } 108 * 109 * @since 4.1 110 * 111 * @param <N> the type of the input elements 112 * @return a {@code Collector} implementing the moments-statistics reduction 113 */ 114 public static <N extends Number> Collector<N, ?, DoubleMoments> 115 toDoubleMoments() { 116 return toDoubleMoments(Number::doubleValue); 117 } 118 119 /** 120 * Return a {@code Collector} which applies a double-producing mapping 121 * function to each input element, and returns moments-statistics for the 122 * resulting values. 123 * {@snippet lang="java": 124 * final Stream<SomeObject> stream = null; // @replace substring='null' replacement="..." 125 * final DoubleMoments moments = stream 126 * .collect(toDoubleMoments(v -> v.doubleValue())); 127 * } 128 * 129 * @param mapper a mapping function to apply to each element 130 * @param <T> the type of the input elements 131 * @return a {@code Collector} implementing the moments-statistics reduction 132 * @throws java.lang.NullPointerException if the given {@code mapper} is 133 * {@code null} 134 */ 135 public static <T> Collector<T, ?, DoubleMoments> 136 toDoubleMoments(final ToDoubleFunction<? super T> mapper) { 137 requireNonNull(mapper); 138 return Collector.of( 139 DoubleMomentStatistics::new, 140 (a, b) -> a.accept(mapper.applyAsDouble(b)), 141 DoubleMomentStatistics::combine, 142 DoubleMoments::of 143 ); 144 } 145 146}