1
2
3
4
5
6
7
8
9
10
11
12
13
14
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 /**
24 * Base class for integer-valued discrete distributions. Default
25 * implementations are provided for some of the methods that do not vary
26 * from distribution to distribution.
27 *
28 * @version $Revision: 348519 $ $Date: 2005-11-23 12:12:18 -0700 (Wed, 23 Nov 2005) $
29 */
30 public abstract class AbstractIntegerDistribution extends AbstractDistribution
31 implements IntegerDistribution, Serializable {
32
33 /** Serializable version identifier */
34 private static final long serialVersionUID = -1146319659338487221L;
35
36 /**
37 * Default constructor.
38 */
39 protected AbstractIntegerDistribution() {
40 super();
41 }
42
43 /**
44 * For a random variable X whose values are distributed according
45 * to this distribution, this method returns P(X ≤ x). In other words,
46 * this method represents the (cumulative) distribution function, or
47 * CDF, for this distribution.
48 * <p>
49 * If <code>x</code> does not represent an integer value, the CDF is
50 * evaluated at the greatest integer less than x.
51 *
52 * @param x the value at which the distribution function is evaluated.
53 * @return cumulative probability that a random variable with this
54 * distribution takes a value less than or equal to <code>x</code>
55 * @throws MathException if the cumulative probability can not be
56 * computed due to convergence or other numerical errors.
57 */
58 public double cumulativeProbability(double x) throws MathException {
59 return cumulativeProbability((int) Math.floor(x));
60 }
61
62 /**
63 * For a random variable X whose values are distributed according
64 * to this distribution, this method returns P(X ≤ x). In other words,
65 * this method represents the probability distribution function, or PDF,
66 * for this distribution.
67 *
68 * @param x the value at which the PDF is evaluated.
69 * @return PDF for this distribution.
70 * @throws MathException if the cumulative probability can not be
71 * computed due to convergence or other numerical errors.
72 */
73 abstract public double cumulativeProbability(int x) throws MathException;
74
75 /**
76 * For a random variable X whose values are distributed according
77 * to this distribution, this method returns P(X = x). In other words, this
78 * method represents the probability mass function, or PMF, for the distribution.
79 * <p>
80 * If <code>x</code> does not represent an integer value, 0 is returned.
81 *
82 * @param x the value at which the probability density function is evaluated
83 * @return the value of the probability density function at x
84 */
85 public double probability(double x) {
86 double fl = Math.floor(x);
87 if (fl == x) {
88 return this.probability((int) x);
89 } else {
90 return 0;
91 }
92 }
93
94 /**
95 * For a random variable X whose values are distributed according
96 * to this distribution, this method returns P(x0 ≤ X ≤ x1).
97 *
98 * @param x0 the inclusive, lower bound
99 * @param x1 the inclusive, upper bound
100 * @return the cumulative probability.
101 * @throws MathException if the cumulative probability can not be
102 * computed due to convergence or other numerical errors.
103 * @throws IllegalArgumentException if x0 > x1
104 */
105 public double cumulativeProbability(int x0, int x1) throws MathException {
106 if (x0 > x1) {
107 throw new IllegalArgumentException
108 ("lower endpoint must be less than or equal to upper endpoint");
109 }
110 return cumulativeProbability(x1) - cumulativeProbability(x0 - 1);
111 }
112
113 /**
114 * For a random variable X whose values are distributed according
115 * to this distribution, this method returns the largest x, such
116 * that P(X ≤ x) ≤ <code>p</code>.
117 *
118 * @param p the desired probability
119 * @return the largest x such that P(X ≤ x) <= p
120 * @throws MathException if the inverse cumulative probability can not be
121 * computed due to convergence or other numerical errors.
122 * @throws IllegalArgumentException if p < 0 or p > 1
123 */
124 public int inverseCumulativeProbability(final double p) throws MathException{
125 if (p < 0.0 || p > 1.0) {
126 throw new IllegalArgumentException(
127 "p must be between 0 and 1.0 (inclusive)");
128 }
129
130
131
132 int x0 = getDomainLowerBound(p);
133 int x1 = getDomainUpperBound(p);
134 double pm;
135 while (x0 < x1) {
136 int xm = x0 + (x1 - x0) / 2;
137 pm = cumulativeProbability(xm);
138 if (pm > p) {
139
140 if (xm == x1) {
141
142
143 --x1;
144 } else {
145
146 x1 = xm;
147 }
148 } else {
149
150 if (xm == x0) {
151
152
153 ++x0;
154 } else {
155
156 x0 = xm;
157 }
158 }
159 }
160
161
162 pm = cumulativeProbability(x0);
163 while (pm > p) {
164 --x0;
165 pm = cumulativeProbability(x0);
166 }
167
168 return x0;
169 }
170
171 /**
172 * Access the domain value lower bound, based on <code>p</code>, used to
173 * bracket a PDF root. This method is used by
174 * {@link #inverseCumulativeProbability(double)} to find critical values.
175 *
176 * @param p the desired probability for the critical value
177 * @return domain value lower bound, i.e.
178 * P(X < <i>lower bound</i>) < <code>p</code>
179 */
180 protected abstract int getDomainLowerBound(double p);
181
182 /**
183 * Access the domain value upper bound, based on <code>p</code>, used to
184 * bracket a PDF root. This method is used by
185 * {@link #inverseCumulativeProbability(double)} to find critical values.
186 *
187 * @param p the desired probability for the critical value
188 * @return domain value upper bound, i.e.
189 * P(X < <i>upper bound</i>) > <code>p</code>
190 */
191 protected abstract int getDomainUpperBound(double p);
192 }