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 }