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 < 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 < 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 < 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 < <i>lower bound</i>) < <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 < <i>upper bound</i>) > <code>p</code> 136 */ 137 protected double getDomainUpperBound(double p) { 138 // NOTE: exponential is skewed to the left 139 // NOTE: therefore, P(X < μ) > .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 < μ) > .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 }