SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
JohnsonSBDist.java
1/*
2 * Class: JohnsonSBDist
3 * Description: Johnson S_B 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.Num;
28
57public class JohnsonSBDist extends JohnsonSystem {
58 // m_psi is used in computing the mean and the variance
59 private double m_psi = -1.0e100;
60
61 private static double getMeanPsi(double gamma, double delta, double xi, double lambda, double[] tpsi) {
62 // Returns the theoretical mean of t = (x - xi)/lambda;
63 // also compute psi and returns it in tpsi[0], since
64 // it is used in computing the mean and the variance
65
66 final int NMAX = 10000;
67 final double EPS = 1.0e-15;
68
69 double a1 = 1.0 / (2 * delta * delta);
70 double a2 = (1.0 - 2 * delta * gamma) / (2 * delta * delta);
71 double a3 = (gamma - 1. / delta) / delta;
72 int n = 0;
73 double tem = 1;
74 double sum = 0;
75 double v;
76 while (Math.abs(tem) > EPS * Math.abs(sum) && n < NMAX) {
77 ++n;
78 v = Math.exp(-n * gamma / delta) + Math.exp(n * a3);
79 tem = Math.exp(-n * n * a1) * v / (1 + Math.exp(-2 * n * a1));
80 // tem = Math.exp(-n*n*a1) * Math.cosh(n*a2) / Math.cosh(n*a1);
81 sum += tem;
82 }
83 if (n >= NMAX)
84 System.err.println("JohnsonSBDist: possible lack of accuracy on mean");
85 double A = (0.5 + sum) / (delta);
86
87 a1 = Math.PI * Math.PI * delta * delta;
88 a2 = Math.PI * delta * gamma;
89 int j;
90 n = 0;
91 tem = 1;
92 sum = 0;
93 while (Math.abs(tem) > EPS * Math.abs(sum) && n < NMAX) {
94 ++n;
95 j = 2 * n - 1;
96 tem = Math.exp(-j * j * a1 / 2.0) * Math.sin(j * a2) / Math.sinh(j * a1);
97 sum += tem;
98 }
99 if (n >= NMAX)
100 System.err.println("JohnsonSBDist: possible lack of accuracy on mean");
101 double B = 2.0 * Math.PI * delta * sum;
102
103 a1 = 2 * Math.PI * Math.PI * delta * delta;
104 a2 = 2 * Math.PI * delta * gamma;
105 n = 0;
106 tem = 1;
107 sum = 0;
108 while (Math.abs(tem) > EPS * Math.abs(sum) && n < NMAX) {
109 ++n;
110 tem = Math.exp(-n * n * a1) * Math.cos(n * a2);
111 sum += tem;
112 }
113 if (n >= NMAX)
114 System.err.println("JohnsonSBDist: possible lack of accuracy on mean");
115 double C = 1 + 2.0 * sum;
116
117 double D = Math.sqrt(2 * Math.PI) * Math.exp(gamma * gamma / 2.0);
118 double tmean = (A - B) / (C * D);
119 tpsi[0] = C * D;
120 return tmean;
121 }
122
129 public JohnsonSBDist(double gamma, double delta, double xi, double lambda) {
130 super(gamma, delta, xi, lambda);
131 setLastParams(xi, lambda);
132 }
133
134 private void setLastParams(double xi, double lambda) {
135 supportA = xi;
136 supportB = xi + lambda;
137 }
138
139 public double density(double x) {
140 return density(gamma, delta, xi, lambda, x);
141 }
142
143 public double cdf(double x) {
144 return cdf(gamma, delta, xi, lambda, x);
145 }
146
147 public double barF(double x) {
148 return barF(gamma, delta, xi, lambda, x);
149 }
150
151 public double inverseF(double u) {
152 return inverseF(gamma, delta, xi, lambda, u);
153 }
154
155 public double getMean() {
156 return JohnsonSBDist.getMean(gamma, delta, xi, lambda);
157 }
158
159 public double getVariance() {
160 return JohnsonSBDist.getVariance(gamma, delta, xi, lambda);
161 }
162
163 public double getStandardDeviation() {
164 return JohnsonSBDist.getStandardDeviation(gamma, delta, xi, lambda);
165 }
166
171 public static double density(double gamma, double delta, double xi, double lambda, double x) {
172 if (lambda <= 0)
173 throw new IllegalArgumentException("lambda <= 0");
174 if (delta <= 0)
175 throw new IllegalArgumentException("delta <= 0");
176 if (x <= xi || x >= (xi + lambda))
177 return 0.0;
178 double y = (x - xi) / lambda;
179 double z = gamma + delta * Math.log(y / (1.0 - y));
180 return delta / (lambda * y * (1.0 - y) * Math.sqrt(2.0 * Math.PI)) * Math.exp(-z * z / 2.0);
181 }
182
187 public static double cdf(double gamma, double delta, double xi, double lambda, double x) {
188 if (lambda <= 0)
189 throw new IllegalArgumentException("lambda <= 0");
190 if (delta <= 0)
191 throw new IllegalArgumentException("delta <= 0");
192 if (x <= xi)
193 return 0.0;
194 if (x >= xi + lambda)
195 return 1.0;
196 double y = (x - xi) / lambda;
197 double z = gamma + delta * Math.log(y / (1.0 - y));
198 return NormalDist.cdf01(z);
199 }
200
204 public static double barF(double gamma, double delta, double xi, double lambda, double x) {
205 if (lambda <= 0)
206 throw new IllegalArgumentException("lambda <= 0");
207 if (delta <= 0)
208 throw new IllegalArgumentException("delta <= 0");
209 if (x <= xi)
210 return 1.0;
211 if (x >= xi + lambda)
212 return 0.0;
213 double y = (x - xi) / lambda;
214 double z = gamma + delta * Math.log(y / (1.0 - y));
215 return NormalDist.barF01(z);
216 }
217
222 public static double inverseF(double gamma, double delta, double xi, double lambda, double u) {
223 if (lambda <= 0)
224 throw new IllegalArgumentException("lambda <= 0");
225 if (delta <= 0)
226 throw new IllegalArgumentException("delta <= 0");
227 if (u > 1.0 || u < 0.0)
228 throw new IllegalArgumentException("u not in [0,1]");
229
230 if (u >= 1.0) // if u == 1, in fact
231 return xi + lambda;
232 if (u <= 0.0) // if u == 0, in fact
233 return xi;
234
235 double z = NormalDist.inverseF01(u);
236 double v = (z - gamma) / delta;
237
238 if (v >= Num.DBL_MAX_EXP * Num.LN2)
239 return xi + lambda;
240 if (v <= Num.DBL_MIN_EXP * Num.LN2)
241 return xi;
242
243 v = Math.exp(v);
244 return (xi + (xi + lambda) * v) / (1.0 + v);
245 }
246
269 public static double[] getMLE(double[] x, int n, double xi, double lambda) {
270 if (n <= 0)
271 throw new IllegalArgumentException("n <= 0");
272 final double LN_EPS = Num.LN_DBL_MIN - Num.LN2;
273 double[] ftab = new double[n];
274 double sum = 0.0;
275 double t;
276
277 for (int i = 0; i < n; i++) {
278 t = (x[i] - xi) / lambda;
279 if (t <= 0.)
280 ftab[i] = LN_EPS;
281 else if (t >= 1 - Num.DBL_EPSILON)
282 ftab[i] = Math.log(1. / Num.DBL_EPSILON);
283 else
284 ftab[i] = Math.log(t / (1. - t));
285 sum += ftab[i];
286 }
287 double empiricalMean = sum / n;
288
289 sum = 0.0;
290 for (int i = 0; i < n; i++) {
291 t = ftab[i] - empiricalMean;
292 sum += t * t;
293 }
294 double sigmaf = Math.sqrt(sum / n);
295
296 double[] param = new double[2];
297 param[0] = -empiricalMean / sigmaf;
298 param[1] = 1.0 / sigmaf;
299
300 return param;
301 }
302
315 public static JohnsonSBDist getInstanceFromMLE(double[] x, int n, double xi, double lambda) {
316 double parameters[] = getMLE(x, n, xi, lambda);
317 return new JohnsonSBDist(parameters[0], parameters[1], xi, lambda);
318 }
319
326 public static double getMean(double gamma, double delta, double xi, double lambda) {
327 if (lambda <= 0)
328 throw new IllegalArgumentException("lambda <= 0");
329 if (delta <= 0)
330 throw new IllegalArgumentException("delta <= 0");
331 double[] tpsi = new double[1];
332 double mu = getMeanPsi(gamma, delta, xi, lambda, tpsi);
333 return xi + lambda * mu;
334 }
335
343 public static double getVariance(double gamma, double delta, double xi, double lambda) {
344 if (lambda <= 0.0)
345 throw new IllegalArgumentException("lambda <= 0");
346 if (delta <= 0.0)
347 throw new IllegalArgumentException("delta <= 0");
348
349 final int NMAX = 10000;
350 final double EPS = 1.0e-15;
351
352 double a1 = 1.0 / (2.0 * delta * delta);
353 double a2 = (1.0 - 2.0 * delta * gamma) / (2.0 * delta * delta);
354 double a3 = (gamma - 1. / delta) / delta;
355 double v;
356 int n = 0;
357 double tem = 1;
358 double sum = 0;
359 while (Math.abs(tem) > EPS * Math.abs(sum) && n < NMAX) {
360 ++n;
361 v = Math.exp(-n * gamma / delta) - Math.exp(n * a3);
362 tem = n * Math.exp(-n * n * a1) * v / (1 + Math.exp(-2 * n * a1));
363 // tem = n*Math.exp(-n*n*a1) * Math.sinh(n*a2) / Math.cosh(n*a1);
364 sum += tem;
365 }
366 if (n >= NMAX)
367 System.err.println("JohnsonSBDist: possible lack of accuracy on variance");
368 double A = -sum / (delta * delta);
369
370 a1 = Math.PI * Math.PI * delta * delta;
371 a2 = Math.PI * delta * gamma;
372 int j;
373 n = 0;
374 tem = 1;
375 sum = 0;
376 while (Math.abs(tem) > EPS * Math.abs(sum) && n < NMAX) {
377 ++n;
378 j = 2 * n - 1;
379 tem = j * Math.exp(-j * j * a1 / 2.0) * Math.cos(j * a2) / Math.sinh(j * a1);
380 sum += tem;
381 }
382 if (n >= NMAX)
383 System.err.println("JohnsonSBDist: possible lack of accuracy on variance");
384 double B = 2.0 * a1 * sum;
385
386 a1 = 2 * Math.PI * Math.PI * delta * delta;
387 a2 = 2 * Math.PI * delta * gamma;
388 n = 0;
389 tem = 1;
390 sum = 0;
391 while (Math.abs(tem) > EPS * Math.abs(sum) && n < NMAX) {
392 ++n;
393 tem = n * Math.exp(-n * n * a1) * Math.sin(n * a2);
394 sum += tem;
395 }
396 if (n >= NMAX)
397 System.err.println("JohnsonSBDist: possible lack of accuracy on variance");
398 double C = -4.0 * Math.PI * delta * sum;
399
400 double D = Math.sqrt(2 * Math.PI) * Math.exp(0.5 * gamma * gamma);
401 double[] tpsi = new double[1];
402 double mu = getMeanPsi(gamma, delta, xi, lambda, tpsi);
403
404 double tvar = mu * (1 - delta * gamma) - mu * mu + delta / tpsi[0] * (A - B - mu * C * D);
405 return lambda * lambda * tvar;
406
407 }
408
416 public static double getStandardDeviation(double gamma, double delta, double xi, double lambda) {
417 return Math.sqrt(JohnsonSBDist.getVariance(gamma, delta, xi, lambda));
418 }
419
425 public void setParams(double gamma, double delta, double xi, double lambda) {
426 setParams0(gamma, delta, xi, lambda);
427 setLastParams(xi, lambda);
428 }
429
430}
static JohnsonSBDist getInstanceFromMLE(double[] x, int n, double xi, double lambda)
Creates a new instance of a JohnsonSBDist object using the maximum likelihood method based on the ob...
void setParams(double gamma, double delta, double xi, double lambda)
Sets the value of the parameters , ,.
double getStandardDeviation()
Returns the standard deviation.
double barF(double x)
Returns the complementary distribution function.
static double[] getMLE(double[] x, int n, double xi, double lambda)
Estimates the parameters of the Johnson.
double inverseF(double u)
Returns the inverse distribution function .
static double inverseF(double gamma, double delta, double xi, double lambda, double u)
Returns the inverse of the distribution ( JohnsonSB-inverse ).
static double getVariance(double gamma, double delta, double xi, double lambda)
Returns the variance tfly06a  of the Johnson distribution with parameters , ,.
static double barF(double gamma, double delta, double xi, double lambda, double x)
Returns the complementary distribution.
double getMean()
Returns the mean.
static double density(double gamma, double delta, double xi, double lambda, double x)
Returns the density function ( JohnsonSB-density ).
JohnsonSBDist(double gamma, double delta, double xi, double lambda)
Constructs a JohnsonSBDist object with shape parameters.
double cdf(double x)
Returns the distribution function .
static double getStandardDeviation(double gamma, double delta, double xi, double lambda)
Returns the standard deviation of the Johnson distribution with parameters , , ,.
static double cdf(double gamma, double delta, double xi, double lambda, double x)
Returns the distribution function ( JohnsonSB-dist ).
double getVariance()
Returns the variance.
double density(double x)
Returns , the density evaluated at .
static double getMean(double gamma, double delta, double xi, double lambda)
Returns the mean tjoh49a  of the Johnson distribution with parameters , ,.
void setParams0(double gamma, double delta, double xi, double lambda)
Sets the value of the parameters , ,.
JohnsonSystem(double gamma, double delta, double xi, double lambda)
Constructs a JohnsonSystem object with shape parameters.
Extends the class ContinuousDistribution for the normal distribution (e.g., tjoh95a  (page 80)).
static double inverseF01(double u)
Same as inverseF(0, 1, u).
static double cdf01(double x)
Same as cdf(0, 1, x).
static double barF01(double x)
Same as barF(0, 1, x).
This class provides various constants and methods to compute numerical quantities such as factorials,...
Definition Num.java:35
static final double LN_DBL_MIN
Natural logarithm of DBL_MIN.
Definition Num.java:118
static final double DBL_EPSILON
Difference between 1.0 and the smallest double greater than 1.0.
Definition Num.java:90
static final int DBL_MIN_EXP
Smallest int such that is representable (approximately) as a normalised double.
Definition Num.java:102
static final int DBL_MAX_EXP
Largest int such that is representable (approximately) as a double.
Definition Num.java:96
static final double LN2
The values of .
Definition Num.java:148