1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.hipparchus.random;
23
24 import org.hipparchus.UnitTestUtils;
25 import org.hipparchus.distribution.continuous.BetaDistribution;
26 import org.hipparchus.distribution.continuous.EnumeratedRealDistribution;
27 import org.hipparchus.distribution.continuous.ExponentialDistribution;
28 import org.hipparchus.distribution.continuous.GammaDistribution;
29 import org.hipparchus.distribution.continuous.NormalDistribution;
30 import org.hipparchus.distribution.discrete.EnumeratedIntegerDistribution;
31 import org.hipparchus.distribution.discrete.PoissonDistribution;
32 import org.hipparchus.distribution.discrete.ZipfDistribution;
33 import org.hipparchus.exception.MathIllegalArgumentException;
34 import org.hipparchus.util.FastMath;
35 import org.junit.jupiter.api.Test;
36
37 import java.text.DecimalFormat;
38 import java.util.ArrayList;
39 import java.util.HashSet;
40 import java.util.List;
41
42 import static org.junit.jupiter.api.Assertions.assertEquals;
43 import static org.junit.jupiter.api.Assertions.assertFalse;
44 import static org.junit.jupiter.api.Assertions.assertThrows;
45 import static org.junit.jupiter.api.Assertions.assertTrue;
46 import static org.junit.jupiter.api.Assertions.fail;
47
48
49
50
51
52 public class RandomDataGeneratorTest {
53
54 public RandomDataGeneratorTest() {
55 randomData = RandomDataGenerator.of(new Well19937c());
56 randomData.setSeed(100);
57 }
58
59 protected final long smallSampleSize = 1000;
60 protected final double[] expected = { 250, 250, 250, 250 };
61 protected final int largeSampleSize = 10000;
62 private final String[] hex = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
63 "a", "b", "c", "d", "e", "f" };
64 protected RandomDataGenerator randomData = null;
65
66 @Test
67 void testNextIntExtremeValues() {
68 int x = randomData.nextInt(Integer.MIN_VALUE, Integer.MAX_VALUE);
69 int y = randomData.nextInt(Integer.MIN_VALUE, Integer.MAX_VALUE);
70 assertFalse(x == y);
71 }
72
73 @Test
74 void testNextLongExtremeValues() {
75 long x = randomData.nextLong(Long.MIN_VALUE, Long.MAX_VALUE);
76 long y = randomData.nextLong(Long.MIN_VALUE, Long.MAX_VALUE);
77 assertFalse(x == y);
78 }
79
80 @Test
81 void testNextUniformExtremeValues() {
82 double x = randomData.nextUniform(-Double.MAX_VALUE, Double.MAX_VALUE);
83 double y = randomData.nextUniform(-Double.MAX_VALUE, Double.MAX_VALUE);
84 assertFalse(x == y);
85 assertFalse(Double.isNaN(x));
86 assertFalse(Double.isNaN(y));
87 assertFalse(Double.isInfinite(x));
88 assertFalse(Double.isInfinite(y));
89 }
90
91 @Test
92 void testNextIntIAE() {
93 try {
94 randomData.nextInt(4, 3);
95 fail("MathIllegalArgumentException expected");
96 } catch (MathIllegalArgumentException ex) {
97
98 }
99 }
100
101 @Test
102 void testNextIntNegativeToPositiveRange() {
103 for (int i = 0; i < 5; i++) {
104 checkNextIntUniform(-3, 5);
105 checkNextIntUniform(-3, 6);
106 }
107 }
108
109 @Test
110 void testNextIntNegativeRange() {
111 for (int i = 0; i < 5; i++) {
112 checkNextIntUniform(-7, -4);
113 checkNextIntUniform(-15, -2);
114 checkNextIntUniform(Integer.MIN_VALUE + 1, Integer.MIN_VALUE + 12);
115 }
116 }
117
118 @Test
119 void testNextIntPositiveRange() {
120 for (int i = 0; i < 5; i++) {
121 checkNextIntUniform(0, 3);
122 checkNextIntUniform(2, 12);
123 checkNextIntUniform(1,2);
124 checkNextIntUniform(Integer.MAX_VALUE - 12, Integer.MAX_VALUE - 1);
125 }
126 }
127
128 private void checkNextIntUniform(int min, int max) {
129 final int len = max - min + 1;
130 final UnitTestUtils.Frequency<Integer> freq = new UnitTestUtils.Frequency<Integer>();
131 for (int i = 0; i < smallSampleSize; i++) {
132 final int value = randomData.nextInt(min, max);
133 assertTrue((value >= min) && (value <= max), "nextInt range");
134 freq.addValue(value);
135 }
136 final long[] observed = new long[len];
137 for (int i = 0; i < len; i++) {
138 observed[i] = freq.getCount(min + i);
139 }
140 final double[] expected = new double[len];
141 for (int i = 0; i < len; i++) {
142 expected[i] = 1d / len;
143 }
144
145 UnitTestUtils.customAssertChiSquareAccept(expected, observed, 0.001);
146 }
147
148 @Test
149 void testNextIntWideRange() {
150 int lower = -0x6543210F;
151 int upper = 0x456789AB;
152 int max = Integer.MIN_VALUE;
153 int min = Integer.MAX_VALUE;
154 for (int i = 0; i < 1000000; ++i) {
155 int r = randomData.nextInt(lower, upper);
156 max = FastMath.max(max, r);
157 min = FastMath.min(min, r);
158 assertTrue(r >= lower);
159 assertTrue(r <= upper);
160 }
161 double ratio = (((double) max) - ((double) min)) /
162 (((double) upper) - ((double) lower));
163 assertTrue(ratio > 0.99999);
164 }
165
166 @Test
167 void testNextLongIAE() {
168 try {
169 randomData.nextLong(4, 3);
170 fail("MathIllegalArgumentException expected");
171 } catch (MathIllegalArgumentException ex) {
172
173 }
174 }
175
176 @Test
177 void testNextLongNegativeToPositiveRange() {
178 for (int i = 0; i < 5; i++) {
179 checkNextLongUniform(-3, 5);
180 checkNextLongUniform(-3, 6);
181 }
182 }
183
184 @Test
185 void testNextLongNegativeRange() {
186 for (int i = 0; i < 5; i++) {
187 checkNextLongUniform(-7, -4);
188 checkNextLongUniform(-15, -2);
189 checkNextLongUniform(Long.MIN_VALUE + 1, Long.MIN_VALUE + 12);
190 }
191 }
192
193 @Test
194 void testNextLongPositiveRange() {
195 for (int i = 0; i < 5; i++) {
196 checkNextLongUniform(0, 3);
197 checkNextLongUniform(2, 12);
198 checkNextLongUniform(Long.MAX_VALUE - 12, Long.MAX_VALUE - 1);
199 }
200 }
201
202 private void checkNextLongUniform(long min, long max) {
203 final int len = ((int) (max - min)) + 1;
204 final UnitTestUtils.Frequency<Integer> freq = new UnitTestUtils.Frequency<Integer>();
205 for (int i = 0; i < smallSampleSize; i++) {
206 final long value = randomData.nextLong(min, max);
207 assertTrue((value >= min) && (value <= max),
208 "nextLong range: " + value + " " + min + " " + max);
209 freq.addValue((int)value);
210 }
211 final long[] observed = new long[len];
212 for (int i = 0; i < len; i++) {
213 observed[i] = freq.getCount((int) min + i);
214 }
215 final double[] expected = new double[len];
216 for (int i = 0; i < len; i++) {
217 expected[i] = 1d / len;
218 }
219
220 UnitTestUtils.customAssertChiSquareAccept(expected, observed, 0.01);
221 }
222
223 @Test
224 void testNextLongWideRange() {
225 long lower = -0x6543210FEDCBA987L;
226 long upper = 0x456789ABCDEF0123L;
227 long max = Long.MIN_VALUE;
228 long min = Long.MAX_VALUE;
229 for (int i = 0; i < 10000000; ++i) {
230 long r = randomData.nextLong(lower, upper);
231 max = FastMath.max(max, r);
232 min = FastMath.min(min, r);
233 assertTrue(r >= lower);
234 assertTrue(r <= upper);
235 }
236 double ratio = (((double) max) - ((double) min)) /
237 (((double) upper) - ((double) lower));
238 assertTrue(ratio > 0.99999);
239 }
240
241
242
243
244
245
246 @Test
247 void testNextPoisson() {
248 try {
249 randomData.nextPoisson(0);
250 fail("zero mean -- expecting MathIllegalArgumentException");
251 } catch (MathIllegalArgumentException ex) {
252
253 }
254 try {
255 randomData.nextPoisson(-1);
256 fail("negative mean supplied -- MathIllegalArgumentException expected");
257 } catch (MathIllegalArgumentException ex) {
258
259 }
260 try {
261 randomData.nextPoisson(0);
262 fail("0 mean supplied -- MathIllegalArgumentException expected");
263 } catch (MathIllegalArgumentException ex) {
264
265 }
266
267 final double mean = 4.0d;
268 final int len = 5;
269 PoissonDistribution poissonDistribution = new PoissonDistribution(mean);
270 final UnitTestUtils.Frequency<Integer> freq = new UnitTestUtils.Frequency<Integer>();
271 randomData.setSeed(1000);
272 for (int i = 0; i < largeSampleSize; i++) {
273 freq.addValue(randomData.nextPoisson(mean));
274 }
275 final long[] observed = new long[len];
276 for (int i = 0; i < len; i++) {
277 observed[i] = freq.getCount(i + 1);
278 }
279 final double[] expected = new double[len];
280 for (int i = 0; i < len; i++) {
281 expected[i] = poissonDistribution.probability(i + 1) * largeSampleSize;
282 }
283
284 UnitTestUtils.customAssertChiSquareAccept(expected, observed, 0.0001);
285 }
286
287 @Test
288 void testNextPoissonConsistency() {
289
290
291 for (int i = 1; i < 100; i++) {
292 checkNextPoissonConsistency(i);
293 }
294
295 for (int i = 1; i < 10; i++) {
296 checkNextPoissonConsistency(randomData.nextUniform(1, 1000));
297 }
298
299 for (int i = 1; i < 10; i++) {
300 checkNextPoissonConsistency(randomData.nextUniform(1000, 10000));
301 }
302 }
303
304
305
306
307
308
309
310
311
312
313 public void checkNextPoissonConsistency(double mean) {
314
315 final int sampleSize = 1000;
316 final int minExpectedCount = 7;
317 long maxObservedValue = 0;
318 final double alpha = 0.001;
319 UnitTestUtils.Frequency<Long> frequency = new UnitTestUtils.Frequency<Long>();
320 for (int i = 0; i < sampleSize; i++) {
321 long value = randomData.nextPoisson(mean);
322 if (value > maxObservedValue) {
323 maxObservedValue = value;
324 }
325 frequency.addValue(value);
326 }
327
328
329
330
331
332
333
334 PoissonDistribution poissonDistribution = new PoissonDistribution(mean);
335 int lower = 1;
336 while (poissonDistribution.cumulativeProbability(lower - 1) * sampleSize < minExpectedCount) {
337 lower++;
338 }
339 int upper = (int) (5 * mean);
340 while ((1 - poissonDistribution.cumulativeProbability(upper - 1)) * sampleSize < minExpectedCount) {
341 upper--;
342 }
343
344
345 int binWidth = 0;
346 boolean widthSufficient = false;
347 double lowerBinMass = 0;
348 double upperBinMass = 0;
349 while (!widthSufficient) {
350 binWidth++;
351 lowerBinMass = poissonDistribution.probability(lower - 1, lower + binWidth - 1);
352 upperBinMass = poissonDistribution.probability(upper - binWidth - 1, upper - 1);
353 widthSufficient = FastMath.min(lowerBinMass, upperBinMass) * sampleSize >= minExpectedCount;
354 }
355
356
357
358
359
360
361
362 List<Integer> binBounds = new ArrayList<Integer>();
363 binBounds.add(lower);
364 int bound = lower + binWidth;
365 while (bound < upper - binWidth) {
366 binBounds.add(bound);
367 bound += binWidth;
368 }
369 binBounds.add(upper);
370
371
372 final int binCount = binBounds.size() + 1;
373 long[] observed = new long[binCount];
374 double[] expected = new double[binCount];
375
376
377 observed[0] = 0;
378 for (int i = 0; i < lower; i++) {
379 observed[0] += frequency.getCount((long)i);
380 }
381 expected[0] = poissonDistribution.cumulativeProbability(lower - 1) * sampleSize;
382
383
384 observed[binCount - 1] = 0;
385 for (int i = upper; i <= maxObservedValue; i++) {
386 observed[binCount - 1] += frequency.getCount((long)i);
387 }
388 expected[binCount - 1] = (1 - poissonDistribution.cumulativeProbability(upper - 1)) * sampleSize;
389
390
391 for (int i = 1; i < binCount - 1; i++) {
392 observed[i] = 0;
393 for (int j = binBounds.get(i - 1); j < binBounds.get(i); j++) {
394 observed[i] += frequency.getCount((long)j);
395 }
396 expected[i] = (poissonDistribution.cumulativeProbability(binBounds.get(i) - 1) -
397 poissonDistribution.cumulativeProbability(binBounds.get(i - 1) -1)) * sampleSize;
398 }
399
400
401
402 if (UnitTestUtils.chiSquareTest(expected, observed) < alpha) {
403 StringBuilder msgBuffer = new StringBuilder();
404 DecimalFormat df = new DecimalFormat("#.##");
405 msgBuffer.append("Chisquare test failed for mean = ");
406 msgBuffer.append(mean);
407 msgBuffer.append(" p-value = ");
408 msgBuffer.append(UnitTestUtils.chiSquareTest(expected, observed));
409 msgBuffer.append(" chisquare statistic = ");
410 msgBuffer.append(UnitTestUtils.chiSquare(expected, observed));
411 msgBuffer.append(". \n");
412 msgBuffer.append("bin\t\texpected\tobserved\n");
413 for (int i = 0; i < expected.length; i++) {
414 msgBuffer.append("[");
415 msgBuffer.append(i == 0 ? 1: binBounds.get(i - 1));
416 msgBuffer.append(",");
417 msgBuffer.append(i == binBounds.size() ? "inf": binBounds.get(i));
418 msgBuffer.append(")");
419 msgBuffer.append("\t\t");
420 msgBuffer.append(df.format(expected[i]));
421 msgBuffer.append("\t\t");
422 msgBuffer.append(observed[i]);
423 msgBuffer.append("\n");
424 }
425 msgBuffer.append("This test can fail randomly due to sampling error with probability ");
426 msgBuffer.append(alpha);
427 msgBuffer.append(".");
428 fail(msgBuffer.toString());
429 }
430 }
431
432
433 @Test
434 void testNextHex() {
435 try {
436 randomData.nextHexString(-1);
437 fail("negative length supplied -- MathIllegalArgumentException expected");
438 } catch (MathIllegalArgumentException ex) {
439
440 }
441 try {
442 randomData.nextHexString(0);
443 fail("zero length supplied -- MathIllegalArgumentException expected");
444 } catch (MathIllegalArgumentException ex) {
445
446 }
447 String hexString = randomData.nextHexString(3);
448 if (hexString.length() != 3) {
449 fail("incorrect length for generated string");
450 }
451 hexString = randomData.nextHexString(1);
452 if (hexString.length() != 1) {
453 fail("incorrect length for generated string");
454 }
455 try {
456 hexString = randomData.nextHexString(0);
457 fail("zero length requested -- expecting MathIllegalArgumentException");
458 } catch (MathIllegalArgumentException ex) {
459
460 }
461 UnitTestUtils.Frequency<String> f = new UnitTestUtils.Frequency<String> ();
462 for (int i = 0; i < smallSampleSize; i++) {
463 hexString = randomData.nextHexString(100);
464 if (hexString.length() != 100) {
465 fail("incorrect length for generated string");
466 }
467 for (int j = 0; j < hexString.length(); j++) {
468 f.addValue(hexString.substring(j, j + 1));
469 }
470 }
471 double[] expected = new double[16];
472 long[] observed = new long[16];
473 for (int i = 0; i < 16; i++) {
474 expected[i] = (double) smallSampleSize * 100 / 16;
475 observed[i] = f.getCount(hex[i]);
476 }
477 UnitTestUtils.customAssertChiSquareAccept(expected, observed, 0.001);
478 }
479
480 @Test
481 void testNextUniformIAE() {
482 try {
483 randomData.nextUniform(4, 3);
484 fail("MathIllegalArgumentException expected");
485 } catch (MathIllegalArgumentException ex) {
486
487 }
488 try {
489 randomData.nextUniform(0, Double.POSITIVE_INFINITY);
490 fail("MathIllegalArgumentException expected");
491 } catch (MathIllegalArgumentException ex) {
492
493 }
494 try {
495 randomData.nextUniform(Double.NEGATIVE_INFINITY, 0);
496 fail("MathIllegalArgumentException expected");
497 } catch (MathIllegalArgumentException ex) {
498
499 }
500 try {
501 randomData.nextUniform(0, Double.NaN);
502 fail("MathIllegalArgumentException expected");
503 } catch (MathIllegalArgumentException ex) {
504
505 }
506 try {
507 randomData.nextUniform(Double.NaN, 0);
508 fail("MathIllegalArgumentException expected");
509 } catch (MathIllegalArgumentException ex) {
510
511 }
512 }
513
514 @Test
515 void testNextUniformUniformPositiveBounds() {
516 for (int i = 0; i < 5; i++) {
517 checkNextUniformUniform(0, 10);
518 }
519 }
520
521 @Test
522 void testNextUniformUniformNegativeToPositiveBounds() {
523 for (int i = 0; i < 5; i++) {
524 checkNextUniformUniform(-3, 5);
525 }
526 }
527
528 @Test
529 void testNextUniformUniformNegaiveBounds() {
530 for (int i = 0; i < 5; i++) {
531 checkNextUniformUniform(-7, -3);
532 }
533 }
534
535 @Test
536 void testNextUniformUniformMaximalInterval() {
537 for (int i = 0; i < 5; i++) {
538 checkNextUniformUniform(-Double.MAX_VALUE, Double.MAX_VALUE);
539 }
540 }
541
542 private void checkNextUniformUniform(double min, double max) {
543
544 final int binCount = 5;
545 final double binSize = max / binCount - min/binCount;
546 final double[] binBounds = new double[binCount - 1];
547 binBounds[0] = min + binSize;
548 for (int i = 1; i < binCount - 1; i++) {
549 binBounds[i] = binBounds[i - 1] + binSize;
550 }
551
552 UnitTestUtils.Frequency<Integer> freq = new UnitTestUtils.Frequency<Integer>();
553 for (int i = 0; i < smallSampleSize; i++) {
554 final double value = randomData.nextUniform(min, max);
555 assertTrue((value > min) && (value < max), "nextUniform range");
556
557 int j = 0;
558 while (j < binCount - 1 && value > binBounds[j]) {
559 j++;
560 }
561 freq.addValue(j);
562 }
563
564 final long[] observed = new long[binCount];
565 for (int i = 0; i < binCount; i++) {
566 observed[i] = freq.getCount(i);
567 }
568 final double[] expected = new double[binCount];
569 for (int i = 0; i < binCount; i++) {
570 expected[i] = 1d / binCount;
571 }
572
573 UnitTestUtils.customAssertChiSquareAccept(expected, observed, 0.01);
574 }
575
576
577 @Test
578 void testNextUniformExclusiveEndpoints() {
579 for (int i = 0; i < 1000; i++) {
580 double u = randomData.nextUniform(0.99, 1);
581 assertTrue(u > 0.99 && u < 1);
582 }
583 }
584
585
586 @Test
587 void testNextGaussian() {
588 try {
589 randomData.nextNormal(0, 0);
590 fail("zero sigma -- MathIllegalArgumentException expected");
591 } catch (MathIllegalArgumentException ex) {
592
593 }
594 double[] quartiles = UnitTestUtils.getDistributionQuartiles(new NormalDistribution(0,1));
595 long[] counts = new long[4];
596 randomData.setSeed(1000);
597 for (int i = 0; i < 1000; i++) {
598 double value = randomData.nextNormal(0, 1);
599 UnitTestUtils.updateCounts(value, counts, quartiles);
600 }
601 UnitTestUtils.customAssertChiSquareAccept(expected, counts, 0.001);
602 }
603
604
605 @Test
606 void testNextExponential() {
607 try {
608 randomData.nextExponential(-1);
609 fail("negative mean -- expecting MathIllegalArgumentException");
610 } catch (MathIllegalArgumentException ex) {
611
612 }
613 try {
614 randomData.nextExponential(0);
615 fail("zero mean -- expecting MathIllegalArgumentException");
616 } catch (MathIllegalArgumentException ex) {
617
618 }
619 double[] quartiles;
620 long[] counts;
621
622
623 quartiles = UnitTestUtils.getDistributionQuartiles(new ExponentialDistribution(1));
624 counts = new long[4];
625 randomData.setSeed(1000);
626 for (int i = 0; i < 1000; i++) {
627 double value = randomData.nextExponential(1);
628 UnitTestUtils.updateCounts(value, counts, quartiles);
629 }
630 UnitTestUtils.customAssertChiSquareAccept(expected, counts, 0.001);
631
632
633 quartiles = UnitTestUtils.getDistributionQuartiles(new ExponentialDistribution(5));
634 counts = new long[4];
635 randomData.setSeed(1000);
636 for (int i = 0; i < 1000; i++) {
637 double value = randomData.nextExponential(5);
638 UnitTestUtils.updateCounts(value, counts, quartiles);
639 }
640 UnitTestUtils.customAssertChiSquareAccept(expected, counts, 0.001);
641 }
642
643
644 @Test
645 void testConfig() {
646 randomData.setSeed(1000);
647 double v = randomData.nextUniform(0, 1);
648 randomData.setSeed(System.currentTimeMillis());
649 assertTrue(FastMath.abs(v - randomData.nextUniform(0, 1)) > 10E-12, "different seeds");
650 randomData.setSeed(1000);
651 assertEquals(v, randomData.nextUniform(0, 1), 10E-12, "same seeds");
652 }
653
654
655 @Test
656 void testNextSample() {
657 Object[][] c = { { "0", "1" }, { "0", "2" }, { "0", "3" },
658 { "0", "4" }, { "1", "2" }, { "1", "3" }, { "1", "4" },
659 { "2", "3" }, { "2", "4" }, { "3", "4" } };
660 long[] observed = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
661 double[] expected = { 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 };
662
663 HashSet<Object> cPop = new HashSet<Object>();
664 for (int i = 0; i < 5; i++) {
665 cPop.add(Integer.toString(i));
666 }
667
668 Object[] sets = new Object[10];
669 for (int i = 0; i < 10; i++) {
670 HashSet<Object> hs = new HashSet<Object>();
671 hs.add(c[i][0]);
672 hs.add(c[i][1]);
673 sets[i] = hs;
674 }
675
676 for (int i = 0; i < 1000; i++) {
677 Object[] cSamp = randomData.nextSample(cPop, 2);
678 observed[findSample(sets, cSamp)]++;
679 }
680
681
682
683
684
685 assertTrue(UnitTestUtils.chiSquare(expected, observed) < 27.88,
686 "chi-square test -- will fail about 1 in 1000 times");
687
688
689 HashSet<Object> hs = new HashSet<Object>();
690 hs.add("one");
691 Object[] one = randomData.nextSample(hs, 1);
692 String oneString = (String) one[0];
693 if ((one.length != 1) || !oneString.equals("one")) {
694 fail("bad sample for set size = 1, sample size = 1");
695 }
696
697
698 try {
699 one = randomData.nextSample(hs, 2);
700 fail("sample size > set size, expecting MathIllegalArgumentException");
701 } catch (MathIllegalArgumentException ex) {
702
703 }
704
705
706 try {
707 hs = new HashSet<Object>();
708 one = randomData.nextSample(hs, 0);
709 fail("n = k = 0, expecting MathIllegalArgumentException");
710 } catch (MathIllegalArgumentException ex) {
711
712 }
713 }
714
715 @SuppressWarnings("unchecked")
716 private int findSample(Object[] u, Object[] samp) {
717 for (int i = 0; i < u.length; i++) {
718 HashSet<Object> set = (HashSet<Object>) u[i];
719 HashSet<Object> sampSet = new HashSet<Object>();
720 for (int j = 0; j < samp.length; j++) {
721 sampSet.add(samp[j]);
722 }
723 if (set.equals(sampSet)) {
724 return i;
725 }
726 }
727 fail("sample not found:{" + samp[0] + "," + samp[1] + "}");
728 return -1;
729 }
730
731
732 @Test
733 void testNextPermutation() {
734 int[][] p = { { 0, 1, 2 }, { 0, 2, 1 }, { 1, 0, 2 }, { 1, 2, 0 },
735 { 2, 0, 1 }, { 2, 1, 0 } };
736 long[] observed = { 0, 0, 0, 0, 0, 0 };
737 double[] expected = { 100, 100, 100, 100, 100, 100 };
738
739 for (int i = 0; i < 600; i++) {
740 int[] perm = randomData.nextPermutation(3, 3);
741 observed[findPerm(p, perm)]++;
742 }
743
744 String[] labels = {"{0, 1, 2}", "{ 0, 2, 1 }", "{ 1, 0, 2 }",
745 "{ 1, 2, 0 }", "{ 2, 0, 1 }", "{ 2, 1, 0 }"};
746 UnitTestUtils.customAssertChiSquareAccept(labels, expected, observed, 0.001);
747
748
749 int[] perm = randomData.nextPermutation(1, 1);
750 if ((perm.length != 1) || (perm[0] != 0)) {
751 fail("bad permutation for n = 1, sample k = 1");
752
753
754 try {
755 perm = randomData.nextPermutation(2, 3);
756 fail("permutation k > n, expecting MathIllegalArgumentException");
757 } catch (MathIllegalArgumentException ex) {
758
759 }
760
761
762 try {
763 perm = randomData.nextPermutation(0, 0);
764 fail("permutation k = n = 0, expecting MathIllegalArgumentException");
765 } catch (MathIllegalArgumentException ex) {
766
767 }
768
769
770 try {
771 perm = randomData.nextPermutation(-1, -3);
772 fail("permutation k < n < 0, expecting MathIllegalArgumentException");
773 } catch (MathIllegalArgumentException ex) {
774
775 }
776
777 }
778 }
779
780 private int findPerm(int[][] p, int[] samp) {
781 for (int i = 0; i < p.length; i++) {
782 boolean good = true;
783 for (int j = 0; j < samp.length; j++) {
784 if (samp[j] != p[i][j]) {
785 good = false;
786 }
787 }
788 if (good) {
789 return i;
790 }
791 }
792 fail("permutation not found");
793 return -1;
794 }
795
796 @Test
797 void testNextBeta() {
798 double[] quartiles = UnitTestUtils.getDistributionQuartiles(new BetaDistribution(2,5));
799 long[] counts = new long[4];
800 randomData.setSeed(1000);
801 for (int i = 0; i < 1000; i++) {
802 double value = randomData.nextBeta(2, 5);
803 UnitTestUtils.updateCounts(value, counts, quartiles);
804 }
805 UnitTestUtils.customAssertChiSquareAccept(expected, counts, 0.001);
806 }
807
808 @Test
809 void testNextGamma() {
810 double[] quartiles;
811 long[] counts;
812
813
814 quartiles = UnitTestUtils.getDistributionQuartiles(new GammaDistribution(4, 2));
815 counts = new long[4];
816 randomData.setSeed(1000);
817 for (int i = 0; i < 1000; i++) {
818 double value = randomData.nextGamma(4, 2);
819 UnitTestUtils.updateCounts(value, counts, quartiles);
820 }
821 UnitTestUtils.customAssertChiSquareAccept(expected, counts, 0.001);
822
823
824 quartiles = UnitTestUtils.getDistributionQuartiles(new GammaDistribution(0.3, 3));
825 counts = new long[4];
826 randomData.setSeed(1000);
827 for (int i = 0; i < 1000; i++) {
828 double value = randomData.nextGamma(0.3, 3);
829 UnitTestUtils.updateCounts(value, counts, quartiles);
830 }
831 UnitTestUtils.customAssertChiSquareAccept(expected, counts, 0.001);
832 }
833
834 @Test
835 void testNextGamma2() {
836 final RandomDataGenerator randomDataGenerator = new RandomDataGenerator(1000);
837 final int sampleSize = 1000;
838 final double alpha = 0.001;
839 GammaDistribution dist = new GammaDistribution(3, 1);
840 double[] values = randomDataGenerator.nextDeviates(dist, sampleSize);
841 UnitTestUtils.customAssertGTest(dist, values, alpha);
842 dist = new GammaDistribution(.4, 2);
843 values = randomDataGenerator.nextDeviates(dist, sampleSize);
844 UnitTestUtils.customAssertGTest(dist, values, alpha);
845 }
846
847 @Test
848 void testNextBeta2() {
849 final double[] alphaBetas = {0.1, 1, 10, 100, 1000};
850 final RandomGenerator random = new Well1024a(0x7829862c82fec2dal);
851 final RandomDataGenerator randomDataGenerator = RandomDataGenerator.of(random);
852 final int sampleSize = 1000;
853 final double alphaCrit = 0.001;
854 for (final double alpha : alphaBetas) {
855 for (final double beta : alphaBetas) {
856 final BetaDistribution betaDistribution = new BetaDistribution(alpha, beta);
857 final double[] values = randomDataGenerator.nextDeviates(betaDistribution, sampleSize);
858 UnitTestUtils.customAssertGTest(betaDistribution, values, alphaCrit);
859 }
860 }
861 }
862
863 @Test
864 void testNextZipf() {
865 int sampleSize = 1000;
866
867 int[] numPointsValues = {
868 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 35, 40, 45, 50, 60, 70, 80, 90, 100
869 };
870 double[] exponentValues = {
871 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1, 2e-1, 5e-1,
872 1. - 1e-9, 1.0, 1. + 1e-9, 1.1, 1.2, 1.3, 1.5, 1.6, 1.7, 1.8, 2.0,
873 2.5, 3.0, 4., 5., 6., 7., 8., 9., 10., 20., 30., 100., 150.
874 };
875
876 for (int numPoints : numPointsValues) {
877 for (double exponent : exponentValues) {
878 double weightSum = 0.;
879 double[] weights = new double[numPoints];
880 for (int i = numPoints; i>=1; i-=1) {
881 weights[i-1] = Math.pow(i, -exponent);
882 weightSum += weights[i-1];
883 }
884
885
886 ZipfDistribution distribution = new ZipfDistribution(numPoints, exponent);
887 randomData.setSeed(1001);
888 double[] expectedCounts = new double[numPoints];
889 long[] observedCounts = new long[numPoints];
890 for (int i = 0; i < numPoints; i++) {
891 expectedCounts[i] = sampleSize * (weights[i]/weightSum);
892 }
893 int[] sample = randomData.nextDeviates(distribution,sampleSize);
894 for (int s : sample) {
895 observedCounts[s-1]++;
896 }
897 UnitTestUtils.customAssertChiSquareAccept(expectedCounts, observedCounts, 0.001);
898 }
899 }
900 }
901
902 @Test
903 void testNextSampleWithReplacement() {
904 final int sampleSize = 1000;
905 final double[] weights = {1, 2, 3, 4};
906 final int[] sample = randomData.nextSampleWithReplacement(sampleSize, weights);
907 final double[] expected = {sampleSize/10d, sampleSize/5d, 3*sampleSize/10d, 2*sampleSize/5d};
908 final long[] observed = {0, 0, 0, 0};
909 for (int i = 0; i < sampleSize; i++) {
910 observed[sample[i]]++;
911 }
912 UnitTestUtils.customAssertChiSquareAccept(new String[] { "0", "1", "2", "3"}, expected, observed, 0.01);
913 }
914
915 @Test
916 void testNextSampleWithReplacementPointMass() {
917 final int sampleSize = 2;
918 double[] weights = {1};
919 final int[] expected = new int[] {0, 0};
920 UnitTestUtils.customAssertEquals(expected, randomData.nextSampleWithReplacement(sampleSize, weights));
921 weights = new double[] {1, 0};
922 UnitTestUtils.customAssertEquals(expected, randomData.nextSampleWithReplacement(sampleSize, weights));
923 }
924
925 @Test
926 void testNextSampleWithReplacementAllZeroWeights() {
927 assertThrows(MathIllegalArgumentException.class, () -> {
928 final double[] weights = {0, 0, 0};
929 randomData.nextSampleWithReplacement(1, weights);
930 });
931 }
932
933 @Test
934 void testNextSampleWithReplacementNegativeWeights() {
935 assertThrows(MathIllegalArgumentException.class, () -> {
936 final double[] weights = {-1, 1, 0};
937 randomData.nextSampleWithReplacement(1, weights);
938 });
939 }
940
941 @Test
942 void testNextSampleWithReplacement0SampleSize() {
943 final double[] weights = {1, 0};
944 final int[] expected = {};
945 UnitTestUtils.customAssertEquals(expected, randomData.nextSampleWithReplacement(0, weights));
946 }
947
948 @Test
949 void testNextSampleWithReplacementNegativeSampleSize() {
950 assertThrows(MathIllegalArgumentException.class, () -> {
951 final double[] weights = {1, 0};
952 randomData.nextSampleWithReplacement(-1, weights);
953 });
954 }
955
956 @Test
957 void testNextSampleWithReplacementNaNWeights() {
958 assertThrows(MathIllegalArgumentException.class, () -> {
959 final double[] weights = {1, Double.NaN};
960 randomData.nextSampleWithReplacement(0, weights);
961 });
962 }
963
964 @Test
965 void testNextDeviateEnumeratedIntegerDistribution() {
966 final int sampleSize = 1000;
967 final int[] data = new int[] {0, 1, 1, 2, 2, 2};
968 final EnumeratedIntegerDistribution dist = new EnumeratedIntegerDistribution(data);
969 final int[] sample = randomData.nextDeviates(dist, sampleSize);
970 final double[] expected = {sampleSize/6d, sampleSize/3d, sampleSize/2d};
971 final long[] observed = {0, 0, 0};
972 for (int i = 0; i < sampleSize; i++) {
973 observed[sample[i]]++;
974 }
975 UnitTestUtils.customAssertChiSquareAccept(new String[] { "0", "1", "2"}, expected, observed, 0.01);
976 }
977
978 @Test
979 void testNextDeviateEnumeratedRealDistribution() {
980 final int sampleSize = 1000;
981 final double[] data = new double[] {0, 1, 1, 2, 2, 2};
982 final EnumeratedRealDistribution dist = new EnumeratedRealDistribution(data);
983 final double[] sample = randomData.nextDeviates(dist, sampleSize);
984 final double[] expected = {sampleSize/6d, sampleSize/3d, sampleSize/2d};
985 final long[] observed = {0, 0, 0};
986 for (int i = 0; i < sampleSize; i++) {
987 observed[(int)sample[i]]++;
988 }
989 UnitTestUtils.customAssertChiSquareAccept(new String[] { "0", "1", "2"}, expected, observed, 0.01);
990 }
991
992 }