SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
BetaSymmetricalDist.java
1/*
2 * Class: BetaSymmetricalDist
3 * Description: Symmetrical beta 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 April 2005
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
43public class BetaSymmetricalDist extends BetaDist {
44 private static final double PI_2 = 1.5707963267948966; // Pi/2
45 private static final int MAXI = 11; // Max number of Newton iterations
46 private static final int MAXIB = 50; // Max number of bisection iterations
47 private static final int MAXJ = 2000; // Max number of terms in series
48 private static final double EPSSINGLE = 1.0e-5;
49 private static final double EPSBETA = 1.0e-10; // < 0.75 sqrt(DBL_EPSILON)
50 private static final double SQPI_2 = 0.88622692545275801; // Sqrt(Pi)/2
51 private static final double LOG_SQPI_2 = -0.1207822376352453; // Ln(Sqrt(Pi)/2)
52 private static final double ALIM1 = 100000.0; // limit for normal approximation
53 private static final double LOG2 = 0.6931471805599453; // Ln(2)
54 private static final double LOG4 = 1.3862943611198906; // Ln(4)
55 private static final double INV2PI = 0.6366197723675813; // 2 / PI
56 private double Ceta;
57 private double logCeta;
58
59 private static class Function implements MathFunction {
60 protected int n;
61 protected double sum;
62
63 public Function(double sum, int n) {
64 this.n = n;
65 this.sum = sum;
66 }
67
68 public double evaluate(double x) {
69 if (x <= 0.0)
70 return 1.0e100;
71 return (-2.0 * n * Num.digamma(x) + n * 2.0 * Num.digamma(2.0 * x) + sum);
72 }
73 }
74
80 public BetaSymmetricalDist(double alpha) {
81 super(alpha, alpha);
82 setParams(alpha, 14);
83 }
84
90 public BetaSymmetricalDist(double alpha, int d) {
91 super(alpha, alpha);
92 setParams(alpha, d);
93 }
94
95 public double cdf(double x) {
96 return calcCdf(alpha, x, decPrec, logFactor, logBeta, logCeta, Ceta);
97 }
98
99 public double barF(double x) {
100 return calcCdf(alpha, 1.0 - x, decPrec, logFactor, logBeta, logCeta, Ceta);
101 }
102
103 public double inverseF(double u) {
104 return calcInverseF(alpha, u, decPrec, logFactor, logBeta, logCeta, Ceta);
105 }
106
110 public static double density(double alpha, double x) {
111 return density(alpha, alpha, 0.0, 1.0, x);
112 }
113
117 public static double cdf(double alpha, int d, double x) {
118 return calcCdf(alpha, x, d, Num.DBL_MIN, 0.0, 0.0, 0.0);
119 }
120
124 public static double barF(double alpha, int d, double x) {
125 return cdf(alpha, d, 1.0 - x);
126 }
127
141 public static double inverseF(double alpha, double u) {
142 return calcInverseF(alpha, u, 14, Num.DBL_MIN, 0.0, 0.0, 0.0);
143 }
144
145 /*----------------------------------------------------------------------*/
146
147 private static double series1(double alpha, double x, double epsilon)
148 /*
149 * Compute the series for F(x). This series is used for alpha < 1 and x close to
150 * 0.
151 */
152 {
153 int j;
154 double sum, term;
155 double poc = 1.0;
156 sum = 1.0 / alpha;
157 j = 1;
158 do {
159 poc *= x * (j - alpha) / j;
160 term = poc / (j + alpha);
161 sum += term;
162 ++j;
163 } while ((term > sum * epsilon) && (j < MAXJ));
164
165 return sum * Math.pow(x, alpha);
166 }
167
168 /*------------------------------------------------------------------------*/
169
170 private static double series2(double alpha, double y, double epsilon)
171 /*
172 * Compute the series for G(y). y = 0.5 - x. This series is used for alpha < 1
173 * and x close to 1/2.
174 */
175 {
176 int j;
177 double term, sum;
178 double poc;
179 final double z = 4.0 * y * y;
180
181 /* Compute the series for G(y) */
182 poc = sum = 1.0;
183 j = 1;
184 do {
185 poc *= z * (j - alpha) / j;
186 term = poc / (2 * j + 1);
187 sum += term;
188 ++j;
189 } while ((term > sum * epsilon) && (j < MAXJ));
190
191 return sum * y;
192 }
193
194 /*------------------------------------------------------------------------*/
195
196 private static double series3(double alpha, double x, double epsilon)
197 /*
198 * Compute the series for F(x). This series is used for alpha > 1 and x close to
199 * 0.
200 */
201 {
202 int j;
203 double sum, term;
204 final double z = -x / (1.0 - x);
205
206 sum = term = 1.0;
207 j = 1;
208 do {
209 term *= z * (j - alpha) / (j + alpha);
210 sum += term;
211 ++j;
212 } while ((Math.abs(term) > sum * epsilon) && (j < MAXJ));
213
214 return sum * x;
215 }
216
217 /*------------------------------------------------------------------------*/
218
219 private static double series4(double alpha, double y, double epsilon)
220 /*
221 * Compute the series for G(y). y = 0.5 - x. This series is used for alpha > 1
222 * and x close to 1/2.
223 */
224 {
225 int j;
226 double term, sum;
227 final double z = 4.0 * y * y;
228
229 term = sum = 1.0;
230 j = 1;
231 do {
232 term *= z * (j + alpha - 0.5) / (0.5 + j);
233 sum += term;
234 ++j;
235 } while ((term > sum * epsilon) && (j < MAXJ));
236
237 return sum * y;
238 }
239
240 /*------------------------------------------------------------------------*/
241
242 private static double Peizer(double alpha, double x)
243 /*
244 * Normal approximation of Peizer and Pratt
245 */
246 {
247 final double y = 1.0 - x;
248 double z;
249 z = Math.sqrt(
250 (1.0 - y * BetaDist.beta_g(2.0 * x) - x * BetaDist.beta_g(2.0 * y)) / ((2.0 * alpha - 5.0 / 6.0) * x * y))
251 * (2.0 * x - 1.0) * (alpha - 1.0 / 3.0 + 0.025 / alpha);
252
253 return NormalDist.cdf01(z);
254 }
255
256 /*-------------------------------------------------------------------------*/
257
258 private static double inverse1(double alpha, // Shape parameter
259 double bu, // u * Beta(alpha, alpha)
260 int d // Digits of precision
261 )
262 /*
263 * This method is used for alpha < 1 and x close to 0.
264 */
265 {
266 int i, j;
267 double x, xnew, poc, sum, term;
268 final double EPSILON = EPSARRAY[d];
269
270 // First term of series
271 x = Math.pow(bu * alpha, 1.0 / alpha);
272
273 // If T1/T0 is very small, neglect all terms of series except T0
274 term = alpha * (1.0 - alpha) * x / (1.0 + alpha);
275 if (term < EPSILON)
276 return x;
277
278 x = bu * alpha / (1.0 + term);
279 xnew = Math.pow(x, 1.0 / alpha); // Starting point of Newton's iterates
280
281 i = 0;
282 do {
283 ++i;
284 x = xnew;
285
286 /* Compute the series for F(x) */
287 poc = 1.0;
288 sum = 1.0 / alpha;
289 j = 1;
290 do {
291 poc *= x * (j - alpha) / j;
292 term = poc / (j + alpha);
293 sum += term;
294 ++j;
295 } while ((term > sum * EPSILON) && (j < MAXJ));
296 sum *= Math.pow(x, alpha);
297
298 /* Newton's method */
299 term = (sum - bu) * Math.pow(x * (1.0 - x), 1.0 - alpha);
300 xnew = x - term;
301
302 } while ((Math.abs(term) > EPSILON) && (i <= MAXI));
303
304 return xnew;
305 }
306
307 /*----------------------------------------------------------------------*/
308
309 private static double inverse2(double alpha, // Shape parameter
310 double w, // (0.5 - u)B/pow(4, 1 - alpha)
311 int d // Digits of precision
312 )
313 /*
314 * This method is used for alpha < 1 and x close to 1/2.
315 */
316 {
317 int i, j;
318 double term, y, ynew, z, sum;
319 double poc;
320 final double EPSILON = EPSARRAY[d];
321
322 term = (1.0 - alpha) * w * w * 4.0 / 3.0;
323 /* If T1/T0 is very small, neglect all terms of series except T0 */
324 if (term < EPSILON)
325 return 0.5 - w;
326
327 ynew = w / (1 + term); /* Starting point of Newton's iterates */
328 i = 0;
329 do {
330 ++i;
331 y = ynew;
332 z = 4.0 * y * y;
333
334 // Compute the series for G(y)
335 poc = sum = 1.0;
336 j = 1;
337 do {
338 poc *= z * (j - alpha) / j;
339 term = poc / (2 * j + 1);
340 sum += term;
341 ++j;
342 } while ((term > sum * EPSILON) && (j < MAXJ));
343
344 sum *= y;
345
346 // Newton's method
347 ynew = y - (sum - w) * Math.pow(1.0 - z, 1.0 - alpha);
348
349 } while ((Math.abs(ynew - y) > EPSILON) && (i <= MAXI));
350
351 return 0.5 - ynew;
352 }
353
354 /*---------------------------------------------------------------------*/
355
356 private static double bisect(double alpha, // Shape parameter
357 double logBua, // Ln(alpha * u * Beta(alpha, alpha))
358 double a, // x is presumed in [a, b]
359 double b, int d // Digits of precision
360 )
361 /*
362 * This method is used for alpha > 1 and u very close to 0. It will almost never
363 * be called, if at all.
364 */
365 {
366 int i, j;
367 double z, sum, term;
368 double x, xprev;
369 final double EPSILON = EPSARRAY[d];
370
371 if (a >= 0.5 || a > b) {
372 a = 0.0;
373 b = 0.5;
374 }
375
376 x = 0.5 * (a + b);
377 i = 0;
378 do {
379 ++i;
380 z = -x / (1 - x);
381
382 /* Compute the series for F(x) */
383 sum = term = 1.0;
384 j = 1;
385 do {
386 term *= z * (j - alpha) / (j + alpha);
387 sum += term;
388 ++j;
389 } while ((Math.abs(term / sum) > EPSILON) && (j < MAXJ));
390 sum *= x;
391
392 /* Bisection method */
393 term = Math.log(x * (1.0 - x));
394 z = logBua - (alpha - 1.0) * term;
395 if (z > Math.log(sum))
396 a = x;
397 else
398 b = x;
399 xprev = x;
400 x = 0.5 * (a + b);
401
402 } while ((Math.abs(xprev - x) > EPSILON) && (i < MAXIB));
403
404 return x;
405 }
406
407 /*---------------------------------------------------------------------*/
408
409 private static double inverse3(double alpha, // Shape parameter
410 double logBua, // Ln(alpha * u * Beta(alpha, alpha))
411 int d // Digits of precision
412 )
413 /*
414 * This method is used for alpha > 1 and x close to 0.
415 */
416 {
417 int i, j;
418 double z, x, w, xnew, sum = 0., term;
419 double eps = EPSSINGLE;
420 final double EPSILON = EPSARRAY[d];
421 // For alpha <= 100000 and u < 1.0/(2.5 + 2.25*sqrt(alpha)), X0 is always
422 // to the right of the solution, so Newton is certain to converge.
423 final double X0 = 0.497;
424
425 /* Compute starting point of Newton's iterates */
426 w = logBua / alpha;
427 x = Math.exp(w);
428 term = (Math.log1p(-x) + logBua) / alpha;
429 z = Math.exp(term);
430 if (z >= 0.25)
431 xnew = X0;
432 else if (z > 1.0e-6)
433 xnew = (1.0 - Math.sqrt(1.0 - 4.0 * z)) / 2.0;
434 else
435 xnew = z;
436
437 i = 0;
438 do {
439 ++i;
440 if (xnew >= 0.5)
441 xnew = X0;
442 x = xnew;
443
444 sum = Math.log(x * (1.0 - x));
445 w = logBua - (alpha - 1.0) * sum;
446 if (Math.abs(w) >= Num.DBL_MAX_EXP * Num.LN2) {
447 xnew = X0;
448 continue;
449 }
450 w = Math.exp(w);
451 z = -x / (1 - x);
452
453 /* Compute the series for F(x) */
454 sum = term = 1.0;
455 j = 1;
456 do {
457 term *= z * (j - alpha) / (j + alpha);
458 sum += term;
459 ++j;
460 } while ((Math.abs(term / sum) > eps) && (j < MAXJ));
461 sum *= x;
462
463 /* Newton's method */
464 term = (sum - w) / alpha;
465 xnew = x - term;
466 if (Math.abs(term) < 32.0 * EPSSINGLE)
467 eps = EPSILON;
468
469 } while ((Math.abs(xnew - x) > sum * EPSILON) && (Math.abs(xnew - x) > EPSILON) && (i <= MAXI));
470
471 /*
472 * If Newton has not converged with enough precision, call bisection method. It
473 * is very slow, but will be called very rarely.
474 */
475 if (i >= MAXI && Math.abs(xnew - x) > 10.0 * EPSILON)
476 return bisect(alpha, logBua, 0.0, 0.5, d);
477 return xnew;
478 }
479
480 /*---------------------------------------------------------------------*/
481
482 private static double inverse4(double alpha, // Shape parameter
483 double logBva, // Ln(B) + Ln(1/2 - u) + (alpha - 1)*Ln(4)
484 int d // Digits of precision
485 )
486 /*
487 * This method is used for alpha > 1 and x close to 1/2.
488 */
489 {
490 int i, j;
491 double term, sum, y, ynew, z;
492 double eps = EPSSINGLE;
493 final double EPSILON = EPSARRAY[d];
494
495 ynew = Math.exp(logBva); // Starting point of Newton's iterates
496 i = 0;
497 do {
498 ++i;
499 y = ynew;
500
501 /* Compute the series for G(y) */
502 z = 4.0 * y * y;
503 term = sum = 1.0;
504 j = 1;
505 do {
506 term *= z * (j + alpha - 0.5) / (0.5 + j);
507 sum += term;
508 ++j;
509 } while ((term > sum * eps) && (j < MAXJ));
510 sum *= y * (1.0 - z);
511
512 /* Newton's method */
513 term = Math.log1p(-z);
514 term = sum - Math.exp(logBva - (alpha - 1.0) * term);
515 ynew = y - term;
516 if (Math.abs(term) < 32.0 * EPSSINGLE)
517 eps = EPSILON;
518
519 } while ((Math.abs(ynew - y) > EPSILON) && (Math.abs(ynew - y) > sum * EPSILON) && (i <= MAXI));
520
521 return 0.5 - ynew;
522 }
523
524 /*---------------------------------------------------------------------*/
525
526 private static double PeizerInverse(double alpha, double u) {
527 /* Inverse of the normal approximation of Peizer and Pratt */
528 double t1, t3, xprev;
529 final double C2 = alpha - 1.0 / 3.0 + 0.025 / alpha;
530 final double z = NormalDist.inverseF01(u);
531 double x = 0.5;
532 double y = 1.0 - x;
533 int i = 0;
534
535 do {
536 i++;
537 t1 = (2.0 * alpha - 5.0 / 6.0) * x * y;
538 t3 = 1.0 - y * BetaDist.beta_g(2.0 * x) - x * BetaDist.beta_g(2.0 * y);
539 xprev = x;
540 x = 0.5 + 0.5 * z * Math.sqrt(t1 / t3) / C2;
541 y = 1.0 - x;
542 } while (i <= MAXI && Math.abs(x - xprev) > EPSBETA);
543
544 return x;
545 }
546
547 /*---------------------------------------------------------------------*/
548
549 private static void CalcB4(double alpha, double[] bc, double epsilon) {
550 double temp;
551 double pB = 0.0;
552 double plogB = 0.0;
553 double plogC = 0.0;
554
555 /* Compute Beta(alpha, alpha) or Beta(alpha, alpha)*4^(alpha-1). */
556
557 if (alpha <= EPSBETA) {
558 /* For a -> 0, B(a,a) = (2/a)*(1 - 1.645*a^2 + O(a^3)) */
559 pB = 2.0 / alpha;
560 plogB = Math.log(pB);
561 plogC = plogB + (alpha - 1.0) * LOG4;
562
563 } else if (alpha <= 1.0) {
564 temp = Num.lnGamma(alpha);
565 plogB = 2.0 * temp - Num.lnGamma(2.0 * alpha);
566 plogC = plogB + (alpha - 1.0) * LOG4;
567 pB = Math.exp(plogB);
568
569 } else if (alpha <= 10.0) {
570 plogC = Num.lnGamma(alpha) - Num.lnGamma(0.5 + alpha) + LOG_SQPI_2;
571 plogB = plogC - (alpha - 1.0) * LOG4;
572 pB = Math.exp(plogB);
573
574 } else if (alpha <= 200.0) {
575 /* Convergent series for Gamma(x + 0.5) / Gamma(x) */
576 double term = 1.0;
577 double sum = 1.0;
578 int i = 1;
579 while (term > epsilon * sum) {
580 term *= (i - 1.5) * (i - 1.5) / (i * (alpha + i - 1.5));
581 sum += term;
582 i++;
583 }
584 temp = SQPI_2 / Math.sqrt((alpha - 0.5) * sum);
585 plogC = Math.log(temp);
586 plogB = plogC - (alpha - 1.0) * LOG4;
587 pB = Math.exp(plogB);
588
589 } else {
590 /* Asymptotic series for Gamma(a + 0.5) / (Gamma(a) * Sqrt(a)) */
591 double z = 1.0 / (8.0 * alpha);
592 temp = 1.0 + z * (-1.0 + z * (0.5 + z * (2.5 - z * (2.625 + 49.875 * z))));
593 /* This is 4^(alpha - 1)*B(alpha, alpha) */
594 temp = SQPI_2 / (Math.sqrt(alpha) * temp);
595 plogC = Math.log(temp);
596 plogB = plogC - (alpha - 1.0) * LOG4;
597 pB = Math.exp(plogB);
598 }
599 bc[0] = pB;
600 bc[1] = plogB;
601 bc[2] = plogC;
602 }
603
604 /*---------------------------------------------------------------------*/
605
606 private static double calcInverseF(double alpha, double u, int d, double logFact, double logBeta, double logCeta,
607 double Ceta) {
608 if (alpha <= 0.0)
609 throw new IllegalArgumentException("alpha <= 0");
610 if (u > 1.0 || u < 0.0)
611 throw new IllegalArgumentException("u not in [0,1]");
612 if (u == 0.0)
613 return 0.0;
614 if (u == 1.0)
615 return 1.0;
616 if (u == 0.5)
617 return 0.5;
618
619 // Case alpha = 1 is the uniform law
620 if (alpha == 1.0)
621 return u;
622
623 // Case alpha = 1/2 is the arcsin law
624 double temp;
625 if (alpha == 0.5) {
626 temp = Math.sin(u * PI_2);
627 return temp * temp;
628 }
629
630 if (alpha > ALIM1)
631 return PeizerInverse(alpha, u);
632
633 boolean isUpper; // True if u > 0.5
634 if (u > 0.5) {
635 isUpper = true;
636 u = 1.0 - u;
637 } else
638 isUpper = false;
639
640 double x;
641 double C = 0.0, B = 0.0, logB = 0.0, logC = 0.0;
642
643 if (logFact == Num.DBL_MIN) {
644 double[] bc = new double[] { 0.0, 0.0, 0.0 };
645 CalcB4(alpha, bc, EPSARRAY[d]);
646 B = bc[0];
647 logB = bc[1];
648 logC = bc[2];
649 C = Math.exp(logC);
650 } else {
651 B = 1.0 / Math.exp(logFact);
652 logB = logBeta;
653 logC = logCeta;
654 C = Ceta;
655 }
656
657 if (alpha <= 1.0) {
658 // First term of integrated series around 1/2
659 double y0 = C * (0.5 - u);
660 if (y0 > 0.25)
661 x = inverse1(alpha, B * u, d);
662 else
663 x = inverse2(alpha, y0, d);
664
665 } else {
666 if (u < 1.0 / (2.5 + 2.25 * Math.sqrt(alpha))) {
667 double logBua = logB + Math.log(u * alpha);
668 x = inverse3(alpha, logBua, d);
669 } else {
670 // logBva = Ln(Beta(a,a) * (0.5 - u)*pow(4, a - 1)
671 double logBva = logC - LOG2 + Math.log1p(-2.0 * u);
672
673 x = inverse4(alpha, logBva, d);
674 }
675 }
676
677 if (isUpper)
678 return 1.0 - x - Num.DBL_EPSILON;
679 else
680 return x;
681 }
682
683 /*---------------------------------------------------------------------*/
684
685 private static double calcCdf(double alpha, double x, int d, double logFact, double logBeta, double logCeta,
686 double Ceta) {
687 double temp, u, logB = 0.0, logC = 0.0, C = 0.0;
688 boolean isUpper; /* True if x > 0.5 */
689 double B = 0.0; /* Beta(alpha, alpha) */
690 double x0;
691 final double EPSILON = EPSARRAY[d]; // Absolute precision
692
693 if (alpha <= 0.0)
694 throw new IllegalArgumentException("alpha <= 0");
695
696 if (x <= 0.0)
697 return 0.0;
698 if (x >= 1.0)
699 return 1.0;
700 if (x == 0.5)
701 return 0.5;
702 if (alpha == 1.0)
703 return x; /* alpha = 1 is the uniform law */
704 if (alpha == 0.5) /* alpha = 1/2 is the arcsin law */
705 return INV2PI * Math.asin(Math.sqrt(x));
706
707 if (alpha > ALIM1)
708 return Peizer(alpha, x);
709
710 if (x > 0.5) {
711 x = 1.0 - x;
712 isUpper = true;
713 } else
714 isUpper = false;
715
716 if (logFact == Num.DBL_MIN) {
717 double[] bc = new double[3];
718 bc[0] = B;
719 bc[1] = logB;
720 bc[2] = logC;
721 CalcB4(alpha, bc, EPSILON);
722 B = bc[0];
723 logB = bc[1];
724 logC = bc[2];
725 C = Math.exp(logC);
726 } else {
727 B = 1.0 / Math.exp(logFact);
728 logB = logBeta;
729 logC = logCeta;
730 C = Ceta;
731 }
732
733 if (alpha <= 1.0) {
734 /*
735 * For x = x0, both series use the same number of terms to get the required
736 * precision
737 */
738 if (x > 0.25) {
739 temp = -Math.log(alpha);
740 if (alpha >= 1.0e-6)
741 x0 = 0.25 + 0.005 * temp;
742 else
743 x0 = 0.13863 + .01235 * temp;
744 } else
745 x0 = 0.25;
746
747 if (x <= x0)
748 u = (series1(alpha, x, EPSILON)) / B;
749 else
750 u = 0.5 - (series2(alpha, 0.5 - x, EPSILON)) / C;
751
752 } else { /* 1 < alpha < ALIM1 */
753 if (alpha < 400.0)
754 x0 = 0.5 - 0.9 / Math.sqrt(4.0 * alpha);
755 else
756 x0 = 0.5 - 1.0 / Math.sqrt(alpha);
757 if (x0 < 0.25)
758 x0 = 0.25;
759
760 if (x <= x0) {
761 temp = (alpha - 1.0) * Math.log(x * (1.0 - x)) - logB;
762 u = series3(alpha, x, EPSILON) * Math.exp(temp) / alpha;
763
764 } else {
765 final double y = 0.5 - x;
766 if (y > 0.05) {
767 temp = Math.log(1.0 - 4.0 * y * y);
768 } else {
769 u = 4.0 * y * y;
770 temp = -u
771 * (1.0 + u * (0.5 + u * (1.0 / 3.0 + u * (0.25 + u * (0.2 + u * (1.0 / 6.0 + u * 1.0 / 7.0))))));
772 }
773 temp = alpha * temp - logC;
774 u = 0.5 - (series4(alpha, y, EPSILON)) * Math.exp(temp);
775 }
776 }
777
778 if (isUpper)
779 return 1.0 - u;
780 else
781 return u;
782 }
783
784 public double getMean() {
785 return 0.5;
786 }
787
788 public double getVariance() {
789 return BetaSymmetricalDist.getVariance(alpha);
790 }
791
792 public double getStandardDeviation() {
793 return BetaSymmetricalDist.getStandardDeviation(alpha);
794 }
795
812 public static double[] getMLE(double[] x, int n) {
813 if (n <= 0)
814 throw new IllegalArgumentException("n <= 0");
815
816 double var = 0.0;
817 double sum = 0.0;
818 for (int i = 0; i < n; i++) {
819 var += ((x[i] - 0.5) * (x[i] - 0.5));
820 if (x[i] > 0.0 && x[i] < 1.0)
821 sum += Math.log(x[i] * (1.0 - x[i]));
822 else
823 sum -= 709.0;
824 }
825 var /= n;
826
827 Function f = new Function(sum, n);
828
829 double[] parameters = new double[1];
830 double alpha0 = (1.0 - 4.0 * var) / (8.0 * var);
831
832 double a = alpha0 - 5.0;
833 if (a <= 0.0)
834 a = 1e-15;
835
836 parameters[0] = RootFinder.brentDekker(a, alpha0 + 5.0, f, 1e-5);
837
838 return parameters;
839 }
840
849 public static BetaSymmetricalDist getInstanceFromMLE(double[] x, int n) {
850 double parameters[] = getMLE(x, n);
851 return new BetaSymmetricalDist(parameters[0]);
852 }
853
860 public static double getMean(double alpha) {
861 if (alpha <= 0.0)
862 throw new IllegalArgumentException("alpha <= 0");
863
864 return 0.5;
865 }
866
874 public static double getVariance(double alpha) {
875 if (alpha <= 0.0)
876 throw new IllegalArgumentException("alpha <= 0");
877
878 return (1 / (8 * alpha + 4));
879 }
880
887 public static double getStandardDeviation(double alpha) {
888 if (alpha <= 0.0)
889 throw new IllegalArgumentException("alpha <= 0");
890
891 return (1 / Math.sqrt(8 * alpha + 4));
892 }
893
894 public void setParams(double alpha, double beta, double a, double b, int d) {
895 // We don't want to calculate Beta, logBeta and logFactor twice.
896 if (a >= b)
897 throw new IllegalArgumentException("a >= b");
898 this.decPrec = d;
899 supportA = this.a = a;
900 supportB = this.b = b;
901 bminusa = b - a;
902 }
903
904 private void setParams(double alpha, int d) {
905 if (alpha <= 0.0)
906 throw new IllegalArgumentException("alpha <= 0");
907 this.alpha = alpha;
908 beta = alpha;
909
910 double[] bc = new double[] { 0.0, 0.0, 0.0 };
911 CalcB4(alpha, bc, EPSARRAY[d]);
912 Beta = bc[0];
913 logBeta = bc[1];
914 logCeta = bc[2];
915 Ceta = Math.exp(logCeta);
916 if (Beta > 0.0)
917 logFactor = -logBeta - (2.0 * alpha - 1) * Math.log(bminusa);
918 else
919 logFactor = 0.0;
920 }
921
925 public double[] getParams() {
926 double[] retour = { alpha };
927 return retour;
928 }
929
933 public String toString() {
934 return getClass().getSimpleName() + " : alpha = " + alpha;
935 }
936
937}
BetaDist(double alpha, double beta)
Constructs a BetaDist object with parameters alpha, beta and default domain .
static double density(double alpha, double x)
Returns the density evaluated at .
static BetaSymmetricalDist getInstanceFromMLE(double[] x, int n)
Creates a new instance of a symmetrical beta distribution with parameter estimated using the maximum...
static double getStandardDeviation(double alpha)
Computes and returns the standard deviation of the symmetrical beta distribution with parameter .
String toString()
Returns a String containing information about the current distribution.
static double cdf(double alpha, int d, double x)
Same as cdf(alpha, alpha, d, x).
double getStandardDeviation()
Returns the standard deviation.
static double barF(double alpha, int d, double x)
Returns the complementary distribution function.
BetaSymmetricalDist(double alpha, int d)
Same as BetaSymmetricalDist (alpha), but using approximations of roughly d decimal digits of precisio...
BetaSymmetricalDist(double alpha)
Constructs a BetaSymmetricalDist object with parameters.
double inverseF(double u)
Returns the inverse distribution function .
static double inverseF(double alpha, double u)
Returns the inverse distribution function evaluated at , for the symmetrical beta distribution over t...
static double getMean(double alpha)
Computes and returns the mean of the symmetrical beta distribution with parameter .
double barF(double x)
Returns the complementary distribution function.
static double[] getMLE(double[] x, int n)
Estimates the parameter of the symmetrical beta distribution over the interval [0,...
static double getVariance(double alpha)
Computes and returns the variance, , of the symmetrical beta distribution with parameter.
double cdf(double x)
Returns the distribution function .
double[] getParams()
Return a table containing the parameter of the current distribution.
This class provides various constants and methods to compute numerical quantities such as factorials,...
Definition Num.java:35
static final double DBL_MIN
Smallest normalized positive floating-point double.
Definition Num.java:113
static double digamma(double x)
Returns the value of the logarithmic derivative of the Gamma function .
Definition Num.java:487
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.