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  /***
    24   * Base class for integer-valued discrete distributions.  Default
    25   * implementations are provided for some of the methods that do not vary
    26   * from distribution to distribution.
    27   *
    28   * @version $Revision: 1.1 $ $Date: 2004/11/07 03:32:48 $
    29   */
    30  public abstract class AbstractIntegerDistribution extends AbstractDistribution
    31      implements IntegerDistribution, Serializable {
    32
    33      /*** Serializable version identifier */
    34      static final long serialVersionUID = -1146319659338487221L;
    35
    36      /***
    37       * Default constructor.
    38       */
    39      protected AbstractIntegerDistribution() {
    40          super();
    41      }
    42
    43      /***
    44       * For a random variable X whose values are distributed according
    45       * to this distribution, this method returns P(X &le; x).  In other words,
    46       * this method represents the  (cumulative) distribution function, or
    47       * CDF, for this distribution.
    48       * <p>
    49       * If <code>x</code> does not represent an integer value, the CDF is
    50       * evaluated at the greatest integer less than x.
    51       *
    52       * @param x the value at which the distribution function is evaluated.
    53       * @return cumulative probability that a random variable with this
    54       * distribution takes a value less than or equal to <code>x</code>
    55       * @throws MathException if the cumulative probability can not be
    56       * computed due to convergence or other numerical errors.
    57       */
    58      public double cumulativeProbability(double x) throws MathException {
    59          return cumulativeProbability((int) Math.floor(x));
    60      }
    61
    62      /***
    63       * For a random variable X whose values are distributed according
    64       * to this distribution, this method returns P(X &le; x).  In other words,
    65       * this method represents the probability distribution function, or PDF,
    66       * for this distribution.
    67       *
    68       * @param x the value at which the PDF is evaluated.
    69       * @return PDF for this distribution.
    70       * @throws MathException if the cumulative probability can not be
    71       *            computed due to convergence or other numerical errors.
    72       */
    73      abstract public double cumulativeProbability(int x) throws MathException;
    74
    75      /***
    76       * For a random variable X whose values are distributed according
    77       * to this distribution, this method returns P(X = x). In other words, this
    78       * method represents the probability mass function,  or PMF, for the distribution.
    79       * <p>
    80       * If <code>x</code> does not represent an integer value, 0 is returned.
    81       *
    82       * @param x the value at which the probability density function is evaluated
    83       * @return the value of the probability density function at x
    84       */
    85      public double probability(double x) {
    86          double fl = Math.floor(x);
    87          if (fl == x) {
    88              return this.probability((int) x);
    89          } else {
    90              return 0;
    91          }
    92      }
    93
    94      /***
    95      * For a random variable X whose values are distributed according
    96       * to this distribution, this method returns P(x0 &le; X &le; x1).
    97       *
    98       * @param x0 the inclusive, lower bound
    99       * @param x1 the inclusive, upper bound
    100      * @return the cumulative probability.
    101      * @throws MathException if the cumulative probability can not be
    102      *            computed due to convergence or other numerical errors.
    103      * @throws IllegalArgumentException if x0 > x1
    104      */
    105     public double cumulativeProbability(int x0, int x1) throws MathException {
    106         if (x0 > x1) {
    107             throw new IllegalArgumentException
    108             	("lower endpoint must be less than or equal to upper endpoint");
    109         }
    110         return cumulativeProbability(x1) - cumulativeProbability(x0 - 1);
    111     }
    112
    113     /***
    114      * For a random variable X whose values are distributed according
    115      * to this distribution, this method returns the largest x, such
    116      * that P(X &le; x) &le; <code>p</code>.
    117      *
    118      * @param p the desired probability
    119      * @return the largest x such that P(X &le; x) <= p
    120      * @throws MathException if the inverse cumulative probability can not be
    121      *            computed due to convergence or other numerical errors.
    122      * @throws IllegalArgumentException if p < 0 or p > 1
    123      */
    124     public int inverseCumulativeProbability(final double p) throws MathException{
    125         if (p < 0.0 || p > 1.0) {
    126             throw new IllegalArgumentException(
    127                 "p must be between 0 and 1.0 (inclusive)");
    128         }
    129
    130         // by default, do simple bisection.
    131         // subclasses can override if there is a better method.
    132         int x0 = getDomainLowerBound(p);
    133         int x1 = getDomainUpperBound(p);
    134         double pm;
    135         while (x0 < x1) {
    136             int xm = x0 + (x1 - x0) / 2;
    137             pm = cumulativeProbability(xm);
    138             if (pm > p) {
    139                 // update x1
    140                 if (xm == x1) {
    141                     // this can happen with integer division
    142                     // simply decrement x1
    143                     --x1;
    144                 } else {
    145                     // update x1 normally
    146                     x1 = xm;
    147                 }
    148             } else {
    149                 // update x0
    150                 if (xm == x0) {
    151                     // this can happen with integer division
    152                     // simply increment x0
    153                     ++x0;
    154                 } else {
    155                     // update x0 normally
    156                     x0 = xm;
    157                 }
    158             }
    159         }
    160
    161         // insure x0 is the correct critical point
    162         pm = cumulativeProbability(x0);
    163         while (pm > p) {
    164             --x0;
    165             pm = cumulativeProbability(x0);
    166         }
    167
    168         return x0;
    169     }
    170
    171     /***
    172      * Access the domain value lower bound, based on <code>p</code>, used to
    173      * bracket a PDF root.  This method is used by
    174      * {@link #inverseCumulativeProbability(double)} to find critical values.
    175      *
    176      * @param p the desired probability for the critical value
    177      * @return domain value lower bound, i.e.
    178      *         P(X &lt; <i>lower bound</i>) &lt; <code>p</code>
    179      */
    180     protected abstract int getDomainLowerBound(double p);
    181
    182     /***
    183      * Access the domain value upper bound, based on <code>p</code>, used to
    184      * bracket a PDF root.  This method is used by
    185      * {@link #inverseCumulativeProbability(double)} to find critical values.
    186      *
    187      * @param p the desired probability for the critical value
    188      * @return domain value upper bound, i.e.
    189      *         P(X &lt; <i>upper bound</i>) &gt; <code>p</code>
    190      */
    191     protected abstract int getDomainUpperBound(double p);
    192 }