001: /*
002: * Copyright 2003-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.apache.commons.math.distribution;
017:
018: import java.io.Serializable;
019:
020: import org.apache.commons.math.MathException;
021:
022: /**
023: * The default implementation of {@link ExponentialDistribution}.
024: *
025: * @version $Revision: 355770 $ $Date: 2005-12-10 12:48:57 -0700 (Sat, 10 Dec 2005) $
026: */
027: public class ExponentialDistributionImpl extends
028: AbstractContinuousDistribution implements
029: ExponentialDistribution, Serializable {
030:
031: /** Serializable version identifier */
032: private static final long serialVersionUID = 2401296428283614780L;
033:
034: /** The mean of this distribution. */
035: private double mean;
036:
037: /**
038: * Create a exponential distribution with the given mean.
039: * @param mean mean of this distribution.
040: */
041: public ExponentialDistributionImpl(double mean) {
042: super ();
043: setMean(mean);
044: }
045:
046: /**
047: * Modify the mean.
048: * @param mean the new mean.
049: * @throws IllegalArgumentException if <code>mean</code> is not positive.
050: */
051: public void setMean(double mean) {
052: if (mean <= 0.0) {
053: throw new IllegalArgumentException("mean must be positive.");
054: }
055: this .mean = mean;
056: }
057:
058: /**
059: * Access the mean.
060: * @return the mean.
061: */
062: public double getMean() {
063: return mean;
064: }
065:
066: /**
067: * For this disbution, X, this method returns P(X < x).
068: *
069: * The implementation of this method is based on:
070: * <ul>
071: * <li>
072: * <a href="http://mathworld.wolfram.com/ExponentialDistribution.html">
073: * Exponential Distribution</a>, equation (1).</li>
074: * </ul>
075: *
076: * @param x the value at which the CDF is evaluated.
077: * @return CDF for this distribution.
078: * @throws MathException if the cumulative probability can not be
079: * computed due to convergence or other numerical errors.
080: */
081: public double cumulativeProbability(double x) throws MathException {
082: double ret;
083: if (x <= 0.0) {
084: ret = 0.0;
085: } else {
086: ret = 1.0 - Math.exp(-x / getMean());
087: }
088: return ret;
089: }
090:
091: /**
092: * For this distribution, X, this method returns the critical point x, such
093: * that P(X < x) = <code>p</code>.
094: * <p>
095: * Returns 0 for p=0 and <code>Double.POSITIVE_INFINITY</code> for p=1.
096: *
097: * @param p the desired probability
098: * @return x, such that P(X < x) = <code>p</code>
099: * @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)
104: throws MathException {
105: double ret;
106:
107: if (p < 0.0 || p > 1.0) {
108: throw new IllegalArgumentException(
109: "probability argument must be between 0 and 1 (inclusive)");
110: } else if (p == 1.0) {
111: ret = Double.POSITIVE_INFINITY;
112: } else {
113: ret = -getMean() * Math.log(1.0 - p);
114: }
115:
116: return ret;
117: }
118:
119: /**
120: * Access the domain value lower bound, based on <code>p</code>, used to
121: * bracket a CDF root.
122: *
123: * @param p the desired probability for the critical value
124: * @return domain value lower bound, i.e.
125: * P(X < <i>lower bound</i>) < <code>p</code>
126: */
127: protected double getDomainLowerBound(double p) {
128: return 0;
129: }
130:
131: /**
132: * Access the domain value upper bound, based on <code>p</code>, used to
133: * bracket a CDF root.
134: *
135: * @param p the desired probability for the critical value
136: * @return domain value upper bound, i.e.
137: * P(X < <i>upper bound</i>) > <code>p</code>
138: */
139: protected double getDomainUpperBound(double p) {
140: // NOTE: exponential is skewed to the left
141: // NOTE: therefore, P(X < μ) > .5
142:
143: if (p < .5) {
144: // use mean
145: return getMean();
146: } else {
147: // use max
148: return Double.MAX_VALUE;
149: }
150: }
151:
152: /**
153: * Access the initial domain value, based on <code>p</code>, used to
154: * bracket a CDF root.
155: *
156: * @param p the desired probability for the critical value
157: * @return initial domain value
158: */
159: protected double getInitialDomain(double p) {
160: // TODO: try to improve on this estimate
161: // Exponential is skewed to the left, therefore, P(X < μ) > .5
162: if (p < .5) {
163: // use 1/2 mean
164: return getMean() * .5;
165: } else {
166: // use mean
167: return getMean();
168: }
169: }
170: }
|