SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
AndersonDarlingDist.java
1/*
2 * Class: AndersonDarlingDist
3 * Description: Anderson-Darling 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
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
49 protected int n;
50
51 private static class Function implements MathFunction {
52 protected int n;
53 protected double u;
54
55 public Function(int n, double u) {
56 this.n = n;
57 this.u = u;
58 }
59
60 public double evaluate(double x) {
61 return u - cdf(n, x);
62 }
63 }
64
68 public AndersonDarlingDist(int n) {
69 setN(n);
70 }
71
72 public double density(double x) {
73 return density(n, x);
74 }
75
76 public double cdf(double x) {
77 return cdf(n, x);
78 }
79
80 public double barF(double x) {
81 return barF(n, x);
82 }
83
84 public double inverseF(double u) {
85 return inverseF(n, u);
86 }
87
88 private static double dclem(int n, double x, double EPS) {
89 return (cdf(n, x + EPS) - cdf(n, x - EPS)) / (2.0 * EPS);
90 }
91
92 protected static double density_N_1(double x) {
93 final double AD_X0 = 0.38629436111989062;
94 final double AD_X1 = 37.816242111357;
95 if (x <= AD_X0 || x >= AD_X1)
96 return 0.0;
97
98 final double t = Math.exp(-x - 1.0);
99 return 2.0 * t / Math.sqrt(1.0 - 4.0 * t);
100 }
101
106 public static double density(int n, double x) {
107 if (n <= 0)
108 throw new IllegalArgumentException("n <= 0");
109 if (n == 1)
110 return density_N_1(x);
111
112 if (x >= XBIG || x <= 0.0)
113 return 0.0;
114 final double EPS = 1.0 / 64.0;
115 final double D1 = dclem(n, x, EPS);
116 final double D2 = dclem(n, x, 2.0 * EPS);
117 double res = D1 + (D1 - D2) / 3.0;
118 return res >= 0. ? res : 0.;
119 }
120
121 protected static double cdf_N_1(double x) {
122 // The Anderson-Darling distribution for N = 1
123 final double AD_X0 = 0.38629436111989062;
124 final double AD_X1 = 37.816242111357;
125
126 if (x <= AD_X0)
127 return 0.0;
128 if (x >= AD_X1)
129 return 1.0;
130 return Math.sqrt(1.0 - 4.0 * Math.exp(-x - 1.0));
131 }
132
133 private static double ADf(double z, int j) { // called by ADinf(); see article.
134 final double T = (4.0 * j + 1.0) * (4.0 * j + 1.0) * 1.23370055013617 / z;
135 if (T > 150.)
136 return 0.;
137
138 double f, fnew, a, b, c, r;
139 int i;
140 a = 2.22144146907918 * Math.exp(-T) / Math.sqrt(T);
141 // initialization requires cPhi
142 // if you have erfc(), replace 2*cPhi(sqrt(2*t)) with erfc(sqrt(t))
143 b = 3.93740248643060 * 2. * NormalDistQuick.barF01(Math.sqrt(2 * T));
144 r = z * .125;
145 f = a + b * r;
146 for (i = 1; i < 200; i++) {
147 c = ((i - .5 - T) * b + T * a) / i;
148 a = b;
149 b = c;
150 r *= z / (8 * i + 8);
151 if (Math.abs(r) < 1e-40 || Math.abs(c) < 1.e-40)
152 return f;
153 fnew = f + c * r;
154 if (f == fnew)
155 return f;
156 f = fnew;
157 }
158 return f;
159 }
160
161 private static double ADinf(double z) {
162 if (z < .01)
163 return 0.; // avoids exponent limits; ADinf(.01)=.528e-52
164 int j;
165 double ad, adnew, r;
166 r = 1. / z;
167 ad = r * ADf(z, 0);
168 for (j = 1; j < 100; j++) {
169 r *= (.5 - j) / j;
170 adnew = ad + (4 * j + 1) * r * ADf(z, j);
171 if (ad == adnew) {
172 return ad;
173 }
174 ad = adnew;
175 }
176 return ad;
177 }
178
179 private static double adinf(double z) {
180 if (z < 2.)
181 return Math.exp(-1.2337141 / z) / Math.sqrt(z)
182 * (2.00012 + (.247105 - (.0649821 - (.0347962 - (.011672 - .00168691 * z) * z) * z) * z) * z);
183 // max |error| < .000002 for z<2, (p=.90816...)
184 return Math.exp(-Math.exp(1.0776 - (2.30695 - (.43424 - (.082433 - (.008056 - .0003146 * z) * z) * z) * z) * z));
185 // max |error|<.0000008 for 4<z<infinity
186 }
187
188 private static double AD(int n, double z, boolean isFastADinf) {
189 double v, x;
190 /*
191 * If isFastADinf is true, use the fast approximation adinf (z), if it is false,
192 * use the more exact ADinf (z)
193 */
194 if (isFastADinf)
195 x = adinf(z);
196 else
197 x = ADinf(z);
198
199 // now x=adinf(z). Next, get v=errfix(n,x) and return x+v;
200 if (x > .8) {
201 v = (-130.2137 + (745.2337 - (1705.091 - (1950.646 - (1116.360 - 255.7844 * x) * x) * x) * x) * x) / n;
202 return x + v;
203 }
204 final double C = .01265 + .1757 / n;
205 if (x < C) {
206 v = x / C;
207 v = Math.sqrt(v) * (1. - v) * (49 * v - 102);
208 return x + v * (.0037 / (n * n) + .00078 / n + .00006) / n;
209 }
210 v = (x - C) / (.8 - C);
211 v = -.00022633 + (6.54034 - (14.6538 - (14.458 - (8.259 - 1.91864 * v) * v) * v) * v) * v;
212 return x + v * (.04213 + .01365 / n) / n;
213 }
214
223 public static double cdf(int n, double x) {
224 if (n <= 0)
225 throw new IllegalArgumentException("n <= 0");
226 if (x <= 0)
227 return 0.0;
228 if (x >= XBIG)
229 return 1.0;
230 if (1 == n)
231 return cdf_N_1(x);
232 final double RES = AD(n, x, true);
233 if (RES <= 0.0)
234 return 0.0;
235 return RES;
236 }
237
238 protected static double barF_N_1(double x) {
239 if (x <= 3.8629436111989E-1)
240 return 1.0;
241 if (x >= XBIGM)
242 return 0.0;
243
244 double q;
245 if (x < 6.0) {
246 q = 1.0 - 4.0 * Math.exp(-x - 1.0);
247 return 1.0 - Math.sqrt(q);
248 }
249 q = 4.0 * Math.exp(-x - 1.0);
250 return 0.5 * q * (1.0 + 0.25 * q * (1.0 + 0.5 * q * (1.0 + 0.125 * q * (5.0 + 3.5 * q))));
251 }
252
257 public static double barF(int n, double x) {
258 if (n <= 0)
259 throw new IllegalArgumentException("n <= 0");
260 if (n == 1)
261 return barF_N_1(x);
262 return 1.0 - cdf(n, x);
263 }
264
265 protected static double inverse_N_1(double u) {
266 final double AD_X0 = 0.38629436111989062;
267 if (u <= 0.0)
268 return AD_X0;
269 final double AD_X1 = 37.816242111357;
270 if (u >= 1.0)
271 return AD_X1;
272 return AD_X0 - Math.log1p(-u * u);
273 }
274
279 public static double inverseF(int n, double u) {
280 if (n <= 0)
281 throw new IllegalArgumentException("n <= 0");
282 if (u < 0.0 || u > 1.0)
283 throw new IllegalArgumentException("u must be in [0,1]");
284 if (n == 1)
285 return inverse_N_1(u);
286 if (u == 1.0)
287 return Double.POSITIVE_INFINITY;
288 if (u == 0.0)
289 return 0.0;
290 Function f = new Function(n, u);
291 return RootFinder.brentDekker(0.0, 50.0, f, 1e-10);
292 }
293
297 public int getN() {
298 return n;
299 }
300
304 public void setN(int n) {
305 if (n <= 0)
306 throw new IllegalArgumentException("n < 1");
307 this.n = n;
308 if (1 == n) {
309 supportA = 0.38629436111989062;
310 supportB = 37.816242111357;
311 } else {
312 supportA = 0.0;
313 supportB = 1000.0;
314 }
315 }
316
320 public double[] getParams() {
321 double[] retour = { n };
322 return retour;
323 }
324
328 public String toString() {
329 return getClass().getSimpleName() + " : n = " + n;
330 }
331
332}
static double cdf(int n, double x)
Computes the Anderson–Darling distribution function , with parameter , using Marsaglia’s and al.
double[] getParams()
Return an array containing the parameter of the current distribution.
static double density(int n, double x)
Computes the density of the Anderson–Darling distribution with parameter .
double barF(double x)
Returns the complementary distribution function.
double cdf(double x)
Returns the distribution function .
int getN()
Returns the parameter of this object.
double density(double x)
Returns , the density evaluated at .
AndersonDarlingDist(int n)
Constructs an Anderson–Darling distribution for a sample of size .
String toString()
Returns a String containing information about the current distribution.
void setN(int n)
Sets the parameter of this object.
static double barF(int n, double x)
Computes the complementary distribution function with parameter .
static double inverseF(int n, double u)
Computes the inverse of the Anderson–Darling distribution with parameter .
double inverseF(double u)
Returns the inverse distribution function .
Classes implementing continuous distributions should inherit from this base class.
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.