SSJ API Documentation
Stochastic Simulation in Java
Loading...
Searching...
No Matches
PoissonTIACGen.java
1/*
2 * Class: PoissonTIACGen
3 * Description: random variate generators having the Poisson distribution
4 using the tabulated inversion combined with the acceptance
5 complement method
6 * Environment: Java
7 * Software: SSJ
8 * Copyright (C) 2001 Pierre L'Ecuyer and Universite de Montreal
9 * Organization: DIRO, Universite de Montreal
10 * @author
11 * @since
12 *
13 *
14 * Licensed under the Apache License, Version 2.0 (the "License");
15 * you may not use this file except in compliance with the License.
16 * You may obtain a copy of the License at
17 *
18 * http://www.apache.org/licenses/LICENSE-2.0
19 *
20 * Unless required by applicable law or agreed to in writing, software
21 * distributed under the License is distributed on an "AS IS" BASIS,
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 * See the License for the specific language governing permissions and
24 * limitations under the License.
25 *
26 */
27package umontreal.ssj.randvar;
28
29import umontreal.ssj.probdist.*;
30import umontreal.ssj.rng.*;
31
44public class PoissonTIACGen extends PoissonGen {
45
46 private double[] pp = new double[36];
47 private int[] llref = { 0 };
48 private static double[] staticPP = new double[36];
49 private static int[] staticllref = { 0 };
50 // Used by TIAC, avoid creating a table upon each call.
51
57 public PoissonTIACGen(RandomStream s, double lambda) {
58 super(s, null);
59 init(lambda);
60 }
61
67 super(s, dist);
68 init(dist.getLambda());
69 }
70
71 public int nextInt() {
72 return tiac(stream, lambda, pp, llref);
73 }
74
79 public static int nextInt(RandomStream s, double lambda) {
80 return tiac(s, lambda, staticPP, staticllref);
81 }
82
83 private void init(double lam) {
84 setParams(lam);
85 for (int i = 0; i < pp.length; i++)
86 pp[i] = 0.0;
87 }
88
89 /*
90 * **************************************************************************
91 * GENERATION METHOD : Tabulated Inversion combined with * Acceptance Complement
92 * * *
93 *****************************************************************************
94 * * METHOD : - samples a random number from the Poisson distribution with *
95 * parameter lambda > 0. * Tabulated Inversion for lambda < 10 * Acceptance
96 * Complement for lambda >= 10. *
97 * ---------------------------------------------------------------------------*
98 * * CODE REFERENCE : The code is adapted from UNURAN * UNURAN (c) 2000 W.
99 * Hoermann & J. Leydold, Institut f. Statistik, WU Wien * *
100 * ---------------------------------------------------------------------------*
101 * * REFERENCE: - J.H. Ahrens, U. Dieter (1982): Computer generation of *
102 * Poisson deviates from modified normal distributions, * ACM Trans. Math.
103 * Software 8, 163-179. * * Implemented by R. Kremer, August 1990 * Revised by
104 * E. Stadlober, April 1992 *
105 *****************************************************************************
106 * WinRand (c) 1995 Ernst Stadlober, Institut fuer Statistitk, TU Graz *
107 *****************************************************************************
108 * UNURAN :
109 ****************************************************************************/
110 private static int tiac(RandomStream s, double lambda, double[] pp, int[] llref) {
111 final double a0 = -0.5000000002;
112 final double a1 = 0.3333333343;
113 final double a2 = -0.2499998565;
114 final double a3 = 0.1999997049;
115 final double a4 = -0.1666848753;
116 final double a5 = 0.1428833286;
117 final double a6 = -0.1241963125;
118 final double a7 = 0.1101687109;
119 final double a8 = -0.1142650302;
120 final double a9 = 0.1055093006;
121 // factorial for 0 <= k <= 9
122 final int fac[] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };
123
124 double u;
125 int i;
126 if (lambda < 10) {
127 int m = lambda > 1 ? (int) lambda : 1;
128 int ll = llref[0];
129 double p0, q, p;
130 p0 = q = p = Math.exp(-lambda);
131 int k = 0;
132 while (true) {
133 u = s.nextDouble(); // Step u. Uniform sample
134 k = 0;
135 if (u <= p0)
136 return k;
137
138 // Step T. Table comparison
139 if (ll != 0) {
140 i = (u > 0.458) ? Math.min(ll, m) : 1;
141 for (k = i; k <= ll; k++)
142 if (u <= pp[k])
143 return k;
144 if (ll == 35)
145 continue;
146 }
147
148 // Step C. Creation of new prob.
149 for (k = ll + 1; k <= 35; k++) {
150 p *= lambda / (double) k;
151 q += p;
152 pp[k] = q;
153 if (u <= q) {
154 ll = k;
155 llref[0] = ll;
156 return k;
157 }
158 }
159 ll = 35;
160 llref[0] = ll;
161 }
162 } else { // lambda > 10, we use acceptance complement
163 double sl = Math.sqrt(lambda);
164 double d = 6 * lambda * lambda;
165 int l = (int) (lambda - 1.1484);
166
167 // Step P. Preparations for steps Q and H
168 double omega = 0.3989423 / sl;
169 double b1 = 0.416666666667e-1 / lambda;
170 double b2 = 0.3 * b1 * b1;
171 double c3 = 0.1428571 * b1 * b2;
172 double c2 = b2 - 15.0 * c3;
173 double c1 = b1 - 6.0 * b2 + 45.0 * c3;
174 double c0 = 1.0 - b1 + 3.0 * b2 - 15.0 * c3;
175 double c = 0.1069 / lambda;
176
177 double t, g, lambda_k;
178 double gx, gy, px, py, x, xx, delta, v;
179 int sign;
180
181 double e;
182 int k;
183
184 // Step N. Normal sample
185 // We don't use NormalGen because this could create bad side effects.
186 // With NormalGen, the behavior of this method would depend
187 // on the selected static method of NormalGen.
188 t = NormalDist.inverseF(0, 1, s.nextDouble());
189 g = lambda + sl * t;
190
191 if (g >= 0) {
192 k = (int) g;
193 // Step I. Immediate acceptance
194 if (k >= l)
195 return k;
196 // Step S. Squeeze acceptance
197 u = s.nextDouble();
198 lambda_k = lambda - k;
199 if (d * u >= lambda_k * lambda_k * lambda_k)
200 return k;
201
202 // FUNCTION F
203 if (k < 10) {
204 px = -lambda;
205 py = Math.exp(k * Math.log(lambda)) / fac[k];
206 } else { // k >= 10
207 delta = 0.83333333333e-1 / (double) k;
208 delta = delta - 4.8 * delta * delta * delta * (1. - 1. / (3.5 * k * k));
209 v = (lambda_k) / (double) k;
210 if (Math.abs(v) > 0.25)
211 px = k * Math.log(1. + v) - lambda_k - delta;
212 else {
213 px = k * v * v;
214 px *= ((((((((a9 * v + a8) * v + a7) * v + a6) * v + a5) * v + a4) * v + a3) * v + a2) * v + a1) * v
215 + a0;
216 px -= delta;
217 }
218 py = 0.3989422804 / Math.sqrt((double) k);
219 }
220 x = (0.5 - lambda_k) / sl;
221 xx = x * x;
222 gx = -0.5 * xx;
223 gy = omega * (((c3 * xx + c2) * xx + c1) * xx + c0);
224 // end FUNCTION F
225
226 // Step Q. Quotient acceptance
227 if (gy * (1.0 - u) <= py * Math.exp(px - gx))
228 return k;
229 }
230
231 // Step E. Double exponential sample
232 while (true) {
233 do {
234 e = -Math.log(s.nextDouble());
235 u = s.nextDouble();
236 u = u + u - 1;
237 sign = u < 0 ? -1 : 1;
238 t = 1.8 + e * sign;
239 } while (t <= -0.6744);
240 k = (int) (lambda + sl * t);
241 lambda_k = lambda - k;
242
243 // FUNCTION F
244 if (k < 10) {
245 px = -lambda;
246 py = Math.exp(k * Math.log(lambda)) / fac[k];
247 } else { // k >= 10
248 delta = 0.83333333333e-1 / (double) k;
249 delta = delta - 4.8 * delta * delta * delta * (1.0 - 1.0 / (3.5 * k * k));
250 v = lambda_k / (double) k;
251 if (Math.abs(v) > 0.25)
252 px = k * Math.log(1. + v) - lambda_k - delta;
253 else {
254 px = k * v * v;
255 px *= ((((((((a9 * v + a8) * v + a7) * v + a6) * v + a5) * v + a4) * v + a3) * v + a2) * v + a1) * v
256 + a0;
257 px -= delta;
258 }
259 py = 0.3989422804 / Math.sqrt((double) k);
260 }
261 x = (0.5 - lambda_k) / sl;
262 xx = x * x;
263 gx = -0.5 * xx;
264 gy = omega * (((c3 * xx + c2) * xx + c1) * xx + c0);
265 // end FUNCTION F
266
267 // Step H. Hat acceptance
268 if (c * sign * u <= py * Math.exp(px + e) - gy * Math.exp(gx + e))
269 return k;
270 }
271 }
272 }
273
274 static {
275 for (int i = 0; i < staticPP.length; i++)
276 staticPP[i] = 0.0;
277 }
278}
Extends the class DiscreteDistributionInt for the Poisson distribution slaw00a  (page 325) with mean.
PoissonGen(RandomStream s, double lambda)
Creates a Poisson random variate generator with parameter.
void setParams(double lam)
Sets the parameter lam of this object.
int nextInt()
Generates a random number (an integer) from the discrete distribution contained in this object.
PoissonTIACGen(RandomStream s, PoissonDist dist)
Creates a new random variate generator using the Poisson distribution dist and stream s.
static int nextInt(RandomStream s, double lambda)
A static method for generating a random variate from a Poisson distribution with parameter = lambda.
PoissonTIACGen(RandomStream s, double lambda)
Creates a Poisson random variate generator with parameter.
This interface defines the basic structures to handle multiple streams of uniform (pseudo)random numb...