01: package JSci.maths.statistics;
02:
03: /**
04: * The ProbabilityDistribution superclass provides an object for encapsulating probability distributions.
05: * @version 1.0
06: * @author Jaco van Kooten
07: */
08: public abstract class ProbabilityDistribution extends Object {
09: /**
10: * Constructs a probability distribution.
11: */
12: public ProbabilityDistribution() {
13: }
14:
15: /**
16: * Probability density function.
17: * @return the probability that a stochastic variable x has the value X, i.e. P(x=X).
18: */
19: public abstract double probability(double X);
20:
21: /**
22: * Cumulative distribution function.
23: * @return the probability that a stochastic variable x is less then X, i.e. P(x<X).
24: */
25: public abstract double cumulative(double X);
26:
27: /**
28: * Inverse of the cumulative distribution function.
29: * @return the value X for which P(x<X).
30: */
31: public abstract double inverse(double probability);
32:
33: /**
34: * Check if the range of the argument of the distribution method is between <code>lo</code> and <code>hi</code>.
35: * @exception OutOfRangeException If the argument is out of range.
36: */
37: protected final void checkRange(double x, double lo, double hi) {
38: if (x < lo || x > hi)
39: throw new OutOfRangeException(
40: "The argument of the distribution method should be between "
41: + lo + " and " + hi + ".");
42: }
43:
44: /**
45: * Check if the range of the argument of the distribution method is between 0.0 and 1.0.
46: * @exception OutOfRangeException If the argument is out of range.
47: */
48: protected final void checkRange(double x) {
49: if (x < 0.0 || x > 1.0)
50: throw new OutOfRangeException(
51: "The argument of the distribution method should be between 0.0 and 1.0.");
52: }
53:
54: private static final double FINDROOT_ACCURACY = 1.0e-15;
55: private static final int FINDROOT_MAX_ITERATIONS = 150;
56:
57: /**
58: * This method approximates the value of X for which P(x<X)=<I>prob</I>.
59: * It applies a combination of a Newton-Raphson procedure and bisection method
60: * with the value <I>guess</I> as a starting point. Furthermore, to ensure convergency
61: * and stability, one should supply an inverval [<I>xLo</I>,<I>xHi</I>] in which the probalility
62: * distribution reaches the value <I>prob</I>. The method does no checking, it will produce
63: * bad results if wrong values for the parameters are supplied - use it with care.
64: */
65: protected final double findRoot(double prob, double guess,
66: double xLo, double xHi) {
67: double x = guess, xNew = guess;
68: double error, pdf, dx = 1.0;
69: int i = 0;
70: while (Math.abs(dx) > FINDROOT_ACCURACY
71: && i++ < FINDROOT_MAX_ITERATIONS) {
72: // Apply Newton-Raphson step
73: error = cumulative(x) - prob;
74: if (error < 0.0)
75: xLo = x;
76: else
77: xHi = x;
78: pdf = probability(x);
79: if (pdf != 0.0) { // Avoid division by zero
80: dx = error / pdf;
81: xNew = x - dx;
82: }
83: // If the Newton-Raphson fails to converge (which for example may be the
84: // case if the initial guess is to rough) we apply a bisection
85: // step to determine a more narrow interval around the root.
86: if (xNew < xLo || xNew > xHi || pdf == 0.0) {
87: xNew = (xLo + xHi) / 2.0;
88: dx = xNew - x;
89: }
90: x = xNew;
91: }
92: return x;
93: }
94: }
|