SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
BetaStratifiedRejectionGen.java
1/*
2 * Class: BetaStratifiedRejectionGen
3 * Description: beta random variate generators using the stratified
4 rejection/patchwork rejection method
5 * Environment: Java
6 * Software: SSJ
7 * Copyright (C) 2001 Pierre L'Ecuyer and Universite de Montreal
8 * Organization: DIRO, Universite de Montreal
9 * @author
10 * @since
11 *
12 *
13 * Licensed under the Apache License, Version 2.0 (the "License");
14 * you may not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS,
21 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 *
25 */
26package umontreal.ssj.randvar;
27
28import umontreal.ssj.util.Num;
29import umontreal.ssj.rng.*;
30import umontreal.ssj.probdist.*;
31
44public class BetaStratifiedRejectionGen extends BetaGen {
45
46 private RandomStream auxStream;
47 private int gen;
48
49 // Parameters for stratified rejection/patchwork rejection
50 private static final int b00 = 2;
51 private static final int b01 = 3;
52 private static final int b01inv = 4;
53 private static final int b1prs = 5;
54 private double pint;
55 private double qint;
56 private double p_;
57 private double q_;
58 private double c;
59 private double t;
60 private double fp;
61 private double fq;
62 private double ml;
63 private double mu;
64 private double p1;
65 private double p2;
66 private double s;
67 private double m;
68 private double D;
69 private double Dl;
70 private double x1;
71 private double x2;
72 private double x4;
73 private double x5;
74 private double f1;
75 private double f2;
76 private double f4;
77 private double f5;
78 private double ll;
79 private double lr;
80 private double z2;
81 private double z4;
82 private double p3;
83 private double p4;
84
92 public BetaStratifiedRejectionGen(RandomStream s, RandomStream aux, double alpha, double beta) {
93 super(s, null);
94 auxStream = aux;
95 setParams(alpha, beta, 0.0, 1.0);
96 init();
97 }
98
104 public BetaStratifiedRejectionGen(RandomStream s, double alpha, double beta) {
105 this(s, s, alpha, beta);
106 }
107
116 public BetaStratifiedRejectionGen(RandomStream s, RandomStream aux, double alpha, double beta, double a, double b) {
117 super(s, null);
118 auxStream = aux;
119 setParams(alpha, beta, a, b);
120 init();
121 }
122
129 public BetaStratifiedRejectionGen(RandomStream s, double alpha, double beta, double a, double b) {
130 this(s, s, alpha, beta, a, b);
131 }
132
139 super(s, dist);
140 auxStream = aux;
141 if (dist != null)
142 setParams(dist.getAlpha(), dist.getBeta(), dist.getA(), dist.getB());
143 init();
144 }
145
151 this(s, s, dist);
152 }
153
158 return auxStream;
159 }
160
161 public double nextDouble() {
162 /************************************
163 * Previously: return stratifiedRejection(); Now executes code directly (without
164 * calling anything)
165 ***********************************/
166
167 // The code was taken from UNURAN
168 double X = 0.0;
169 double U, V, Z, W, Y;
170 RandomStream stream = this.stream;
171 switch (gen) {
172 case b00:
173 /* -X- generator code -X- */
174 while (true) {
175 U = stream.nextDouble() * p2;
176 stream = auxStream;
177 if (U <= p1) { /* X < t */
178 Z = Math.exp(Math.log(U / p1) / p);
179 X = t * Z;
180 /* squeeze accept: L(x) = 1 + (1 - q)x */
181 V = stream.nextDouble() * fq;
182 if (V <= 1. - q_ * X)
183 break;
184 /* squeeze reject: U(x) = 1 + ((1 - t)^(q-1) - 1)/t * x */
185 if (V <= 1. + (fq - 1.) * Z) {
186 /* quotient accept: quot(x) = (1 - x)^(q-1) / fq */
187 if (Math.log(V) <= q_ * Math.log(1. - X))
188 break;
189 }
190 } else { /* X > t */
191 Z = Math.exp(Math.log((U - p1) / (p2 - p1)) / q);
192 X = 1. - (1. - t) * Z;
193 /* squeeze accept: L(x) = 1 + (1 - p)(1 - x) */
194 V = stream.nextDouble() * fp;
195 if (V <= 1.0 - p_ * (1. - X))
196 break;
197 /* squeeze reject: U(x) = 1 + (t^(p-1) - 1)/(1 - t) * (1 - x) */
198 if (V <= 1.0 + (fp - 1.) * Z) {
199 /* quotient accept: quot(x) = x^(p-1) / fp */
200 if (Math.log(V) <= p_ * Math.log(X))
201 break;
202 }
203 }
204 }
205 /* -X- end of generator code -X- */
206 break;
207 case b01:
208 case b01inv:
209 /* -X- generator code -X- */
210 while (true) {
211 U = stream.nextDouble() * p2;
212 stream = auxStream;
213 if (U <= p1) { /* X < t */
214 Z = Math.exp(Math.log(U / p1) / pint);
215 X = t * Z;
216 /* squeeze accept: L(x) = 1 + m1*x, ml = -m1 */
217 V = stream.nextDouble();
218 if (V <= 1. - ml * X)
219 break;
220 /* squeeze reject: U(x) = 1 + m2*x, mu = -m2 * t */
221 if (V <= 1. - mu * Z)
222 /* quotient accept: quot(x) = (1 - x)^(q-1) */
223 if (Math.log(V) <= q_ * Math.log(1. - X))
224 break;
225 } else { /* X > t */
226 Z = Math.exp(Math.log((U - p1) / (p2 - p1)) / qint);
227 X = 1. - (1. - t) * Z;
228 /* squeeze accept: L(x) = 1 + (1 - p)(1 - x) */
229 V = stream.nextDouble() * fp;
230 if (V <= 1. - p_ * (1. - X))
231 break;
232 /* squeeze reject: U(x) = 1 + (t^(p-1) - 1)/(1 - t) * (1 - x) */
233 if (V <= 1. + (fp - 1.) * Z)
234 /* quotient accept: quot(x) = (x)^(p-1) / fp */
235 if (Math.log(V) <= p_ * Math.log(X))
236 break;
237 }
238 }
239 if (p > q)
240 /* p and q has been swapped */
241 X = 1. - X;
242 /* -X- end of generator code -X- */
243 break;
244 case b1prs:
245 while (true) {
246 U = stream.nextDouble() * p4;
247 stream = auxStream;
248 if (U <= p1) {
249 /* immediate accept: x2 < X < m, - f(x2) < W < 0 */
250 W = U / Dl - f2;
251 if (W <= 0.0) {
252 X = m - U / f2;
253 break;
254 }
255 /* immediate accept: x1 < X < x2, 0 < W < f(x1) */
256 if (W <= f1) {
257 X = x2 - W / f1 * Dl;
258 break;
259 }
260 /* candidates for acceptance-rejection-test */
261 U = stream.nextDouble();
262 V = Dl * U;
263 X = x2 - V;
264 Y = x2 + V;
265 /* squeeze accept: L(x) = f(x2) (x - z2) / (x2 - z2) */
266 if (W * (x2 - z2) <= f2 * (X - z2))
267 break;
268 V = f2 + f2 - W;
269 if (V < 1.0) {
270 /* squeeze accept: L(x) = f(x2) + (1 - f(x2))(x - x2)/(m - x2) */
271 if (V <= f2 + (1. - f2) * U) {
272 X = Y;
273 break;
274 }
275 /* quotient accept: x2 < Y < m, W >= 2f2 - f(Y) */
276 if (V <= Math.exp(p_ * Math.log(Y / m) + q_ * Math.log((10. - Y) / (1.0 - m)))) {
277 X = Y;
278 break;
279 }
280 }
281 } else if (U <= p2) {
282 U -= p1;
283 /* immediate accept: m < X < x4, - f(x4) < W < 0 */
284 W = U / D - f4;
285 if (W <= 0.) {
286 X = m + U / f4;
287 break;
288 }
289 /* immediate accept: x4 < X < x5, 0 < W < f(x5) */
290 if (W <= f5) {
291 X = x4 + W / f5 * D;
292 break;
293 }
294 /* candidates for acceptance-rejection-test */
295 U = stream.nextDouble();
296 V = D * U;
297 X = x4 + V;
298 Y = x4 - V;
299 /* squeeze accept: L(x) = f(x4) (z4 - x) / (z4 - x4) */
300 if (W * (z4 - x4) <= f4 * (z4 - X))
301 break;
302 V = f4 + f4 - W;
303 if (V < 1.0) {
304 /* squeeze accept: L(x) = f(x4) + (1 - f(x4))(x4 - x)/(x4 - m) */
305 if (V <= f4 + (1.0 - f4) * U) {
306 X = Y;
307 break;
308 }
309 /* quotient accept: m < Y < x4, W >= 2f4 - f(Y) */
310 if (V <= Math.exp(p_ * Math.log(Y / m) + q_ * Math.log((1.0 - Y) / (1.0 - m)))) {
311 X = Y;
312 break;
313 }
314 }
315 } else if (U <= p3) { /* X < x1 */
316 U = (U - p2) / (p3 - p2);
317 Y = Math.log(U);
318 X = x1 + ll * Y;
319 if (X <= 0.0) /* X > 0!! */
320 continue;
321 W = U * stream.nextDouble();
322 /* squeeze accept: L(x) = f(x1) (x - z1) / (x1 - z1) */
323 /* z1 = x1 - ll, W <= 1 + (X - x1)/ll */
324 if (W <= 1.0 + Y)
325 break;
326 W *= f1;
327 } else { /* x5 < X */
328 U = (U - p3) / (p4 - p3);
329 Y = Math.log(U);
330 X = x5 - lr * Y;
331 if (X >= 1.0) /* X < 1!! */
332 continue;
333 W = U * stream.nextDouble();
334 /* squeeze accept: L(x) = f(x5) (z5 - x) / (z5 - x5) */
335 /* z5 = x5 + lr, W <= 1 + (x5 - X)/lr */
336 if (W <= 1.0 + Y)
337 break;
338 W *= f5;
339 }
340 /* density accept: f(x) = (x/m)^(p_) ((1 - x)/(1 - m))^(q_) */
341 if (Math.log(W) <= p_ * Math.log(X / m) + q_ * Math.log((1.0 - X) / (1.0 - m)))
342 break;
343 }
344 /* -X- end of generator code -X- */
345 break;
346 default:
347 throw new IllegalStateException();
348 }
349
350 return gen == b01inv ? a + (b - a) * (1.0 - X) : a + (b - a) * X;
351 }
352
353 public static double nextDouble(RandomStream s, double alpha, double beta, double a, double b) {
354 return BetaDist.inverseF(alpha, beta, a, b, s.nextDouble());
355 }
356
357 private void init() {
358 // Code taken from UNURAN
359 if (p > 1.) {
360 if (q > 1.) /* p > 1 && q > 1 */
361 gen = b1prs;
362 else { /* p > 1 && q <= 1 */
363 gen = b01inv;
364 double temp = p;
365 p = q;
366 q = temp;
367 }
368 } else {
369 if (q > 1.) /* p <= 1 && q > 1 */
370 gen = b01;
371 else /* p <= 1 && q <= 1 */
372 gen = b00;
373 }
374
375 switch (gen) {
376 case b00:
377 /* -X- setup code -X- */
378 p_ = p - 1.;
379 q_ = q - 1.;
380 c = (q * q_) / (p * p_); /* q(1-q) / p(1-p) */
381 t = (c == 1.) ? 0.5 : (1. - Math.sqrt(c)) / (1. - c); /* t = t_opt */
382 fp = Math.exp(p_ * Math.log(t));
383 fq = Math.exp(q_ * Math.log(1. - t)); /* f(t) = fa * fb */
384
385 p1 = t / p; /* 0 < X < t */
386 p2 = (1. - t) / q + p1; /* t < X < 1 */
387 /* -X- end of setup code -X- */
388 break;
389 case b01:
390 case b01inv:
391 /* -X- setup code -X- */
392 /* internal use of p and q */
393 if (p > q) {
394 /* swap p and q */
395 pint = q;
396 qint = p;
397 } else {
398 pint = p;
399 qint = q;
400 }
401
402 p_ = pint - 1.;
403 q_ = qint - 1.;
404 t = p_ / (pint - qint); /* one step Newton * start value t */
405 fq = Math.exp((q_ - 1.) * Math.log(1. - t));
406 fp = pint - (pint + q_) * t;
407 t -= (t - (1. - fp) * (1. - t) * fq / qint) / (1. - fp * fq);
408 fp = Math.exp(p_ * Math.log(t));
409 fq = Math.exp(q_ * Math.log(1. - t)); /* f(t) = fa * fb */
410 if (q_ <= 1.0) {
411 ml = (1. - fq) / t; /* ml = -m1 */
412 mu = q_ * t; /* mu = -m2 * t */
413 } else {
414 ml = q_;
415 mu = 1. - fq;
416 }
417 p1 = t / pint; /* 0 < X < t */
418 p2 = fq * (1. - t) / qint + p1; /* t < X < 1 */
419 /* -X- end of setup code -X- */
420 break;
421 case b1prs:
422 /* -X- setup code -X- */
423 p_ = p - 1.0;
424 q_ = q - 1.0;
425 s = p_ + q_;
426 m = p_ / s;
427
428 if (p_ > 1.0 || q_ > 1.0)
429 D = Math.sqrt(m * (1. - m) / (s - 1.0));
430
431 if (p_ <= 1.0) {
432 x2 = (Dl = m * 0.5);
433 x1 = z2 = f1 = ll = 0.0;
434 } else {
435 x2 = m - D;
436 x1 = x2 - D;
437 z2 = x2 * (1.0 - (1.0 - x2) / (s * D));
438 if (x1 <= 0.0 || (s - 6.0) * x2 - p_ + 3.0 > 0.0) {
439 x1 = z2;
440 x2 = (x1 + m) * 0.5;
441 Dl = m - x2;
442 } else {
443 Dl = D;
444 }
445 f1 = Math.exp(p_ * Math.log(x1 / m) + q_ * Math.log((1.0 - x1) / (1.0 - m)));
446 ll = x1 * (1.0 - x1) / (s * (m - x1)); /* z1 = x1 - ll */
447 }
448 f2 = Math.exp(p_ * Math.log(x2 / m) + q_ * Math.log((1.0 - x2) / (1.0 - m)));
449
450 if (q_ <= 1.) {
451 D = (1.0 - m) * 0.5;
452 x4 = 1.0 - D;
453 x5 = z4 = 1.0;
454 f5 = lr = 0.0;
455 } else {
456 x4 = m + D;
457 x5 = x4 + D;
458 z4 = x4 * (1.0 + (1.0 - x4) / (s * D));
459 if (x5 >= 1.0 || (s - 6.0) * x4 - p_ + 3.0 < 0.0) {
460 x5 = z4;
461 x4 = (m + x5) * 0.5;
462 D = x4 - m;
463 }
464 f5 = Math.exp(p_ * Math.log(x5 / m) + q_ * Math.log((1.0 - x5) / (1. - m)));
465 lr = x5 * (1.0 - x5) / (s * (x5 - m)); /* z5 = x5 + lr */
466 }
467 f4 = Math.exp(p_ * Math.log(x4 / m) + q_ * Math.log((1.0 - x4) / (1.0 - m)));
468
469 p1 = f2 * (Dl + Dl); /* x1 < X < m */
470 p2 = f4 * (D + D) + p1; /* m < X < x5 */
471 p3 = f1 * ll + p2; /* X < x1 */
472 p4 = f5 * lr + p3; /* x5 < X */
473 /* -X- end of setup code -X- */
474 break;
475 default:
476 throw new IllegalStateException();
477 }
478 }
479
480 private static boolean equalsDouble(double a, double b) {
481 if (a == b)
482 return true;
483 double absa = Math.abs(a);
484 double absb = Math.abs(b);
485 return Math.abs(a - b) <= Math.min(absa, absb) * Num.DBL_EPSILON;
486 }
487
488}
Extends the class ContinuousDistribution for the beta distribution.
Definition BetaDist.java:54
double inverseF(double u)
Returns the inverse distribution function .
BetaGen(RandomStream s, double alpha, double beta, double a, double b)
Creates a new beta generator with parameters alpha and beta, over the interval.
Definition BetaGen.java:64
BetaStratifiedRejectionGen(RandomStream s, RandomStream aux, double alpha, double beta, double a, double b)
Creates a beta random variate generator with parameters.
BetaStratifiedRejectionGen(RandomStream s, RandomStream aux, double alpha, double beta)
Creates a beta random variate generator with parameters alpha and beta, over the interval ,...
RandomStream getAuxStream()
Returns the auxiliary stream associated with this object.
static double nextDouble(RandomStream s, double alpha, double beta, double a, double b)
Generates a variate from the beta distribution with parameters.
BetaStratifiedRejectionGen(RandomStream s, RandomStream aux, BetaDist dist)
Creates a new generator for the distribution dist, using the given stream s and auxiliary stream aux.
double nextDouble()
Generates a random number from the continuous distribution contained in this object.
BetaStratifiedRejectionGen(RandomStream s, double alpha, double beta, double a, double b)
Creates a beta random variate generator with parameters.
BetaStratifiedRejectionGen(RandomStream s, BetaDist dist)
Same as BetaStratifiedRejectionGen(s, s,dist).
BetaStratifiedRejectionGen(RandomStream s, double alpha, double beta)
Creates a beta random variate generator with parameters alpha and beta, over the interval ,...
This interface defines the basic structures to handle multiple streams of uniform (pseudo)random numb...