SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
BiNormalDist.java
1/*
2 * Class: BiNormalDist
3 * Description: bivariate normal 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.probdistmulti;
26
27import umontreal.ssj.probdist.NormalDist;
28
65 protected int ndigit; // Number of decimal digits of accuracy
66 protected double mu1, mu2;
67 protected double sigma1, sigma2;
68 protected double rho;
69 protected double racRho; // sqrt(1 - rho^2)
70 protected double detS; // 2*PI*sigma1*sigma2*sqrt(1 - rho^2)
71 protected static final double RHO_SMALL = 1.0e-8; // neglect small rhos
72
73 private static final double Z[] = { 0.04691008, 0.23076534, 0.5, 0.76923466, 0.95308992 };
74
75 private static final double W[] = { 0.018854042, 0.038088059, 0.0452707394, 0.038088059, 0.018854042 };
76
77 private static final double AGauss[] = { -0.72657601, 0.71070688, -0.142248368, 0.127414796 };
78
85 public BiNormalDist(double rho) {
86 setParams(0.0, 1.0, 0.0, 1.0, rho);
87 }
88
95 public BiNormalDist(double mu1, double sigma1, double mu2, double sigma2, double rho) {
96 setParams(mu1, sigma1, mu2, sigma2, rho);
97 }
98
99 public double density(double x, double y) {
100 if (Math.abs(rho) == 1.)
101 throw new IllegalArgumentException("|rho| = 1");
102 double X = (x - mu1) / sigma1;
103 double Y = (y - mu2) / sigma2;
104 double T = (X * X - 2.0 * rho * X * Y + Y * Y) / (2.0 * racRho * racRho);
105 return Math.exp(-T) / detS;
106 }
107
113 public static double density(double x, double y, double rho) {
114 return density(0.0, 1.0, x, 0.0, 1.0, y, rho);
115 }
116
125 public static double density(double mu1, double sigma1, double x, double mu2, double sigma2, double y, double rho) {
126 if (sigma1 <= 0.)
127 throw new IllegalArgumentException("sigma1 <= 0");
128 if (sigma2 <= 0.)
129 throw new IllegalArgumentException("sigma2 <= 0");
130 if (Math.abs(rho) >= 1.)
131 throw new IllegalArgumentException("|rho| >= 1");
132 double X = (x - mu1) / sigma1;
133 double Y = (y - mu2) / sigma2;
134 double fRho = (1.0 - rho) * (1.0 + rho);
135 double T = (X * X - 2.0 * rho * X * Y + Y * Y) / (2.0 * fRho);
136 return Math.exp(-T) / (2.0 * Math.PI * sigma1 * sigma2 * Math.sqrt(fRho));
137
138 }
139
140 protected static double Gauss(double z) {
141 // Computes normal probabilities to within accuracy of 10^(-7)
142 // Drezner Z., and G.O. Wesolowsky (1990) On the computation of the
143 // bivariate normal integral. J. Statist. Comput. Simul. 35:101-107.
144
145 final double x = 1.0 / (1.0 + 0.23164189 * Math.abs(z));
146 double G = 0.53070271;
147 for (int i = 0; i < 4; ++i)
148 G = G * x + AGauss[i];
149 G = G * x * Math.exp(-z * z / 2.0);
150 if (z > 0.0)
151 G = 1.0 - G;
152 return G;
153 }
154
155 protected static double specialCDF(double x, double y, double rho, double xbig) {
156 // Compute the bivariate normal CDF for limiting cases and returns
157 // its value. If non limiting case, returns -2 as flag.
158 // xbig is practical infinity
159
160 if (Math.abs(rho) > 1.0)
161 throw new IllegalArgumentException("|rho| > 1");
162 if (x == 0.0 && y == 0.0)
163 return 0.25 + Math.asin(rho) / (2.0 * Math.PI);
164
165 if (rho == 1.0) {
166 if (y < x)
167 x = y;
168 return NormalDist.cdf01(x);
169 }
170 if (rho == -1.0) {
171 if (y <= -x)
172 return 0.0;
173 else
174 return NormalDist.cdf01(x) - NormalDist.cdf01(-y);
175 }
176 if (Math.abs(rho) < RHO_SMALL)
177 // return NormalDist.cdf01(x) * NormalDist.cdf01(y);
178 return Gauss(x) * Gauss(y); // return this value to keep sequence monotone around rho=0.
179
180 if ((x <= -xbig) || (y <= -xbig))
181 return 0.0;
182 if (x >= xbig)
183 return NormalDist.cdf01(y);
184 if (y >= xbig)
185 return NormalDist.cdf01(x);
186
187 return -2.0;
188 }
189
198 public static double cdf(double x, double y, double rho) {
199 double bvn = specialCDF(x, y, rho, 20.0);
200 if (bvn >= 0.0)
201 return bvn;
202 bvn = 0.0;
203
204 /*
205 * prob(x <= h1, y <= h2), where x and y are standard binormal, with rho =
206 * corr(x,y), error < 2e-7. Drezner Z., and G.O. Wesolowsky (1990) On the
207 * computation of the bivariate normal integral. J. Statist. Comput. Simul.
208 * 35:101-107.
209 */
210
211 int i;
212 double r1, r2, r3, rr, aa, ab, h3, h5, h6, h7;
213 final double h1 = -x;
214 double h2 = -y;
215 final double h12 = (h1 * h1 + h2 * h2) / 2.;
216
217 if (Math.abs(rho) >= 0.7) {
218 r2 = (1. - rho) * (1. + rho);
219 r3 = Math.sqrt(r2);
220 if (rho < 0.)
221 h2 = -h2;
222 h3 = h1 * h2;
223 if (h3 < 300.)
224 h7 = Math.exp(-h3 / 2.);
225 else
226 h7 = 0.;
227 if (r2 != 0.) {
228 h6 = Math.abs(h1 - h2);
229 h5 = h6 * h6 / 2.;
230 h6 /= r3;
231 aa = .5 - h3 / 8.;
232 ab = 3. - 2. * aa * h5;
233 bvn = .13298076 * h6 * ab * (1.0 - Gauss(h6)) - Math.exp(-h5 / r2) * (ab + aa * r2) * 0.053051647;
234// if (h7 > 0. && -h3 < 500.0)
235 for (i = 0; i < 5; i++) {
236 r1 = r3 * Z[i];
237 rr = r1 * r1;
238 r2 = Math.sqrt(1. - rr);
239 bvn -= W[i] * Math.exp(-h5 / rr) * (Math.exp(-h3 / (1. + r2)) / r2 / h7 - 1. - aa * rr);
240 }
241 }
242
243 if (rho > 0.)
244 bvn = bvn * r3 * h7 + (1.0 - Gauss(Math.max(h1, h2)));
245 else if (rho < 0.)
246 bvn = (h1 < h2 ? Gauss(h2) - Gauss(h1) : 0.) - bvn * r3 * h7;
247
248 } else {
249 h3 = h1 * h2;
250 for (i = 0; i < 5; i++) {
251 r1 = rho * Z[i];
252 r2 = 1. - r1 * r1;
253 bvn += W[i] * Math.exp((r1 * h3 - h12) / r2) / Math.sqrt(r2);
254 }
255 bvn = (1.0 - Gauss(h1)) * (1.0 - Gauss(h2)) + rho * bvn;
256 }
257
258 if (bvn <= 0.0)
259 return 0.0;
260 if (bvn <= 1.0)
261 return bvn;
262 return 1.0;
263 }
264
265 public double cdf(double x, double y) {
266 return cdf((x - mu1) / sigma1, (y - mu2) / sigma2, rho);
267 }
268
279 public static double cdf(double mu1, double sigma1, double x, double mu2, double sigma2, double y, double rho) {
280 if (sigma1 <= 0)
281 throw new IllegalArgumentException("sigma1 <= 0");
282 if (sigma2 <= 0)
283 throw new IllegalArgumentException("sigma2 <= 0");
284 double X = (x - mu1) / sigma1;
285 double Y = (y - mu2) / sigma2;
286 return cdf(X, Y, rho);
287 }
288
295 public static double barF(double x, double y, double rho) {
296 return cdf(-x, -y, rho);
297 }
298
299 public double barF(double x, double y) {
300 return barF((x - mu1) / sigma1, (y - mu2) / sigma2, rho);
301 }
302
313 public static double barF(double mu1, double sigma1, double x, double mu2, double sigma2, double y, double rho) {
314 if (sigma1 <= 0)
315 throw new IllegalArgumentException("sigma1 <= 0");
316 if (sigma2 <= 0)
317 throw new IllegalArgumentException("sigma2 <= 0");
318 double X = (x - mu1) / sigma1;
319 double Y = (y - mu2) / sigma2;
320 return barF(X, Y, rho);
321 }
322
323 public double[] getMean() {
324 return getMean(mu1, mu2, sigma1, sigma2, rho);
325 }
326
331 public static double[] getMean(double mu1, double sigma1, double mu2, double sigma2, double rho) {
332 if (sigma1 <= 0)
333 throw new IllegalArgumentException("sigma1 <= 0");
334 if (sigma2 <= 0)
335 throw new IllegalArgumentException("sigma2 <= 0");
336 if (Math.abs(rho) > 1.)
337 throw new IllegalArgumentException("|rho| > 1");
338
339 double mean[] = new double[2];
340
341 mean[0] = mu1;
342 mean[1] = mu2;
343
344 return mean;
345 }
346
347 public double[][] getCovariance() {
348 return getCovariance(mu1, sigma1, mu2, sigma2, rho);
349 }
350
354 public static double[][] getCovariance(double mu1, double sigma1, double mu2, double sigma2, double rho) {
355 if (sigma1 <= 0)
356 throw new IllegalArgumentException("sigma1 <= 0");
357 if (sigma2 <= 0)
358 throw new IllegalArgumentException("sigma2 <= 0");
359 if (Math.abs(rho) > 1.)
360 throw new IllegalArgumentException("|rho| > 1");
361
362 double cov[][] = new double[2][2];
363
364 cov[0][0] = sigma1 * sigma1;
365 cov[0][1] = rho * sigma1 * sigma2;
366 cov[1][0] = cov[0][1];
367 cov[1][1] = sigma2 * sigma2;
368
369 return cov;
370 }
371
372 public double[][] getCorrelation() {
373 return getCovariance(mu1, sigma1, mu2, sigma2, rho);
374 }
375
379 public static double[][] getCorrelation(double mu1, double sigma1, double mu2, double sigma2, double rho) {
380 if (sigma1 <= 0)
381 throw new IllegalArgumentException("sigma1 <= 0");
382 if (sigma2 <= 0)
383 throw new IllegalArgumentException("sigma2 <= 0");
384 if (Math.abs(rho) > 1.)
385 throw new IllegalArgumentException("|rho| > 1");
386
387 double corr[][] = new double[2][2];
388
389 corr[0][0] = 1.0;
390 corr[0][1] = rho;
391 corr[1][0] = rho;
392 corr[1][1] = 1.0;
393
394 return corr;
395 }
396
400 public double getMu1() {
401 return mu1;
402 }
403
407 public double getMu2() {
408 return mu2;
409 }
410
414 public double getSigma1() {
415 return sigma1;
416 }
417
421 public double getSigma2() {
422 return sigma2;
423 }
424
431 protected void setParams(double mu1, double sigma1, double mu2, double sigma2, double rho) {
432 if (sigma1 <= 0)
433 throw new IllegalArgumentException("sigma1 <= 0");
434 if (sigma2 <= 0)
435 throw new IllegalArgumentException("sigma2 <= 0");
436 if (Math.abs(rho) > 1.)
437 throw new IllegalArgumentException("|rho| > 1");
438 this.dimension = 2;
439 this.mu1 = mu1;
440 this.sigma1 = sigma1;
441 this.mu2 = mu2;
442 this.sigma2 = sigma2;
443 this.rho = rho;
444 racRho = Math.sqrt((1.0 - rho) * (1.0 + rho));
445 detS = 2.0 * Math.PI * sigma1 * sigma2 * racRho;
446 }
447
448}
static double barF(double x, double y, double rho)
Computes the standard upper binormal distribution with and .
static double density(double x, double y, double rho)
Computes the standard binormal density function ( f1binormal ) with and .
double density(double x, double y)
Returns , the density of evaluated at .
BiNormalDist(double mu1, double sigma1, double mu2, double sigma2, double rho)
Constructs a BiNormalDist object with parameters = mu1, = mu2, = sigma1,.
static double cdf(double x, double y, double rho)
Computes the standard binormal distribution ( cdf2binormal ) using the fast Drezner-Wesolowsky method...
double[] getMean()
Returns the mean vector of the distribution, defined as .
double cdf(double x, double y)
Computes the distribution function :
static double cdf(double mu1, double sigma1, double x, double mu2, double sigma2, double y, double rho)
Computes the binormal distribution function ( cdf1binormal ) with parameters = mu1,...
double getSigma1()
Returns the parameter .
double[][] getCorrelation()
Returns the correlation matrix of the distribution, defined as.
static double[][] getCorrelation(double mu1, double sigma1, double mu2, double sigma2, double rho)
Return the correlation matrix of the binormal distribution.
void setParams(double mu1, double sigma1, double mu2, double sigma2, double rho)
Sets the parameters = mu1, = mu2,.
BiNormalDist(double rho)
Constructs a BiNormalDist object with default parameters , and correlation.
double getMu2()
Returns the parameter .
double getMu1()
Returns the parameter .
double getSigma2()
Returns the parameter .
static double[][] getCovariance(double mu1, double sigma1, double mu2, double sigma2, double rho)
Return the covariance matrix of the binormal distribution.
double barF(double x, double y)
Computes the upper cumulative distribution function.
static double barF(double mu1, double sigma1, double x, double mu2, double sigma2, double y, double rho)
Computes the upper binormal distribution function ( cdf3binormal ) with parameters = mu1,...
double[][] getCovariance()
Returns the variance-covariance matrix of the distribution, defined as .
static double density(double mu1, double sigma1, double x, double mu2, double sigma2, double y, double rho)
Computes the binormal density function ( f1binormal ) with parameters = mu1, = mu2,...
static double[] getMean(double mu1, double sigma1, double mu2, double sigma2, double rho)
Return the mean vector of the binormal distribution.
Classes implementing 2-dimensional continuous distributions should inherit from this class.