19
19
import java.io.Serializable;
21
21
import org.apache.commons.math.ConvergenceException;
22
import org.apache.commons.math.FunctionEvaluationException;
23
22
import org.apache.commons.math.MathException;
24
23
import org.apache.commons.math.MathRuntimeException;
25
24
import org.apache.commons.math.analysis.UnivariateRealFunction;
26
25
import org.apache.commons.math.analysis.solvers.BrentSolver;
27
26
import org.apache.commons.math.analysis.solvers.UnivariateRealSolverUtils;
27
import org.apache.commons.math.FunctionEvaluationException;
28
import org.apache.commons.math.exception.util.LocalizedFormats;
29
import org.apache.commons.math.random.RandomDataImpl;
30
import org.apache.commons.math.util.FastMath;
30
33
* Base class for continuous distributions. Default implementations are
31
34
* provided for some of the methods that do not vary from distribution to
34
* @version $Revision: 925812 $ $Date: 2010-03-21 11:49:31 -0400 (Sun, 21 Mar 2010) $
37
* @version $Revision: 1073498 $ $Date: 2011-02-22 21:57:26 +0100 (mar. 22 févr. 2011) $
36
39
public abstract class AbstractContinuousDistribution
37
40
extends AbstractDistribution
41
44
private static final long serialVersionUID = -38038050983108802L;
44
* Solver absolute accuracy for inverse cum computation
47
* RandomData instance used to generate samples from the distribution
50
protected final RandomDataImpl randomData = new RandomDataImpl();
53
* Solver absolute accuracy for inverse cumulative computation
47
56
private double solverAbsoluteAccuracy = BrentSolver.DEFAULT_ABSOLUTE_ACCURACY;
63
72
public double density(double x) throws MathRuntimeException {
64
73
throw new MathRuntimeException(new UnsupportedOperationException(),
65
"This distribution does not have a density function implemented");
74
LocalizedFormats.NO_DENSITY_FOR_THIS_DISTRIBUTION);
80
89
throws MathException {
81
90
if (p < 0.0 || p > 1.0) {
82
91
throw MathRuntimeException.createIllegalArgumentException(
83
"{0} out of [{1}, {2}] range", p, 0.0, 1.0);
92
LocalizedFormats.OUT_OF_RANGE_SIMPLE, p, 0.0, 1.0);
86
95
// by default, do simple root finding using bracketing and default solver.
93
102
ret = cumulativeProbability(x) - p;
94
103
} catch (MathException ex) {
95
throw new FunctionEvaluationException(ex, x, ex.getPattern(), ex.getArguments());
104
throw new FunctionEvaluationException(x, ex.getSpecificPattern(), ex.getGeneralPattern(), ex.getArguments());
97
106
if (Double.isNaN(ret)) {
98
throw new FunctionEvaluationException(x,
99
"Cumulative probability function returned NaN for argument {0} p = {1}", x, p);
107
throw new FunctionEvaluationException(x, LocalizedFormats.CUMULATIVE_PROBABILITY_RETURNED_NAN, x, p);
105
// Try to bracket root, test domain endoints if this fails
113
// Try to bracket root, test domain endpoints if this fails
106
114
double lowerBound = getDomainLowerBound(p);
107
115
double upperBound = getDomainUpperBound(p);
108
116
double[] bracket = null;
116
124
* the default solver's defaultAbsoluteAccuracy of 0 (will be the
117
125
* case if density has bounded support and p is 0 or 1).
119
if (Math.abs(rootFindingFunction.value(lowerBound)) < getSolverAbsoluteAccuracy()) {
127
if (FastMath.abs(rootFindingFunction.value(lowerBound)) < getSolverAbsoluteAccuracy()) {
120
128
return lowerBound;
122
if (Math.abs(rootFindingFunction.value(upperBound)) < getSolverAbsoluteAccuracy()) {
130
if (FastMath.abs(rootFindingFunction.value(upperBound)) < getSolverAbsoluteAccuracy()) {
123
131
return upperBound;
125
133
// Failed bracket convergence was not because of corner solution
146
* Reseeds the random generator used to generate samples.
148
* @param seed the new seed
151
public void reseedRandomGenerator(long seed) {
152
randomData.reSeed(seed);
156
* Generates a random value sampled from this distribution. The default
157
* implementation uses the
158
* <a href="http://en.wikipedia.org/wiki/Inverse_transform_sampling"> inversion method.</a>
160
* @return random value
162
* @throws MathException if an error occurs generating the random value
164
public double sample() throws MathException {
165
return randomData.nextInversionDeviate(this);
169
* Generates a random sample from the distribution. The default implementation
170
* generates the sample by calling {@link #sample()} in a loop.
172
* @param sampleSize number of random values to generate
174
* @return an array representing the random sample
175
* @throws MathException if an error occurs generating the sample
176
* @throws IllegalArgumentException if sampleSize is not positive
178
public double[] sample(int sampleSize) throws MathException {
179
if (sampleSize <= 0) {
180
MathRuntimeException.createIllegalArgumentException(LocalizedFormats.NOT_POSITIVE_SAMPLE_SIZE, sampleSize);
182
double[] out = new double[sampleSize];
183
for (int i = 0; i < sampleSize; i++) {
138
190
* Access the initial domain value, based on <code>p</code>, used to
139
191
* bracket a CDF root. This method is used by
140
192
* {@link #inverseCumulativeProbability(double)} to find critical values.
167
219
protected abstract double getDomainUpperBound(double p);
170
* Returns the solver absolute accuracy for inverse cum computation.
222
* Returns the solver absolute accuracy for inverse cumulative computation.
172
224
* @return the maximum absolute error in inverse cumulative probability estimates