View Javadoc

    1   /*
    2    * Copyright 2003-2004 The Apache Software Foundation.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *      http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  package org.apache.commons.math.distribution;
    17
    18  import java.io.Serializable;
    19
    20  import org.apache.commons.math.MathException;
    21
    22  /***
    23   * The default implementation of {@link ChiSquaredDistribution}
    24   *
    25   * @version $Revision: 1.19 $ $Date: 2004/07/24 20:43:29 $
    26   */
    27  public class ChiSquaredDistributionImpl
    28      extends AbstractContinuousDistribution
    29      implements ChiSquaredDistribution, Serializable  {
    30
    31      /*** Serializable version identifier */
    32      static final long serialVersionUID = -8352658048349159782L;
    33
    34      /*** Internal Gamma distribution. */
    35      private GammaDistribution gamma;
    36
    37      /***
    38       * Create a Chi-Squared distribution with the given degrees of freedom.
    39       * @param degreesOfFreedom degrees of freedom.
    40       */
    41      public ChiSquaredDistributionImpl(double degreesOfFreedom) {
    42          super();
    43          setGamma(DistributionFactory.newInstance().createGammaDistribution(
    44              degreesOfFreedom / 2.0, 2.0));
    45      }
    46
    47      /***
    48       * Modify the degrees of freedom.
    49       * @param degreesOfFreedom the new degrees of freedom.
    50       */
    51      public void setDegreesOfFreedom(double degreesOfFreedom) {
    52          getGamma().setAlpha(degreesOfFreedom / 2.0);
    53      }
    54
    55      /***
    56       * Access the degrees of freedom.
    57       * @return the degrees of freedom.
    58       */
    59      public double getDegreesOfFreedom() {
    60          return getGamma().getAlpha() * 2.0;
    61      }
    62
    63      /***
    64       * For this disbution, X, this method returns P(X &lt; x).
    65       * @param x the value at which the CDF is evaluated.
    66       * @return CDF for this distribution.
    67       * @throws MathException if the cumulative probability can not be
    68       *            computed due to convergence or other numerical errors.
    69       */
    70      public double cumulativeProbability(double x) throws MathException {
    71          return getGamma().cumulativeProbability(x);
    72      }
    73
    74      /***
    75       * For this distribution, X, this method returns the critical point x, such
    76       * that P(X &lt; x) = <code>p</code>.
    77       * <p>
    78       * Returns 0 for p=0 and <code>Double.POSITIVE_INFINITY</code> for p=1.
    79       *
    80       * @param p the desired probability
    81       * @return x, such that P(X &lt; x) = <code>p</code>
    82       * @throws MathException if the inverse cumulative probability can not be
    83       *         computed due to convergence or other numerical errors.
    84       * @throws IllegalArgumentException if <code>p</code> is not a valid
    85       *         probability.
    86       */
    87      public double inverseCumulativeProbability(final double p)
    88          throws MathException {
    89          if (p == 0) {
    90              return 0d;
    91          }
    92          if (p == 1) {
    93              return Double.POSITIVE_INFINITY;
    94          }
    95          return super.inverseCumulativeProbability(p);
    96      }
    97
    98      /***
    99       * Access the domain value lower bound, based on <code>p</code>, used to
    100      * bracket a CDF root.  This method is used by
    101      * {@link #inverseCumulativeProbability(double)} to find critical values.
    102      *
    103      * @param p the desired probability for the critical value
    104      * @return domain value lower bound, i.e.
    105      *         P(X &lt; <i>lower bound</i>) &lt; <code>p</code>
    106      */
    107     protected double getDomainLowerBound(double p) {
    108         return Double.MIN_VALUE * getGamma().getBeta();
    109     }
    110
    111     /***
    112      * Access the domain value upper bound, based on <code>p</code>, used to
    113      * bracket a CDF root.  This method is used by
    114      * {@link #inverseCumulativeProbability(double)} to find critical values.
    115      *
    116      * @param p the desired probability for the critical value
    117      * @return domain value upper bound, i.e.
    118      *         P(X &lt; <i>upper bound</i>) &gt; <code>p</code>
    119      */
    120     protected double getDomainUpperBound(double p) {
    121         // NOTE: chi squared is skewed to the left
    122         // NOTE: therefore, P(X < &mu;) > .5
    123
    124         double ret;
    125
    126         if (p < .5) {
    127             // use mean
    128             ret = getDegreesOfFreedom();
    129         } else {
    130             // use max
    131             ret = Double.MAX_VALUE;
    132         }
    133
    134         return ret;
    135     }
    136
    137     /***
    138      * Access the initial domain value, based on <code>p</code>, used to
    139      * bracket a CDF root.  This method is used by
    140      * {@link #inverseCumulativeProbability(double)} to find critical values.
    141      *
    142      * @param p the desired probability for the critical value
    143      * @return initial domain value
    144      */
    145     protected double getInitialDomain(double p) {
    146         // NOTE: chi squared is skewed to the left
    147         // NOTE: therefore, P(X < &mu;) > .5
    148
    149         double ret;
    150
    151         if (p < .5) {
    152             // use 1/2 mean
    153             ret = getDegreesOfFreedom() * .5;
    154         } else {
    155             // use mean
    156             ret = getDegreesOfFreedom();
    157         }
    158
    159         return ret;
    160     }
    161
    162     /***
    163      * Modify the Gamma distribution.
    164      * @param gamma the new distribution.
    165      */
    166     private void setGamma(GammaDistribution gamma) {
    167         this.gamma = gamma;
    168     }
    169
    170     /***
    171      * Access the Gamma distribution.
    172      * @return the internal Gamma distribution.
    173      */
    174     private GammaDistribution getGamma() {
    175         return gamma;
    176     }
    177 }