SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
WatsonUDist.java
1/*
2 * Class: WatsonUDist
3 * Description: Watson U distribution
4 * Environment: Java
5 * Software: SSJ
6 * Copyright (C) 2001 Pierre L'Ecuyer and Universite de Montreal
7 * Organization: DIRO, Universite de Montreal
8 * @author Richard Simard
9 * @since
10 *
11 *
12 * Licensed under the Apache License, Version 2.0 (the "License");
13 * you may not use this file except in compliance with the License.
14 * You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *
24 */
25package umontreal.ssj.probdist;
26
27import umontreal.ssj.util.*;
28import umontreal.ssj.functions.MathFunction;
29
49public class WatsonUDist extends ContinuousDistribution {
50 private static final double XSEPARE = 0.15;
51 private static final double PI = Math.PI;
52 private static final int JMAX = 10;
53 protected int n;
54
55 private static class Function implements MathFunction {
56 protected int n;
57 protected double u;
58
59 public Function(int n, double u) {
60 this.n = n;
61 this.u = u;
62 }
63
64 public double evaluate(double x) {
65 return u - cdf(n, x);
66 }
67 }
68
69 private static double cdfn(int n, double x) {
70 // The 1/n correction for the cdf, for x < XSEPARE
71 double terme;
72 double v = Math.exp(-0.125 / x);
73 double somme = 0;
74 int j = 0;
75
76 do {
77 double a = (2 * j + 1) * (2 * j + 1);
78 terme = Math.pow(v, (double) (2 * j + 1) * (2 * j + 1));
79 double der = terme * (a - 4.0 * x) / (8.0 * x * x);
80 somme += (5.0 * x - 1.0 / 12.0) * der / 12.0;
81 der = terme * (a * a - 24.0 * a * x + 48.0 * x * x) / (64.0 * x * x * x * x);
82 somme += x * x * der / 6.0;
83 ++j;
84 } while (!(terme <= Math.abs(somme) * Num.DBL_EPSILON || j > JMAX));
85 if (j > JMAX)
86 System.err.println(x + ": watsonU: somme 1/n has not converged");
87
88 v = -2.0 * somme / (n * Math.sqrt(2.0 * PI * x));
89 return v;
90 }
91
95 public WatsonUDist(int n) {
96 setN(n);
97 }
98
99 public double density(double x) {
100 return density(n, x);
101 }
102
103 public double cdf(double x) {
104 return cdf(n, x);
105 }
106
107 public double barF(double x) {
108 return barF(n, x);
109 }
110
111 public double inverseF(double u) {
112 return inverseF(n, u);
113 }
114
115 public double getMean() {
116 return WatsonUDist.getMean(n);
117 }
118
119 public double getVariance() {
120 return WatsonUDist.getVariance(n);
121 }
122
123 public double getStandardDeviation() {
124 return WatsonUDist.getStandardDeviation(n);
125 }
126
130 public static double density(int n, double x) {
131 if (n < 2)
132 throw new IllegalArgumentException("n < 2");
133
134 if (x <= 1.0 / (12.0 * n) || x >= n / 12.0 || x >= XBIG)
135 return 0.0;
136
137 final double EPS = 1.0 / 100.0;
138 return (cdf(n, x + EPS) - cdf(n, x - EPS)) / (2.0 * EPS);
139
140 /*
141 * // This is the asymptotic density for n -> infinity int j; double signe;
142 * double v; double terme; double somme;
143 *
144 * if (x > XSEPARE) { // this series converges rapidly for x > 0.15 v = Math.exp
145 * (-(x*2.0*PI*PI)); signe = 1.0; somme = 0.0; j = 1; do { terme = j*j*Math.pow
146 * (v, (double)j*j); somme += signe*terme; signe = -signe; ++j; } while (!(terme
147 * < Num.DBL_EPSILON || j > JMAX)); if (j > JMAX) System.err.println
148 * ("watsonU: sum1 has not converged"); return 4.0*PI*PI*somme; }
149 *
150 * // this series converges rapidly for x <= 0.15 v = Math.exp (-0.125/x); somme
151 * = v; double somme2 = v; j = 2; do { terme = Math.pow (v, (double)(2*j -
152 * 1)*(2*j - 1)); somme += terme; somme2 += terme * (2*j - 1)*(2*j - 1); ++j; }
153 * while (!(terme <= somme2 * Num.DBL_EPSILON || j > JMAX)); if (j > JMAX)
154 * System.err.println ("watsonU: sum2 has not converged");
155 *
156 * final double RACINE = Math.sqrt (2.0*PI*x); return -somme/(x*RACINE) +
157 * 2*somme2 * 0.125/ ((x*x) * RACINE);
158 */
159 }
160
168 public static double cdf(int n, double x) {
169 if (n < 2)
170 throw new IllegalArgumentException("n < 2");
171
172 if (x <= 1.0 / (12.0 * n))
173 return 0.0;
174 if (x > 3.95 || x >= n / 12.0)
175 return 1.0;
176
177 if (2 == n) {
178 if (x <= 1.0 / 24.0)
179 return 0.0;
180 if (x >= 1.0 / 6.0)
181 return 1.0;
182 return 2.0 * Math.sqrt(2.0 * x - 1.0 / 12.0);
183 }
184
185 if (x > XSEPARE)
186 return 1.0 - barF(n, x);
187
188 // this series converges rapidly for x <= 0.15
189 double terme;
190 double v = Math.exp(-0.125 / x);
191 double somme = v;
192 int j = 2;
193
194 do {
195 terme = Math.pow(v, (double) (2 * j - 1) * (2 * j - 1));
196 somme += terme;
197 ++j;
198 } while (!(terme <= somme * Num.DBL_EPSILON || j > JMAX));
199 if (j > JMAX)
200 System.err.println(x + ": watsonU: sum2 has not converged");
201
202 v = 2.0 * somme / Math.sqrt(2.0 * PI * x);
203 v += cdfn(n, x);
204 if (v >= 1.0)
205 return 1.0;
206 if (v <= 0.0)
207 return 0.0;
208 return v;
209 }
210
215 public static double barF(int n, double x) {
216 if (n < 2)
217 throw new IllegalArgumentException("n < 2");
218
219 if (x <= 1.0 / (12.0 * n))
220 return 1.0;
221 if (x >= XBIG || x >= n / 12.0)
222 return 0.0;
223
224 if (2 == n)
225 return 1.0 - 2.0 * Math.sqrt(2.0 * x - 1.0 / 12.0);
226
227 if (x > XSEPARE) {
228 // this series converges rapidly for x > 0.15
229 double terme, ter;
230 double v = Math.exp(-2.0 * PI * PI * x);
231 double signe = 1.0;
232 double somme = 0.0;
233 double son = 0.0;
234 int j = 1;
235
236 do {
237 terme = Math.pow(v, (double) j * j);
238 somme += signe * terme;
239 double h = 2 * j * PI * x;
240 ter = (5.0 * x - h * h - 1.0 / 12.0) * j * j;
241 son += signe * terme * ter;
242 signe = -signe;
243 ++j;
244 } while (!(terme < Num.DBL_EPSILON || j > JMAX));
245 if (j > JMAX)
246 System.err.println(x + ": watsonU: sum1 has not converged");
247 v = 2.0 * somme + PI * PI * son / (3.0 * n);
248 if (v <= 0.0)
249 return 0.0;
250 if (v >= 1.0)
251 return 1.0;
252 return v;
253 }
254
255 return (1.0 - cdf(n, x));
256 }
257
263 public static double inverseF(int n, double u) {
264 if (n < 2)
265 throw new IllegalArgumentException("n < 2");
266 if (u < 0.0 || u > 1.0)
267 throw new IllegalArgumentException("u must be in [0,1]");
268 if (u >= 1.0)
269 return n / 12.0;
270 if (u <= 0.0)
271 return 1.0 / (12.0 * n);
272
273 if (2 == n)
274 return 1.0 / 24.0 + u * u / 8.0;
275
276 Function f = new Function(n, u);
277 return RootFinder.brentDekker(0.0, 2.0, f, 1e-7);
278 }
279
285 public static double getMean(int n) {
286 return 1.0 / 12.0;
287 }
288
295 public static double getVariance(int n) {
296 return (n - 1) / (360.0 * n);
297 }
298
305 public static double getStandardDeviation(int n) {
306 return Math.sqrt(WatsonUDist.getVariance(n));
307 }
308
312 public int getN() {
313 return n;
314 }
315
319 public void setN(int n) {
320 if (n < 2)
321 throw new IllegalArgumentException("n < 2");
322 this.n = n;
323 supportA = 1.0 / (12.0 * n);
324 supportB = n / 12.0;
325 }
326
330 public double[] getParams() {
331 double[] retour = { n };
332 return retour;
333 }
334
338 public String toString() {
339 return getClass().getSimpleName() + " : n = " + n;
340 }
341
342}
Classes implementing continuous distributions should inherit from this base class.
double getStandardDeviation()
Returns the standard deviation.
double barF(double x)
Returns the complementary distribution function.
double getVariance()
Returns the variance.
int getN()
Returns the parameter of this object.
double density(double x)
Returns , the density evaluated at .
static double getMean(int n)
Returns the mean of the Watson distribution with parameter.
WatsonUDist(int n)
Constructs a Watson U distribution for a sample of size .
static double getVariance(int n)
Returns the variance of the Watson distribution with parameter .
static double barF(int n, double x)
Computes the complementary distribution function , where is the Watson distribution with parameter ...
static double inverseF(int n, double u)
Computes , where is the Watson.
String toString()
Returns a String containing information about the current distribution.
double[] getParams()
Return an array containing the parameter of this object.
double getMean()
Returns the mean.
double inverseF(double u)
Returns the inverse distribution function .
static double density(int n, double x)
Computes the density of the Watson U distribution with parameter .
static double cdf(int n, double x)
Computes the Watson distribution function, i.e.
double cdf(double x)
Returns the distribution function .
static double getStandardDeviation(int n)
Returns the standard deviation of the Watson distribution with parameter .
void setN(int n)
Sets the parameter of this object.
This class provides various constants and methods to compute numerical quantities such as factorials,...
Definition Num.java:35
static final double DBL_EPSILON
Difference between 1.0 and the smallest double greater than 1.0.
Definition Num.java:90
This class provides numerical methods to solve non-linear equations.
static double brentDekker(double a, double b, MathFunction f, double tol)
Computes a root of the function in f using the Brent-Dekker method.
This interface should be implemented by classes which represent univariate mathematical functions.