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