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 ExponentialDistribution}.
    24   *
    25   * @version $Revision: 355770 $ $Date: 2005-12-10 12:48:57 -0700 (Sat, 10 Dec 2005) $
    26   */
    27  public class ExponentialDistributionImpl extends AbstractContinuousDistribution
    28      implements ExponentialDistribution, Serializable {
    29
    30      /*** Serializable version identifier */
    31      private static final long serialVersionUID = 2401296428283614780L;
    32
    33      /*** The mean of this distribution. */
    34      private double mean;
    35
    36      /***
    37       * Create a exponential distribution with the given mean.
    38       * @param mean mean of this distribution.
    39       */
    40      public ExponentialDistributionImpl(double mean) {
    41          super();
    42          setMean(mean);
    43      }
    44
    45      /***
    46       * Modify the mean.
    47       * @param mean the new mean.
    48       * @throws IllegalArgumentException if <code>mean</code> is not positive.
    49       */
    50      public void setMean(double mean) {
    51          if (mean <= 0.0) {
    52              throw new IllegalArgumentException("mean must be positive.");
    53          }
    54          this.mean = mean;
    55      }
    56
    57      /***
    58       * Access the mean.
    59       * @return the mean.
    60       */
    61      public double getMean() {
    62          return mean;
    63      }
    64
    65      /***
    66       * For this disbution, X, this method returns P(X &lt; x).
    67       *
    68       * The implementation of this method is based on:
    69       * <ul>
    70       * <li>
    71       * <a href="http://mathworld.wolfram.com/ExponentialDistribution.html">
    72       * Exponential Distribution</a>, equation (1).</li>
    73       * </ul>
    74       *
    75       * @param x the value at which the CDF is evaluated.
    76       * @return CDF for this distribution.
    77       * @throws MathException if the cumulative probability can not be
    78       *            computed due to convergence or other numerical errors.
    79       */
    80      public double cumulativeProbability(double x) throws MathException{
    81          double ret;
    82          if (x <= 0.0) {
    83              ret = 0.0;
    84          } else {
    85              ret = 1.0 - Math.exp(-x / getMean());
    86          }
    87          return ret;
    88      }
    89
    90      /***
    91       * For this distribution, X, this method returns the critical point x, such
    92       * that P(X &lt; x) = <code>p</code>.
    93       * <p>
    94       * Returns 0 for p=0 and <code>Double.POSITIVE_INFINITY</code> for p=1.
    95       *
    96       * @param p the desired probability
    97       * @return x, such that P(X &lt; x) = <code>p</code>
    98       * @throws MathException if the inverse cumulative probability can not be
    99       *            computed due to convergence or other numerical errors.
    100      * @throws IllegalArgumentException if p < 0 or p > 1.
    101      */
    102     public double inverseCumulativeProbability(double p) throws MathException {
    103         double ret;
    104
    105         if (p < 0.0 || p > 1.0) {
    106             throw new IllegalArgumentException
    107                 ("probability argument must be between 0 and 1 (inclusive)");
    108         } else if (p == 1.0) {
    109             ret = Double.POSITIVE_INFINITY;
    110         } else {
    111             ret = -getMean() * Math.log(1.0 - p);
    112         }
    113
    114         return ret;
    115     }
    116
    117     /***
    118      * Access the domain value lower bound, based on <code>p</code>, used to
    119      * bracket a CDF root.
    120      *
    121      * @param p the desired probability for the critical value
    122      * @return domain value lower bound, i.e.
    123      *         P(X &lt; <i>lower bound</i>) &lt; <code>p</code>
    124      */
    125     protected double getDomainLowerBound(double p) {
    126         return 0;
    127     }
    128
    129     /***
    130      * Access the domain value upper bound, based on <code>p</code>, used to
    131      * bracket a CDF root.
    132      *
    133      * @param p the desired probability for the critical value
    134      * @return domain value upper bound, i.e.
    135      *         P(X &lt; <i>upper bound</i>) &gt; <code>p</code>
    136      */
    137     protected double getDomainUpperBound(double p) {
    138         // NOTE: exponential is skewed to the left
    139         // NOTE: therefore, P(X < &mu;) > .5
    140
    141         if (p < .5) {
    142             // use mean
    143             return getMean();
    144         } else {
    145             // use max
    146             return Double.MAX_VALUE;
    147         }
    148     }
    149
    150     /***
    151      * Access the initial domain value, based on <code>p</code>, used to
    152      * bracket a CDF root.
    153      *
    154      * @param p the desired probability for the critical value
    155      * @return initial domain value
    156      */
    157     protected double getInitialDomain(double p) {
    158         // TODO: try to improve on this estimate
    159         // Exponential is skewed to the left, therefore, P(X < &mu;) > .5
    160         if (p < .5) {
    161             // use 1/2 mean
    162             return getMean() * .5;
    163         } else {
    164             // use mean
    165             return getMean();
    166         }
    167     }
    168 }