View Javadoc

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