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.math3.distribution; 018 019import org.apache.commons.math3.random.RandomGenerator; 020import org.apache.commons.math3.random.Well19937c; 021 022/** 023 * Implementation of the chi-squared distribution. 024 * 025 * @see <a href="http://en.wikipedia.org/wiki/Chi-squared_distribution">Chi-squared distribution (Wikipedia)</a> 026 * @see <a href="http://mathworld.wolfram.com/Chi-SquaredDistribution.html">Chi-squared Distribution (MathWorld)</a> 027 */ 028public class ChiSquaredDistribution extends AbstractRealDistribution { 029 /** 030 * Default inverse cumulative probability accuracy 031 * @since 2.1 032 */ 033 public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9; 034 /** Serializable version identifier */ 035 private static final long serialVersionUID = -8352658048349159782L; 036 /** Internal Gamma distribution. */ 037 private final GammaDistribution gamma; 038 /** Inverse cumulative probability accuracy */ 039 private final double solverAbsoluteAccuracy; 040 041 /** 042 * Create a Chi-Squared distribution with the given degrees of freedom. 043 * 044 * @param degreesOfFreedom Degrees of freedom. 045 */ 046 public ChiSquaredDistribution(double degreesOfFreedom) { 047 this(degreesOfFreedom, DEFAULT_INVERSE_ABSOLUTE_ACCURACY); 048 } 049 050 /** 051 * Create a Chi-Squared distribution with the given degrees of freedom and 052 * inverse cumulative probability accuracy. 053 * <p> 054 * <b>Note:</b> this constructor will implicitly create an instance of 055 * {@link Well19937c} as random generator to be used for sampling only (see 056 * {@link #sample()} and {@link #sample(int)}). In case no sampling is 057 * needed for the created distribution, it is advised to pass {@code null} 058 * as random generator via the appropriate constructors to avoid the 059 * additional initialisation overhead. 060 * 061 * @param degreesOfFreedom Degrees of freedom. 062 * @param inverseCumAccuracy the maximum absolute error in inverse 063 * cumulative probability estimates (defaults to 064 * {@link #DEFAULT_INVERSE_ABSOLUTE_ACCURACY}). 065 * @since 2.1 066 */ 067 public ChiSquaredDistribution(double degreesOfFreedom, 068 double inverseCumAccuracy) { 069 this(new Well19937c(), degreesOfFreedom, inverseCumAccuracy); 070 } 071 072 /** 073 * Create a Chi-Squared distribution with the given degrees of freedom. 074 * 075 * @param rng Random number generator. 076 * @param degreesOfFreedom Degrees of freedom. 077 * @since 3.3 078 */ 079 public ChiSquaredDistribution(RandomGenerator rng, double degreesOfFreedom) { 080 this(rng, degreesOfFreedom, DEFAULT_INVERSE_ABSOLUTE_ACCURACY); 081 } 082 083 /** 084 * Create a Chi-Squared distribution with the given degrees of freedom and 085 * inverse cumulative probability accuracy. 086 * 087 * @param rng Random number generator. 088 * @param degreesOfFreedom Degrees of freedom. 089 * @param inverseCumAccuracy the maximum absolute error in inverse 090 * cumulative probability estimates (defaults to 091 * {@link #DEFAULT_INVERSE_ABSOLUTE_ACCURACY}). 092 * @since 3.1 093 */ 094 public ChiSquaredDistribution(RandomGenerator rng, 095 double degreesOfFreedom, 096 double inverseCumAccuracy) { 097 super(rng); 098 099 gamma = new GammaDistribution(degreesOfFreedom / 2, 2); 100 solverAbsoluteAccuracy = inverseCumAccuracy; 101 } 102 103 /** 104 * Access the number of degrees of freedom. 105 * 106 * @return the degrees of freedom. 107 */ 108 public double getDegreesOfFreedom() { 109 return gamma.getShape() * 2.0; 110 } 111 112 /** {@inheritDoc} */ 113 public double density(double x) { 114 return gamma.density(x); 115 } 116 117 /** {@inheritDoc} **/ 118 @Override 119 public double logDensity(double x) { 120 return gamma.logDensity(x); 121 } 122 123 /** {@inheritDoc} */ 124 public double cumulativeProbability(double x) { 125 return gamma.cumulativeProbability(x); 126 } 127 128 /** {@inheritDoc} */ 129 @Override 130 protected double getSolverAbsoluteAccuracy() { 131 return solverAbsoluteAccuracy; 132 } 133 134 /** 135 * {@inheritDoc} 136 * 137 * For {@code k} degrees of freedom, the mean is {@code k}. 138 */ 139 public double getNumericalMean() { 140 return getDegreesOfFreedom(); 141 } 142 143 /** 144 * {@inheritDoc} 145 * 146 * @return {@code 2 * k}, where {@code k} is the number of degrees of freedom. 147 */ 148 public double getNumericalVariance() { 149 return 2 * getDegreesOfFreedom(); 150 } 151 152 /** 153 * {@inheritDoc} 154 * 155 * The lower bound of the support is always 0 no matter the 156 * degrees of freedom. 157 * 158 * @return zero. 159 */ 160 public double getSupportLowerBound() { 161 return 0; 162 } 163 164 /** 165 * {@inheritDoc} 166 * 167 * The upper bound of the support is always positive infinity no matter the 168 * degrees of freedom. 169 * 170 * @return {@code Double.POSITIVE_INFINITY}. 171 */ 172 public double getSupportUpperBound() { 173 return Double.POSITIVE_INFINITY; 174 } 175 176 /** {@inheritDoc} */ 177 public boolean isSupportLowerBoundInclusive() { 178 return true; 179 } 180 181 /** {@inheritDoc} */ 182 public boolean isSupportUpperBoundInclusive() { 183 return false; 184 } 185 186 /** 187 * {@inheritDoc} 188 * 189 * The support of this distribution is connected. 190 * 191 * @return {@code true} 192 */ 193 public boolean isSupportConnected() { 194 return true; 195 } 196}