1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.rng.sampling.distribution;
18
19 import org.apache.commons.rng.RandomProviderState;
20 import org.apache.commons.rng.RestorableUniformRandomProvider;
21 import org.apache.commons.rng.simple.RandomSource;
22 import org.junit.Assert;
23 import org.junit.Test;
24
25
26
27
28
29
30 public class PoissonSamplerCacheTest {
31
32
33
34
35 private final int minRange = (int) Math.floor(PoissonSampler.PIVOT - 2);
36
37 private final int maxRange = (int) Math.floor(PoissonSampler.PIVOT + 6);
38
39 private final int midRange = (minRange + maxRange) / 2;
40
41
42
43
44
45 @Test
46 public void testMinimumCachedMean() {
47 Assert.assertEquals(PoissonSampler.PIVOT, PoissonSamplerCache.getMinimumCachedMean(), 0);
48 }
49
50
51
52
53
54
55
56
57 @Test
58 public void testConstructorWithNoCache() {
59 final double min = 0;
60 final double max = PoissonSampler.PIVOT - 2;
61 PoissonSamplerCache cache = createPoissonSamplerCache(min, max);
62 Assert.assertFalse(cache.isValidRange());
63 Assert.assertEquals(0, cache.getMinMean(), 0);
64 Assert.assertEquals(0, cache.getMaxMean(), 0);
65 }
66
67
68
69
70
71
72 @Test
73 public void testConstructorWhenMaxEqualsMin() {
74 final double min = PoissonSampler.PIVOT + 2;
75 final double max = min;
76 PoissonSamplerCache cache = createPoissonSamplerCache(min, max);
77 Assert.assertTrue(cache.isValidRange());
78 Assert.assertEquals(min, cache.getMinMean(), 0);
79 Assert.assertEquals(Math.nextAfter(Math.floor(max) + 1, -1),
80 cache.getMaxMean(), 0);
81 }
82
83
84
85
86
87
88 @Test
89 public void testConstructorWhenMaxAboveMin() {
90 final double min = PoissonSampler.PIVOT + 2;
91 final double max = min + 10;
92 PoissonSamplerCache cache = createPoissonSamplerCache(min, max);
93 Assert.assertTrue(cache.isValidRange());
94 Assert.assertEquals(min, cache.getMinMean(), 0);
95 Assert.assertEquals(Math.nextAfter(Math.floor(max) + 1, -1),
96 cache.getMaxMean(), 0);
97 }
98
99
100
101
102 @Test(expected = IllegalArgumentException.class)
103 public void testConstructorThrowsWhenMaxIsLessThanMin() {
104 final double min = PoissonSampler.PIVOT;
105 final double max = Math.nextAfter(min, -1);
106 createPoissonSamplerCache(min, max);
107 }
108
109
110
111
112
113 @Test
114 public void testConstructorWhenMinBelow0() {
115 final double min = -1;
116 final double max = PoissonSampler.PIVOT + 2;
117 PoissonSamplerCache cache = createPoissonSamplerCache(min, max);
118 Assert.assertTrue(cache.isValidRange());
119 Assert.assertEquals(PoissonSampler.PIVOT, cache.getMinMean(), 0);
120 Assert.assertEquals(Math.nextAfter(Math.floor(max) + 1, -1),
121 cache.getMaxMean(), 0);
122 }
123
124
125
126
127
128 @Test
129 public void testConstructorWhenMaxBelow0() {
130 final double min = -10;
131 final double max = -1;
132 PoissonSamplerCache cache = createPoissonSamplerCache(min, max);
133 Assert.assertFalse(cache.isValidRange());
134 Assert.assertEquals(0, cache.getMinMean(), 0);
135 Assert.assertEquals(0, cache.getMaxMean(), 0);
136 }
137
138
139
140
141
142
143 @Test
144 public void testWithRangeConstructorWithNoCache() {
145 final double min = 0;
146 final double max = PoissonSampler.PIVOT - 2;
147 PoissonSamplerCache cache = createPoissonSamplerCache().withRange(min, max);
148 Assert.assertFalse(cache.isValidRange());
149 Assert.assertEquals(0, cache.getMinMean(), 0);
150 Assert.assertEquals(0, cache.getMaxMean(), 0);
151 }
152
153
154
155
156
157
158 @Test
159 public void testWithRangeConstructorWhenMaxEqualsMin() {
160 final double min = PoissonSampler.PIVOT + 2;
161 final double max = min;
162 PoissonSamplerCache cache = createPoissonSamplerCache().withRange(min, max);
163 Assert.assertTrue(cache.isValidRange());
164 Assert.assertEquals(min, cache.getMinMean(), 0);
165 Assert.assertEquals(Math.nextAfter(Math.floor(max) + 1, -1),
166 cache.getMaxMean(), 0);
167 }
168
169
170
171
172
173
174 @Test
175 public void testWithRangeConstructorWhenMaxAboveMin() {
176 final double min = PoissonSampler.PIVOT + 2;
177 final double max = min + 10;
178 PoissonSamplerCache cache = createPoissonSamplerCache().withRange(min, max);
179 Assert.assertTrue(cache.isValidRange());
180 Assert.assertEquals(min, cache.getMinMean(), 0);
181 Assert.assertEquals(Math.nextAfter(Math.floor(max) + 1, -1),
182 cache.getMaxMean(), 0);
183 }
184
185
186
187
188 @Test(expected = IllegalArgumentException.class)
189 public void testWithRangeConstructorThrowsWhenMaxIsLessThanMin() {
190 final double min = PoissonSampler.PIVOT;
191 final double max = Math.nextAfter(min, -1);
192 createPoissonSamplerCache().withRange(min, max);
193 }
194
195
196
197
198
199 @Test
200 public void testWithRangeConstructorWhenMinBelow0() {
201 final double min = -1;
202 final double max = PoissonSampler.PIVOT + 2;
203 PoissonSamplerCache cache = createPoissonSamplerCache().withRange(min, max);
204 Assert.assertTrue(cache.isValidRange());
205 Assert.assertEquals(PoissonSampler.PIVOT, cache.getMinMean(), 0);
206 Assert.assertEquals(Math.nextAfter(Math.floor(max) + 1, -1),
207 cache.getMaxMean(), 0);
208 }
209
210
211
212
213 @Test
214 public void testWithRangeConstructorWhenCacheHasNoCapcity() {
215 final double min = PoissonSampler.PIVOT + 2;
216 final double max = min + 10;
217 PoissonSamplerCache cache = createPoissonSamplerCache(0, 0).withRange(min, max);
218 Assert.assertTrue(cache.isValidRange());
219 Assert.assertEquals(min, cache.getMinMean(), 0);
220 Assert.assertEquals(Math.nextAfter(Math.floor(max) + 1, -1),
221 cache.getMaxMean(), 0);
222 }
223
224
225
226
227
228 @Test
229 public void testWithinRange() {
230 final double min = PoissonSampler.PIVOT + 10;
231 final double max = PoissonSampler.PIVOT + 20;
232 PoissonSamplerCache cache = createPoissonSamplerCache(min, max);
233
234 Assert.assertTrue(cache.withinRange(PoissonSampler.PIVOT - 1));
235 Assert.assertFalse(cache.withinRange(min - 1));
236 Assert.assertTrue(cache.withinRange(min));
237 Assert.assertTrue(cache.withinRange(max));
238 Assert.assertFalse(cache.withinRange(max + 10));
239 }
240
241
242
243
244
245
246
247
248 @Test(expected = IllegalArgumentException.class)
249 public void testCreatePoissonSamplerThrowsWithZeroMean() {
250 final RestorableUniformRandomProvider rng =
251 RandomSource.create(RandomSource.SPLIT_MIX_64);
252 final PoissonSamplerCache cache = createPoissonSamplerCache();
253 cache.createPoissonSampler(rng, 0);
254 }
255
256
257
258
259 @Test(expected = IllegalArgumentException.class)
260 public void testCreatePoissonSamplerThrowsWithNonIntegerMean() {
261 final RestorableUniformRandomProvider rng =
262 RandomSource.create(RandomSource.SPLIT_MIX_64);
263 final PoissonSamplerCache cache = createPoissonSamplerCache();
264 final double mean = Integer.MAX_VALUE + 1.0;
265 cache.createPoissonSampler(rng, mean);
266 }
267
268
269
270
271
272
273
274 @Test
275 public void testCanComputeSameSamplesAsPoissonSamplerWithFullRangeCache() {
276 checkComputeSameSamplesAsPoissonSampler(minRange,
277 maxRange);
278 }
279
280
281
282
283
284 @Test
285 public void testCanComputeSameSamplesAsPoissonSamplerWithNoCache() {
286 checkComputeSameSamplesAsPoissonSampler(0,
287 minRange - 2);
288 }
289
290
291
292
293
294 @Test
295 public void testCanComputeSameSamplesAsPoissonSamplerWithPartialCacheCoveringLowerRange() {
296 checkComputeSameSamplesAsPoissonSampler(minRange,
297 midRange);
298 }
299
300
301
302
303
304 @Test
305 public void testCanComputeSameSamplesAsPoissonSamplerWithPartialCacheCoveringUpperRange() {
306 checkComputeSameSamplesAsPoissonSampler(midRange,
307 maxRange);
308 }
309
310
311
312
313
314 @Test
315 public void testCanComputeSameSamplesAsPoissonSamplerWithCacheAboveTheUpperRange() {
316 checkComputeSameSamplesAsPoissonSampler(maxRange + 10,
317 maxRange + 20);
318 }
319
320
321
322
323
324
325
326
327 private void checkComputeSameSamplesAsPoissonSampler(int minMean,
328 int maxMean) {
329
330 final RestorableUniformRandomProvider rng1 =
331 RandomSource.create(RandomSource.WELL_19937_C);
332 final RandomProviderState state = rng1.saveState();
333 final RestorableUniformRandomProvider rng2 =
334 RandomSource.create(RandomSource.WELL_19937_C);
335 rng2.restoreState(state);
336
337
338 final PoissonSamplerCache cache =
339 createPoissonSamplerCache(minMean, maxMean);
340
341
342 for (int i = minRange; i <= maxRange; i++) {
343
344 testPoissonSamples(rng1, rng2, cache, i);
345
346 testPoissonSamples(rng1, rng2, cache, i + 0.5);
347 }
348 }
349
350
351
352
353
354
355
356
357 private static PoissonSamplerCache createPoissonSamplerCache(double minMean,
358 double maxMean) {
359 return new PoissonSamplerCache(minMean, maxMean);
360 }
361
362
363
364
365
366
367 private static PoissonSamplerCache createPoissonSamplerCache() {
368 return new PoissonSamplerCache(PoissonSampler.PIVOT,
369 PoissonSampler.PIVOT + 10);
370 }
371
372
373
374
375
376
377
378
379
380
381
382 private static void testPoissonSamples(
383 final RestorableUniformRandomProvider rng1,
384 final RestorableUniformRandomProvider rng2,
385 PoissonSamplerCache cache,
386 double mean) {
387 final DiscreteSampler s1 = PoissonSampler.of(rng1, mean);
388 final DiscreteSampler s2 = cache.createPoissonSampler(rng2, mean);
389 for (int j = 0; j < 10; j++) {
390 Assert.assertEquals(s1.sample(), s2.sample());
391 }
392 }
393
394
395
396
397
398 @Test
399 public void testCanComputeSameSamplesAsPoissonSamplerReusingCacheEntireRange() {
400 checkComputeSameSamplesAsPoissonSamplerReusingCache(midRange,
401 maxRange,
402 midRange,
403 maxRange);
404 }
405
406
407
408
409
410 @Test
411 public void testCanComputeSameSamplesAsPoissonSamplerReusingCacheNoRange() {
412 checkComputeSameSamplesAsPoissonSamplerReusingCache(midRange,
413 maxRange,
414 maxRange + 10,
415 maxRange + 20);
416 }
417
418
419
420
421
422 @Test
423 public void testCanComputeSameSamplesAsPoissonSamplerReusingCacheLowerRange() {
424 checkComputeSameSamplesAsPoissonSamplerReusingCache(midRange,
425 maxRange,
426 minRange,
427 midRange + 1);
428 }
429
430
431
432
433
434 @Test
435 public void testCanComputeSameSamplesAsPoissonSamplerReusingCacheUpperRange() {
436 checkComputeSameSamplesAsPoissonSamplerReusingCache(midRange,
437 maxRange,
438 maxRange - 1,
439 maxRange + 5);
440 }
441
442
443
444
445
446
447
448
449
450
451
452
453
454 private void checkComputeSameSamplesAsPoissonSamplerReusingCache(int minMean,
455 int maxMean,
456 int minMean2,
457 int maxMean2) {
458
459 final RestorableUniformRandomProvider rng1 =
460 RandomSource.create(RandomSource.WELL_19937_C);
461 final RandomProviderState state = rng1.saveState();
462 final RestorableUniformRandomProvider rng2 =
463 RandomSource.create(RandomSource.WELL_19937_C);
464
465
466 final PoissonSamplerCache cache =
467 createPoissonSamplerCache(minMean, maxMean);
468
469
470 for (int i = minMean; i <= maxMean; i++) {
471 cache.createPoissonSampler(rng1, i);
472 }
473
474 final PoissonSamplerCache cache2 = cache.withRange(minMean2, maxMean2);
475 Assert.assertTrue("WithRange cache is the same object", cache != cache2);
476
477 rng1.restoreState(state);
478 rng2.restoreState(state);
479
480
481
482 for (int i = minRange; i <= maxRange; i++) {
483
484 testPoissonSamples(rng1, rng2, cache2, i);
485
486 testPoissonSamples(rng1, rng2, cache2, i + 0.5);
487 }
488 }
489 }