SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
JohnsonSLDist.java
1/*
2 * Class: JohnsonSLDist
3 * Description: Johnson S_L 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 July 2012
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;
29import optimization.*;
30
55public class JohnsonSLDist extends JohnsonSystem {
56
57 private static class Function implements MathFunction {
58 // To find value of t > 0 in (Johnson 1949, eq. 16)
59 protected double a;
60
61 public Function(double sb1) {
62 a = sb1;
63 }
64
65 public double evaluate(double t) {
66 return (t * t * t - 3 * t - a);
67 }
68 }
69
70 private static double[] initPar(double[] x, int n, double xmin) {
71 // Use moments to estimate initial values of params as input to MLE
72 // (Johnson 1949, Biometrika 36, p. 149)
73 int j;
74 double sum = 0.0;
75 for (j = 0; j < n; j++) {
76 sum += x[j];
77 }
78 double mean = sum / n;
79
80 double v;
81 double sum3 = 0.0;
82 sum = 0;
83 for (j = 0; j < n; j++) {
84 v = x[j] - mean;
85 sum += v * v;
86 sum3 += v * v * v;
87 }
88 double m2 = sum / n;
89 double m3 = sum3 / n;
90
91 v = m3 / Math.pow(m2, 1.5);
92 Function f = new Function(v);
93 double t0 = 0;
94 double tlim = Math.cbrt(v);
95 if (tlim <= 0) {
96 t0 = tlim;
97 tlim = 10;
98 }
99 double t = RootFinder.brentDekker(t0, tlim, f, 1e-5);
100 if (t <= 0)
101 throw new UnsupportedOperationException("t <= 0; no MLE");
102 double xi = mean - Math.sqrt(m2 / t);
103 if (xi >= xmin)
104 // throw new UnsupportedOperationException("xi >= xmin; no MLE");
105 xi = xmin - 1.0e-1;
106 v = 1 + m2 / ((mean - xi) * (mean - xi));
107 double delta = 1.0 / Math.sqrt((Math.log(v)));
108 v = Math.sqrt(v);
109 double lambda = (mean - xi) / v;
110 double[] param = new double[3];
111 param[0] = delta;
112 param[1] = xi;
113 param[2] = lambda;
114 return param;
115 }
116
117 private static class Optim implements Uncmin_methods {
118 // minimizes the loglikelihood function
119 private int n;
120 private double[] X;
121 private double xmin; // min{X_j}
122 private static final double BARRIER = 1.0e100;
123
124 public Optim(double[] X, int n, double xmin) {
125 this.n = n;
126 this.X = X;
127 this.xmin = xmin;
128 }
129
130 public double f_to_minimize(double[] par) {
131 // par = [0, delta, xi, lambda]
132 // arrays in Uncmin starts at index 1; par[0] is unused
133 double delta = par[1];
134 double xi = par[2];
135 double lambda = par[3];
136 if (delta <= 0.0 || lambda <= 0.0) // barrier at 0
137 return BARRIER;
138 if (xi >= xmin)
139 return BARRIER;
140
141 double loglam = Math.log(lambda);
142 double v, z;
143 double sumv = 0.0;
144 double sumz = 0.0;
145 for (int j = 0; j < n; j++) {
146 v = Math.log(X[j] - xi);
147 z = delta * (v - loglam);
148 sumv += v;
149 sumz += z * z;
150 }
151
152 return sumv + sumz / 2.0 - n * Math.log(delta);
153 }
154
155 public void gradient(double[] x, double[] g) {
156 }
157
158 public void hessian(double[] x, double[][] h) {
159 }
160 }
161
166 public JohnsonSLDist(double gamma, double delta) {
167 this(gamma, delta, 0, 1);
168 }
169
176 public JohnsonSLDist(double gamma, double delta, double xi, double lambda) {
177 super(gamma, delta, xi, lambda);
178 setLastParams(xi);
179 }
180
181 private void setLastParams(double xi) {
182 supportA = xi;
183 }
184
185 public double density(double x) {
186 return density(gamma, delta, xi, lambda, x);
187 }
188
189 public double cdf(double x) {
190 return cdf(gamma, delta, xi, lambda, x);
191 }
192
193 public double barF(double x) {
194 return barF(gamma, delta, xi, lambda, x);
195 }
196
197 public double inverseF(double u) {
198 return inverseF(gamma, delta, xi, lambda, u);
199 }
200
201 public double getMean() {
202 return JohnsonSLDist.getMean(gamma, delta, xi, lambda);
203 }
204
205 public double getVariance() {
206 return JohnsonSLDist.getVariance(gamma, delta, xi, lambda);
207 }
208
209 public double getStandardDeviation() {
210 return JohnsonSLDist.getStandardDeviation(gamma, delta, xi, lambda);
211 }
212
216 public static double density(double gamma, double delta, double xi, double lambda, double x) {
217 if (lambda <= 0)
218 throw new IllegalArgumentException("lambda <= 0");
219 if (delta <= 0)
220 throw new IllegalArgumentException("delta <= 0");
221
222 if (x <= xi)
223 return 0;
224 double y = (x - xi) / lambda;
225 double z = gamma + delta * Math.log(y);
226 if (z >= 1.0e10)
227 return 0;
228 return delta * Math.exp(-z * z / 2.0) / (lambda * y * Math.sqrt(2.0 * Math.PI));
229 }
230
234 public static double cdf(double gamma, double delta, double xi, double lambda, double x) {
235 if (lambda <= 0)
236 throw new IllegalArgumentException("lambda <= 0");
237 if (delta <= 0)
238 throw new IllegalArgumentException("delta <= 0");
239
240 if (x <= xi)
241 return 0.0;
242 double y = (x - xi) / lambda;
243 double z = gamma + delta * Math.log(y);
244 return NormalDist.cdf01(z);
245 }
246
250 public static double barF(double gamma, double delta, double xi, double lambda, double x) {
251 if (lambda <= 0)
252 throw new IllegalArgumentException("lambda <= 0");
253 if (delta <= 0)
254 throw new IllegalArgumentException("delta <= 0");
255
256 if (x <= xi)
257 return 1.0;
258 double y = (x - xi) / lambda;
259 double z = gamma + delta * Math.log(y);
260 return NormalDist.barF01(z);
261 }
262
266 public static double inverseF(double gamma, double delta, double xi, double lambda, double u) {
267 if (lambda <= 0)
268 throw new IllegalArgumentException("lambda <= 0");
269 if (delta <= 0)
270 throw new IllegalArgumentException("delta <= 0");
271 if (u > 1.0 || u < 0.0)
272 throw new IllegalArgumentException("u not in [0,1]");
273
274 if (u >= 1.0)
275 return Double.POSITIVE_INFINITY;
276 if (u <= 0.0)
277 return xi;
278
279 double z = NormalDist.inverseF01(u);
280 double t = (z - gamma) / delta;
281 if (t >= Num.DBL_MAX_EXP * Num.LN2)
282 return Double.POSITIVE_INFINITY;
283 if (t <= Num.DBL_MIN_EXP * Num.LN2)
284 return xi;
285
286 return xi + lambda * Math.exp(t);
287 }
288
301 public static double[] getMLE(double[] x, int n) {
302 if (n <= 0)
303 throw new IllegalArgumentException("n <= 0");
304
305 int j;
306 double xmin = Double.MAX_VALUE;
307 for (j = 0; j < n; j++) {
308 if (x[j] < xmin)
309 xmin = x[j];
310 }
311 double[] paramIn = new double[3];
312 paramIn = initPar(x, n, xmin);
313 double[] paramOpt = new double[4];
314 for (int i = 0; i < 3; i++)
315 paramOpt[i + 1] = paramIn[i];
316
317 Optim system = new Optim(x, n, xmin);
318
319 double[] xpls = new double[4];
320 double[] fpls = new double[4];
321 double[] gpls = new double[4];
322 int[] itrcmd = new int[2];
323 double[][] a = new double[4][4];
324 double[] udiag = new double[4];
325
326 Uncmin_f77.optif0_f77(3, paramOpt, system, xpls, fpls, gpls, itrcmd, a, udiag);
327
328 double[] param = new double[4];
329 param[0] = 0;
330 for (int i = 1; i <= 3; i++)
331 param[i] = xpls[i];
332 return param;
333 }
334
344 public static JohnsonSLDist getInstanceFromMLE(double[] x, int n) {
345 double param[] = getMLE(x, n);
346 return new JohnsonSLDist(0, param[0], param[1], param[2]);
347 }
348
357 public static double getMean(double gamma, double delta, double xi, double lambda) {
358 if (lambda <= 0.0)
359 throw new IllegalArgumentException("lambda <= 0");
360 if (delta <= 0.0)
361 throw new IllegalArgumentException("delta <= 0");
362
363 double t = 1.0 / (2.0 * delta * delta) - gamma / delta;
364 return (xi + lambda * Math.exp(t));
365 }
366
377 public static double getVariance(double gamma, double delta, double xi, double lambda) {
378 if (lambda <= 0.0)
379 throw new IllegalArgumentException("lambda <= 0");
380 if (delta <= 0.0)
381 throw new IllegalArgumentException("delta <= 0");
382
383 double t = 1.0 / (delta * delta) - 2 * gamma / delta;
384 return lambda * lambda * Math.exp(t) * (Math.exp(1.0 / (delta * delta)) - 1);
385 }
386
394 public static double getStandardDeviation(double gamma, double delta, double xi, double lambda) {
395 return Math.sqrt(JohnsonSLDist.getVariance(gamma, delta, xi, lambda));
396 }
397
403 public void setParams(double gamma, double delta, double xi, double lambda) {
404 setParams0(gamma, delta, xi, lambda);
405 setLastParams(xi);
406 }
407
408}
double inverseF(double u)
Returns the inverse distribution function .
static double density(double gamma, double delta, double xi, double lambda, double x)
Returns the density function .
static JohnsonSLDist getInstanceFromMLE(double[] x, int n)
Creates a new instance of a Johnson distribution with parameters 0, , and over the interval estim...
double density(double x)
Returns , the density evaluated at .
static double getVariance(double gamma, double delta, double xi, double lambda)
Returns the variance.
JohnsonSLDist(double gamma, double delta, double xi, double lambda)
Constructs a JohnsonSLDist object with shape parameters.
static double getStandardDeviation(double gamma, double delta, double xi, double lambda)
Returns the standard deviation of the Johnson distribution with parameters , , ,.
double getMean()
Returns the mean.
static double barF(double gamma, double delta, double xi, double lambda, double x)
Returns the complementary distribution function .
void setParams(double gamma, double delta, double xi, double lambda)
Sets the value of the parameters , ,.
static double cdf(double gamma, double delta, double xi, double lambda, double x)
Returns the distribution function .
static double getMean(double gamma, double delta, double xi, double lambda)
Returns the mean.
double getVariance()
Returns the variance.
static double[] getMLE(double[] x, int n)
Estimates the parameters , , ,.
JohnsonSLDist(double gamma, double delta)
Same as JohnsonSLDist(gamma, delta, 0, 1).
static double inverseF(double gamma, double delta, double xi, double lambda, double u)
Returns the inverse distribution function .
double cdf(double x)
Returns the distribution function .
double getStandardDeviation()
Returns the standard deviation.
double barF(double x)
Returns the complementary distribution function.
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 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
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.