001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  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 */
017package org.apache.commons.statistics.interval;
018
019import org.apache.commons.statistics.distribution.ChiSquaredDistribution;
020import org.apache.commons.statistics.distribution.TDistribution;
021
022/**
023 * Generate confidence intervals for a normally distributed population.
024 *
025 * @see <a
026 * href="https://en.wikipedia.org/wiki/Normal_distribution#Confidence_intervals">Normal
027 * distribution confidence interval (Wikipedia)</a>
028 *
029 * @since 1.2
030 */
031public enum NormalConfidenceInterval {
032    /**
033     * Create a confidence interval for the true mean of an unknown normally distributed population.
034     */
035    MEAN {
036        @Override
037        Interval create(double mean, double variance, long n, double alpha) {
038            final double c = TDistribution.of(n - 1).inverseSurvivalProbability(alpha * 0.5);
039            final double distance = c * Math.sqrt(variance / n);
040            return new BaseInterval(mean - distance, mean + distance);
041        }
042    },
043    /**
044     * Create a confidence interval for the true variance of an unknown normally distributed population.
045     */
046    VARIANCE {
047        @Override
048        Interval create(double mean, double variance, long n, double alpha) {
049            final ChiSquaredDistribution d = ChiSquaredDistribution.of(n - 1);
050            final double f = variance * (n - 1.0);
051            final double lower = f / d.inverseSurvivalProbability(alpha * 0.5);
052            final double upper = f / d.inverseCumulativeProbability(alpha * 0.5);
053            return new BaseInterval(lower, upper);
054        }
055    };
056
057    /**
058     * Create a confidence interval from an independent sample from an unknown normally
059     * distributed population with the given error rate.
060     *
061     * <p>The error rate {@code alpha} is related to the confidence level that the
062     * interval contains the true probability of success as
063     * {@code alpha = 1 - confidence}, where {@code confidence} is the confidence level
064     * in {@code [0, 1]}. For example a 95% confidence level is an {@code alpha} of 0.05.
065     *
066     * <p>The unbiased variance is the sum of the squared deviations from the mean divided
067     * by {@code n - 1}.
068     *
069     * @param mean Sample mean.
070     * @param variance Unbiased sample variance.
071     * @param n Sample size.
072     * @param alpha Desired error rate that the true probability of success falls
073     * <em>outside</em> the returned interval.
074     * @return Confidence interval containing the target with error rate {@code alpha}
075     * @throws IllegalArgumentException if {@code n <= 1}, or if {@code alpha} is not in
076     * the open interval {@code (0, 1)}.
077     */
078    public Interval fromErrorRate(double mean, double variance, long n, double alpha) {
079        if (n <= 1) {
080            throw new IllegalArgumentException("Sample size is not above one: " + n);
081        }
082        ArgumentUtils.checkErrorRate(alpha);
083        return create(mean, variance, n, alpha);
084    }
085
086    /**
087     * Create a confidence interval from an independent sample from an unknown normally
088     * distributed population with the given error rate.
089     *
090     * @param mean Sample mean.
091     * @param variance Unbiased sample variance.
092     * @param n Sample size.
093     * @param alpha Desired error rate.
094     * @return Confidence interval
095     */
096    abstract Interval create(double mean, double variance, long n, double alpha);
097}