1 package org.textensor.stochdiff.numeric.stochastic;
2
3 import org.textensor.report.E;
4 import org.textensor.stochdiff.numeric.BaseCalc.distribution_t;
5 import static org.textensor.stochdiff.numeric.BaseCalc.distribution_t.*;
6
7
8 public final class NGoTable {
9
10 double lnp;
11 int nparticle;
12
13 double[] cprob;
14 int ncprob;
15
16 distribution_t mode;
17
18 public NGoTable(int n, double lnp0, distribution_t mode) {
19 lnp = lnp0;
20 nparticle = n;
21 this.mode = mode;
22
23 double p = Math.exp(lnp);
24 double q = 1. - p;
25 double lnq = Math.log(q);
26
27
28
29
30 switch (mode) {
31 case BINOMIAL: {
32 BinomialTable btab = BinomialTable.getTable();
33
34
35
36
37
38
39 double[] wk = new double[n+1];
40
41 double c = 0.;
42 ncprob = -1;
43 for (int i = n; i >= 0; i--) {
44 double pn = Math.exp(i * lnp + (n-i) * lnq) * btab.ncm(n, i);
45 c += pn;
46 wk[i] = c;
47 if (ncprob < 0 && c > 1.e-11) {
48 ncprob = i;
49 }
50 }
51
52
53
54
55
56
57
58 if (Math.abs(1. - c) > 1.e-11) {
59 E.error("cumulative probability miscount? "+ c +
60 " for n, p, nkept " + n + " " + p + " " + ncprob);
61 }
62
63
64
65
66
67
68 cprob = new double[ncprob+1];
69 for (int i = 0; i < ncprob; i++) {
70 cprob[i] = 1. - wk[i+1];
71 }
72 cprob[ncprob] = 2.;
73
74
75 }; break;
76
77 case POISSON: {
78
79 double lambda = n * Math.exp(lnp0);
80 double emlambda = Math.exp(-1. * lambda);
81
82
83 ncprob = -1;
84 int nmax = 4 * n + 20;
85 double[] wk = new double[nmax];
86
87 double lampnbynfac = 1.;
88
89 for (int i = 0; i < nmax; i++) {
90 double pn = emlambda * lampnbynfac;
91 lampnbynfac *= (lambda/ (i+1));
92
93 wk[i] = pn;
94 if (i > lambda && ncprob < 0 && pn < 1.e-11) {
95 ncprob = i;
96 }
97
98 }
99
100 if (ncprob < 0) {
101 E.error("never terminated tabled? " + n + " " + lambda + " " + emlambda * lampnbynfac);
102 }
103
104
105
106
107
108
109
110
111 cprob = new double[ncprob+1];
112 cprob[0] = wk[0];
113 for (int i = 1; i < ncprob; i++) {
114 cprob[i] = cprob[i-1] + wk[i];
115 }
116 cprob[ncprob] = 2.;
117
118 }; break;
119
120 default:
121
122 E.warning("unrecognized distribution " + mode);
123 }
124
125
126
127 }
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154 public int nGoSeq(double r) {
155 int ret = 0;
156 while (cprob[ret] < r) {
157 ret += 1;
158 }
159 return ret;
160 }
161
162
163 public int nGoBS(double r) {
164 int bot = 0;
165 int top = ncprob;
166
167 while (top - bot > 1) {
168 int ic = (bot + top) / 2;
169 if (r < cprob[ic]) {
170 top = ic;
171 } else {
172 bot = ic;
173 }
174 }
175 return bot;
176 }
177
178
179
180 public int nGo(double r) {
181 int ret = 0;
182 while (cprob[ret] < r) {
183 ret++;
184 }
185 return ret;
186 }
187
188
189
190
191
192
193
194
195
196
197
198
199 public double rnGo(double r) {
200 double ret = 0.;
201 if (r < cprob[0]) {
202 ret = r / cprob[0];
203
204 } else {
205 int ia = 1;
206 while (cprob[ia] < r) {
207 ia++;
208 }
209 ret = ia + (r - cprob[ia-1]) / (cprob[ia] - cprob[ia-1]);
210 }
211
212 return ret;
213 }
214
215
216
217
218
219
220
221
222
223
224
225 public void print() {
226 StringBuffer sb = new StringBuffer();
227 sb.append("n=" + nparticle + " p="+ Math.exp(lnp) +
228 " njmax=" + ncprob + " mode=" + mode + "\n");
229 sb.append("p(n < i): ");
230 for (int i = 0; i < ncprob; i++) {
231 sb.append(cprob[i] + ", ");
232 }
233 sb.append("\n");
234
235 sb.append("ngo, rngo for ten equally spaced randoms starting at 0.001 ");
236 for (int i = 0; i < 10; i++) {
237 double r = 0.001 + 0.99 * (i / 9.);
238 sb.append("(" + nGo(r) + ", " + rnGo(r) + ") ");
239 }
240 sb.append("\n");
241 System.out.println(sb.toString());
242 }
243
244
245
246
247
248 private void lookupCheck() {
249 for (int i = 0; i <= 50; i++) {
250 double r = (1. * i) / 50.;
251 int n1 = nGoSeq(r);
252 int n2 = nGoBS(r);
253 if (n1 != n2) {
254 E.error("different results in lookup check " + nparticle + " " +
255 Math.exp(lnp) + " " + n1 + " " + n2);
256 }
257 }
258 }
259
260
261
262
263 private long lookupTimeSeq() {
264 long t0 = System.currentTimeMillis();
265 double rnx = 1.e7;
266 int njt = 0;
267 for (int i = 0; i < rnx; i++) {
268 njt += nGoSeq(i / rnx);
269 }
270 long t1 = System.currentTimeMillis();
271 return (t1 - t0);
272 }
273
274 private long lookupTimeBS() {
275 long t0 = System.currentTimeMillis();
276 double rnx = 1.e7;
277 int njt = 0;
278 for (int i = 0; i < rnx; i++) {
279 njt += nGoBS(i / rnx);
280 }
281 long t1 = System.currentTimeMillis();
282 return (t1 - t0);
283 }
284
285 private long lookupTimeSwitch() {
286 long t0 = System.currentTimeMillis();
287 double rnx = 1.e7;
288 int njt = 0;
289 for (int i = 0; i < rnx; i++) {
290 njt += nGo(i / rnx);
291 }
292 long t1 = System.currentTimeMillis();
293 return (t1 - t0);
294 }
295
296
297
298 private static void lookupTest() {
299 long tstot = 0;
300 long tbtot = 0;
301 long tctot = 0;
302
303 distribution_t m = BINOMIAL;
304
305 for (int i = 10; i <= 90; i+= 10) {
306 for (int ip = -6; ip < -1; ip++) {
307 double lp = 2. * ip;
308 NGoTable jc = new NGoTable(i, lp, m);
309
310 jc.lookupCheck();
311
312 long ts = jc.lookupTimeSeq();
313 long tb = jc.lookupTimeBS();
314 long tc = jc.lookupTimeSwitch();
315
316 tstot += ts;
317 tbtot += tb;
318 tctot += tc;
319 double p = Math.exp(lp);
320 System.out.println("timings " + i + " " + p + " " +
321 ts + " " + tb + " " + tc);
322
323 }
324 }
325
326 E.info("seq " + tstot + " bs " + tbtot + " " + tctot);
327 }
328
329
330 private static void dumpExamples() {
331 new NGoTable(10, Math.log(0.1), BINOMIAL).print();
332 new NGoTable(10, Math.log(0.1), POISSON).print();
333
334 new NGoTable(90, Math.log(0.1), BINOMIAL).print();
335 new NGoTable(90, Math.log(0.1), POISSON).print();
336
337 new NGoTable(10, Math.log(0.01), BINOMIAL).print();
338 new NGoTable(10, Math.log(0.01), POISSON).print();
339
340 new NGoTable(90, Math.log(0.01), BINOMIAL).print();
341 new NGoTable(90, Math.log(0.01), POISSON).print();
342
343 new NGoTable(10, Math.log(0.001), BINOMIAL).print();
344 new NGoTable(10, Math.log(0.001), POISSON).print();
345
346 new NGoTable(90, Math.log(0.001), BINOMIAL).print();
347 new NGoTable(90, Math.log(0.001), POISSON).print();
348
349 new NGoTable(10, Math.log(0.0001), BINOMIAL).print();
350 new NGoTable(10, Math.log(0.0001), POISSON).print();
351
352 new NGoTable(90, Math.log(0.0001), BINOMIAL).print();
353 new NGoTable(90, Math.log(0.0001), POISSON).print();
354 }
355
356
357 public static void main(String[] argv) {
358 dumpExamples();
359
360 }
361
362
363 }