ChiSquaredDistribution.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.math3.distribution;

  18. import org.apache.commons.math3.random.RandomGenerator;
  19. import org.apache.commons.math3.random.Well19937c;

  20. /**
  21.  * Implementation of the chi-squared distribution.
  22.  *
  23.  * @see <a href="http://en.wikipedia.org/wiki/Chi-squared_distribution">Chi-squared distribution (Wikipedia)</a>
  24.  * @see <a href="http://mathworld.wolfram.com/Chi-SquaredDistribution.html">Chi-squared Distribution (MathWorld)</a>
  25.  */
  26. public class ChiSquaredDistribution extends AbstractRealDistribution {
  27.     /**
  28.      * Default inverse cumulative probability accuracy
  29.      * @since 2.1
  30.      */
  31.     public static final double DEFAULT_INVERSE_ABSOLUTE_ACCURACY = 1e-9;
  32.     /** Serializable version identifier */
  33.     private static final long serialVersionUID = -8352658048349159782L;
  34.     /** Internal Gamma distribution. */
  35.     private final GammaDistribution gamma;
  36.     /** Inverse cumulative probability accuracy */
  37.     private final double solverAbsoluteAccuracy;

  38.     /**
  39.      * Create a Chi-Squared distribution with the given degrees of freedom.
  40.      *
  41.      * @param degreesOfFreedom Degrees of freedom.
  42.      */
  43.     public ChiSquaredDistribution(double degreesOfFreedom) {
  44.         this(degreesOfFreedom, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
  45.     }

  46.     /**
  47.      * Create a Chi-Squared distribution with the given degrees of freedom and
  48.      * inverse cumulative probability accuracy.
  49.      * <p>
  50.      * <b>Note:</b> this constructor will implicitly create an instance of
  51.      * {@link Well19937c} as random generator to be used for sampling only (see
  52.      * {@link #sample()} and {@link #sample(int)}). In case no sampling is
  53.      * needed for the created distribution, it is advised to pass {@code null}
  54.      * as random generator via the appropriate constructors to avoid the
  55.      * additional initialisation overhead.
  56.      *
  57.      * @param degreesOfFreedom Degrees of freedom.
  58.      * @param inverseCumAccuracy the maximum absolute error in inverse
  59.      * cumulative probability estimates (defaults to
  60.      * {@link #DEFAULT_INVERSE_ABSOLUTE_ACCURACY}).
  61.      * @since 2.1
  62.      */
  63.     public ChiSquaredDistribution(double degreesOfFreedom,
  64.                                   double inverseCumAccuracy) {
  65.         this(new Well19937c(), degreesOfFreedom, inverseCumAccuracy);
  66.     }

  67.     /**
  68.      * Create a Chi-Squared distribution with the given degrees of freedom.
  69.      *
  70.      * @param rng Random number generator.
  71.      * @param degreesOfFreedom Degrees of freedom.
  72.      * @since 3.3
  73.      */
  74.     public ChiSquaredDistribution(RandomGenerator rng, double degreesOfFreedom) {
  75.         this(rng, degreesOfFreedom, DEFAULT_INVERSE_ABSOLUTE_ACCURACY);
  76.     }

  77.     /**
  78.      * Create a Chi-Squared distribution with the given degrees of freedom and
  79.      * inverse cumulative probability accuracy.
  80.      *
  81.      * @param rng Random number generator.
  82.      * @param degreesOfFreedom Degrees of freedom.
  83.      * @param inverseCumAccuracy the maximum absolute error in inverse
  84.      * cumulative probability estimates (defaults to
  85.      * {@link #DEFAULT_INVERSE_ABSOLUTE_ACCURACY}).
  86.      * @since 3.1
  87.      */
  88.     public ChiSquaredDistribution(RandomGenerator rng,
  89.                                   double degreesOfFreedom,
  90.                                   double inverseCumAccuracy) {
  91.         super(rng);

  92.         gamma = new GammaDistribution(degreesOfFreedom / 2, 2);
  93.         solverAbsoluteAccuracy = inverseCumAccuracy;
  94.     }

  95.     /**
  96.      * Access the number of degrees of freedom.
  97.      *
  98.      * @return the degrees of freedom.
  99.      */
  100.     public double getDegreesOfFreedom() {
  101.         return gamma.getShape() * 2.0;
  102.     }

  103.     /** {@inheritDoc} */
  104.     public double density(double x) {
  105.         return gamma.density(x);
  106.     }

  107.     /** {@inheritDoc} **/
  108.     @Override
  109.     public double logDensity(double x) {
  110.         return gamma.logDensity(x);
  111.     }

  112.     /** {@inheritDoc} */
  113.     public double cumulativeProbability(double x)  {
  114.         return gamma.cumulativeProbability(x);
  115.     }

  116.     /** {@inheritDoc} */
  117.     @Override
  118.     protected double getSolverAbsoluteAccuracy() {
  119.         return solverAbsoluteAccuracy;
  120.     }

  121.     /**
  122.      * {@inheritDoc}
  123.      *
  124.      * For {@code k} degrees of freedom, the mean is {@code k}.
  125.      */
  126.     public double getNumericalMean() {
  127.         return getDegreesOfFreedom();
  128.     }

  129.     /**
  130.      * {@inheritDoc}
  131.      *
  132.      * @return {@code 2 * k}, where {@code k} is the number of degrees of freedom.
  133.      */
  134.     public double getNumericalVariance() {
  135.         return 2 * getDegreesOfFreedom();
  136.     }

  137.     /**
  138.      * {@inheritDoc}
  139.      *
  140.      * The lower bound of the support is always 0 no matter the
  141.      * degrees of freedom.
  142.      *
  143.      * @return zero.
  144.      */
  145.     public double getSupportLowerBound() {
  146.         return 0;
  147.     }

  148.     /**
  149.      * {@inheritDoc}
  150.      *
  151.      * The upper bound of the support is always positive infinity no matter the
  152.      * degrees of freedom.
  153.      *
  154.      * @return {@code Double.POSITIVE_INFINITY}.
  155.      */
  156.     public double getSupportUpperBound() {
  157.         return Double.POSITIVE_INFINITY;
  158.     }

  159.     /** {@inheritDoc} */
  160.     public boolean isSupportLowerBoundInclusive() {
  161.         return true;
  162.     }

  163.     /** {@inheritDoc} */
  164.     public boolean isSupportUpperBoundInclusive() {
  165.         return false;
  166.     }

  167.     /**
  168.      * {@inheritDoc}
  169.      *
  170.      * The support of this distribution is connected.
  171.      *
  172.      * @return {@code true}
  173.      */
  174.     public boolean isSupportConnected() {
  175.         return true;
  176.     }
  177. }