1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.commons.math.random;
17
18 import junit.framework.Test;
19 import junit.framework.TestSuite;
20 import java.security.NoSuchProviderException;
21 import java.security.NoSuchAlgorithmException;
22 import java.util.HashSet;
23
24 import org.apache.commons.math.RetryTestCase;
25 import org.apache.commons.math.stat.Frequency;
26 import org.apache.commons.math.stat.inference.ChiSquareTestImpl;
27 import org.apache.commons.math.stat.descriptive.SummaryStatistics;
28
29 /***
30 * Test cases for the RandomData class.
31 *
32 * @version $Revision: 1.17 $ $Date: 2004/10/08 05:08:19 $
33 */
34
35 public final class RandomDataTest extends RetryTestCase {
36
37 public RandomDataTest(String name) {
38 super(name);
39 }
40
41 private long smallSampleSize = 1000;
42 private double[] expected = {250,250,250,250};
43 private int largeSampleSize = 10000;
44 private int tolerance = 50;
45 private String[] hex =
46 {"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};
47 private RandomDataImpl randomData = new RandomDataImpl();
48 private ChiSquareTestImpl testStatistic = new ChiSquareTestImpl();
49
50 public void setUp() {
51 }
52
53 public static Test suite() {
54 TestSuite suite = new TestSuite(RandomDataTest.class);
55 suite.setName("RandomData Tests");
56 return suite;
57 }
58
59 /*** test dispersion and failure modes for nextInt() */
60 public void testNextInt() {
61 try {
62 int x = randomData.nextInt(4,3);
63 fail("IllegalArgumentException expected");
64 } catch (IllegalArgumentException ex) {
65 ;
66 }
67 Frequency freq = new Frequency();
68 int value = 0;
69 for (int i=0;i<smallSampleSize;i++) {
70 value = randomData.nextInt(0,3);
71 assertTrue("nextInt range",(value >= 0) && (value <= 3));
72 freq.addValue(value);
73 }
74 long[] observed = new long[4];
75 for (int i=0; i<4; i++) {
76 observed[i] = freq.getCount(i);
77 }
78
79
80
81
82 assertTrue("chi-square test -- will fail about 1 in 1000 times",
83 testStatistic.chiSquare(expected,observed) < 16.27);
84 }
85
86 /*** test dispersion and failure modes for nextLong() */
87 public void testNextLong() {
88 try {
89 long x = randomData.nextLong(4,3);
90 fail("IllegalArgumentException expected");
91 } catch (IllegalArgumentException ex) {
92 ;
93 }
94 Frequency freq = new Frequency();
95 long value = 0;
96 for (int i=0;i<smallSampleSize;i++) {
97 value = randomData.nextLong(0,3);
98 assertTrue("nextInt range",(value >= 0) && (value <= 3));
99 freq.addValue(value);
100 }
101 long[] observed = new long[4];
102 for (int i=0; i<4; i++) {
103 observed[i] = freq.getCount(i);
104 }
105
106
107
108
109 assertTrue("chi-square test -- will fail about 1 in 1000 times",
110 testStatistic.chiSquare(expected,observed) < 16.27);
111 }
112
113 /*** test dispersion and failure modes for nextSecureLong() */
114 public void testNextSecureLong() {
115 try {
116 long x = randomData.nextSecureLong(4,3);
117 fail("IllegalArgumentException expected");
118 } catch (IllegalArgumentException ex) {
119 ;
120 }
121 Frequency freq = new Frequency();
122 long value = 0;
123 for (int i=0;i<smallSampleSize;i++) {
124 value = randomData.nextSecureLong(0,3);
125 assertTrue("nextInt range",(value >= 0) && (value <= 3));
126 freq.addValue(value);
127 }
128 long[] observed = new long[4];
129 for (int i=0; i<4; i++) {
130 observed[i] = freq.getCount(i);
131 }
132
133
134
135
136 assertTrue("chi-square test -- will fail about 1 in 1000 times",
137 testStatistic.chiSquare(expected,observed) < 16.27);
138 }
139
140 /*** test dispersion and failure modes for nextSecureInt() */
141 public void testNextSecureInt() {
142 try {
143 long x = randomData.nextSecureInt(4,3);
144 fail("IllegalArgumentException expected");
145 } catch (IllegalArgumentException ex) {
146 ;
147 }
148 Frequency freq = new Frequency();
149 int value = 0;
150 for (int i=0;i<smallSampleSize;i++) {
151 value = randomData.nextSecureInt(0,3);
152 assertTrue("nextInt range",(value >= 0) && (value <= 3));
153 freq.addValue(value);
154 }
155 long[] observed = new long[4];
156 for (int i=0; i<4; i++) {
157 observed[i] = freq.getCount(i);
158 }
159
160
161
162
163 assertTrue("chi-square test -- will fail about 1 in 1000 times",
164 testStatistic.chiSquare(expected,observed) < 16.27);
165 }
166
167 /***
168 * Make sure that empirical distribution of random Poisson(4)'s
169 * has P(X <= 5) close to actual cumulative Poisson probablity
170 * and that nextPoisson fails when mean is non-positive
171 * TODO: replace with statistical test, adding test stat to TestStatistic
172 */
173 public void testNextPoisson() {
174 try {
175 long x = randomData.nextPoisson(0);
176 fail("zero mean -- expecting IllegalArgumentException");
177 } catch (IllegalArgumentException ex) {
178 ;
179 }
180 Frequency f = new Frequency();
181 long v = 0;
182 for (int i = 0; i<largeSampleSize; i++) {
183 try {
184 f.addValue(randomData.nextPoisson(4.0d));
185 } catch (Exception ex) {
186 fail(ex.getMessage());
187 }
188 }
189 long cumFreq = f.getCount(0) + f.getCount(1) + f.getCount(2) +
190 f.getCount(3) + f.getCount(4) + f.getCount(5);
191 long sumFreq = f.getSumFreq();
192 double cumPct =
193 new Double(cumFreq).doubleValue()/new Double(sumFreq).doubleValue();
194 assertEquals("cum Poisson(4)",cumPct,0.7851,0.2);
195 try {
196 long x = randomData.nextPoisson(-1);
197 fail("negative mean supplied -- IllegalArgumentException expected");
198 } catch (IllegalArgumentException ex) {
199 ;
200 }
201 try {
202 long x = randomData.nextPoisson(0);
203 fail("0 mean supplied -- IllegalArgumentException expected");
204 } catch (IllegalArgumentException ex) {
205 ;
206 }
207
208 }
209
210 /*** test dispersion and failute modes for nextHex() */
211 public void testNextHex() {
212 try {
213 String x = randomData.nextHexString(-1);
214 fail("negative length supplied -- IllegalArgumentException expected");
215 } catch (IllegalArgumentException ex) {
216 ;
217 }
218 try {
219 String x = randomData.nextHexString(0);
220 fail("zero length supplied -- IllegalArgumentException expected");
221 } catch (IllegalArgumentException ex) {
222 ;
223 }
224 String hexString = randomData.nextHexString(3);
225 if (hexString.length() != 3) {
226 fail("incorrect length for generated string");
227 }
228 hexString = randomData.nextHexString(1);
229 if (hexString.length() != 1) {
230 fail("incorrect length for generated string");
231 }
232 try {
233 hexString = randomData.nextHexString(0);
234 fail("zero length requested -- expecting IllegalArgumentException");
235 } catch (IllegalArgumentException ex) {
236 ;
237 }
238 if (hexString.length() != 1) {
239 fail("incorrect length for generated string");
240 }
241 Frequency f = new Frequency();
242 for (int i = 0; i < smallSampleSize; i++) {
243 hexString = randomData.nextHexString(100);
244 if (hexString.length() != 100) {
245 fail("incorrect length for generated string");
246 }
247 for (int j = 0; j < hexString.length(); j++) {
248 f.addValue(hexString.substring(j,j+1));
249 }
250 }
251 double[] expected = new double[16];
252 long[] observed = new long[16];
253 for (int i = 0; i < 16; i++) {
254 expected[i] = (double)smallSampleSize*100/(double)16;
255 observed[i] = f.getCount(hex[i]);
256 }
257
258
259
260 assertTrue("chi-square test -- will fail about 1 in 1000 times",
261 testStatistic.chiSquare(expected,observed) < 37.70);
262 }
263
264 /*** test dispersion and failute modes for nextHex() */
265 public void testNextSecureHex() {
266 try {
267 String x = randomData.nextSecureHexString(-1);
268 fail("negative length -- IllegalArgumentException expected");
269 } catch (IllegalArgumentException ex) {
270 ;
271 }
272 try {
273 String x = randomData.nextSecureHexString(0);
274 fail("zero length -- IllegalArgumentException expected");
275 } catch (IllegalArgumentException ex) {
276 ;
277 }
278 String hexString = randomData.nextSecureHexString(3);
279 if (hexString.length() != 3) {
280 fail("incorrect length for generated string");
281 }
282 hexString = randomData.nextSecureHexString(1);
283 if (hexString.length() != 1) {
284 fail("incorrect length for generated string");
285 }
286 try {
287 hexString = randomData.nextSecureHexString(0);
288 fail("zero length requested -- expecting IllegalArgumentException");
289 } catch (IllegalArgumentException ex) {
290 ;
291 }
292 if (hexString.length() != 1) {
293 fail("incorrect length for generated string");
294 }
295 Frequency f = new Frequency();
296 for (int i = 0; i < smallSampleSize; i++) {
297 hexString = randomData.nextSecureHexString(100);
298 if (hexString.length() != 100) {
299 fail("incorrect length for generated string");
300 }
301 for (int j = 0; j < hexString.length(); j++) {
302 f.addValue(hexString.substring(j,j+1));
303 }
304 }
305 double[] expected = new double[16];
306 long[] observed = new long[16];
307 for (int i = 0; i < 16; i++) {
308 expected[i] = (double)smallSampleSize*100/(double)16;
309 observed[i] = f.getCount(hex[i]);
310 }
311
312
313
314 assertTrue("chi-square test -- will fail about 1 in 1000 times",
315 testStatistic.chiSquare(expected,observed) < 37.70);
316 }
317
318 /*** test failure modes and dispersion of nextUniform() */
319 public void testNextUniform() {
320 try {
321 double x = randomData.nextUniform(4,3);
322 fail("IllegalArgumentException expected");
323 } catch (IllegalArgumentException ex) {
324 ;
325 }
326 try {
327 double x = randomData.nextUniform(3,3);
328 fail("IllegalArgumentException expected");
329 } catch (IllegalArgumentException ex) {
330 ;
331 }
332 double[] expected = {500,500};
333 long[] observed = {0,0};
334 double lower = -1d;
335 double upper = 20d;
336 double midpoint = (lower + upper)/2d;
337 double result = 0;
338 for (int i = 0; i < 1000; i++) {
339 result = randomData.nextUniform(lower,upper);
340 if ((result == lower) || (result == upper)) {
341 fail("generated value equal to an endpoint: " + result);
342 }
343 if (result < midpoint) {
344 observed[0]++;
345 } else {
346 observed[1]++;
347 }
348 }
349
350
351
352 assertTrue("chi-square test -- will fail about 1 in 1000 times",
353 testStatistic.chiSquare(expected,observed) < 10.83);
354 }
355
356 /*** test failure modes and distribution of nextGaussian() */
357 public void testNextGaussian() {
358 try {
359 double x = randomData.nextGaussian(0,0);
360 fail("zero sigma -- IllegalArgumentException expected");
361 } catch (IllegalArgumentException ex) {
362 ;
363 }
364 SummaryStatistics u = SummaryStatistics.newInstance();
365 for (int i = 0; i<largeSampleSize; i++) {
366 u.addValue(randomData.nextGaussian(0,1));
367 }
368 double xbar = u.getMean();
369 double s = u.getStandardDeviation();
370 double n = (double) u.getN();
371
372
373
374 assertTrue(Math.abs(xbar)/(s/Math.sqrt(n))< 3.29);
375 }
376
377 /*** test failure modes and distribution of nextExponential() */
378 public void testNextExponential() {
379 try {
380 double x = randomData.nextExponential(-1);
381 fail("negative mean -- expecting IllegalArgumentException");
382 } catch (IllegalArgumentException ex) {
383 ;
384 }
385 assertEquals("0 mean", 0,randomData.nextExponential(0),10E-8);
386 long cumFreq = 0;
387 double v = 0;
388 for (int i = 0; i < largeSampleSize; i++) {
389 v = randomData.nextExponential(1);
390 assertTrue("exponential deviate postive", v > 0);
391 if (v < 2) cumFreq++;
392 }
393
394
395
396
397 assertEquals("exponential cumulative distribution",
398 (double)cumFreq/(double)largeSampleSize,0.8646647167633873,.2);
399 }
400
401 /*** test reseeding, algorithm/provider games */
402 public void testConfig() throws NoSuchProviderException,
403 NoSuchAlgorithmException{
404 randomData.reSeed(1000);
405 double v = randomData.nextUniform(0,1);
406 randomData.reSeed();
407 assertTrue("different seeds",
408 Math.abs(v - randomData.nextUniform(0,1)) > 10E-12);
409 randomData.reSeed(1000);
410 assertEquals("same seeds",v,randomData.nextUniform(0,1),10E-12);
411 randomData.reSeedSecure(1000);
412 String hex = randomData.nextSecureHexString(40);
413 randomData.reSeedSecure();
414 assertTrue("different seeds",
415 !hex.equals(randomData.nextSecureHexString(40)));
416 randomData.reSeedSecure(1000);
417 assertTrue("same seeds",
418 !hex.equals(randomData.nextSecureHexString(40)));
419
420
421
422
423 randomData.setSecureAlgorithm("SHA1PRNG","SUN");
424 assertTrue("different seeds",
425 !hex.equals(randomData.nextSecureHexString(40)));
426 try {
427 randomData.setSecureAlgorithm("NOSUCHTHING","SUN");
428 fail("expecting NoSuchAlgorithmException");
429 } catch (NoSuchAlgorithmException ex) {
430 ;
431 }
432
433 try {
434 randomData.setSecureAlgorithm("SHA1PRNG","NOSUCHPROVIDER");
435 fail("expecting NoSuchProviderException");
436 } catch (NoSuchProviderException ex) {
437 ;
438 }
439
440
441 RandomDataImpl rd = new RandomDataImpl();
442 rd.reSeed(100);
443 double ret = rd.nextLong(1,2);
444 RandomDataImpl rd2 = new RandomDataImpl();
445 rd2.reSeedSecure(2000);
446 ret = rd2.nextSecureLong(1,2);
447 rd = new RandomDataImpl();
448 rd.reSeed();
449 ret = rd.nextLong(1,2);
450 rd2 = new RandomDataImpl();
451 rd2.reSeedSecure();
452 ret = rd2.nextSecureLong(1,2);
453 }
454
455 /*** tests for nextSample() sampling from Collection */
456 public void testNextSample() {
457 Object[][] c = {{"0","1"},{"0","2"},{"0","3"},{"0","4"},{"1","2"},
458 {"1","3"},{"1","4"},{"2","3"},{"2","4"},{"3","4"}};
459 long[] observed = {0,0,0,0,0,0,0,0,0,0};
460 double[] expected = {100,100,100,100,100,100,100,100,100,100};
461
462 HashSet cPop = new HashSet();
463 for (int i = 0; i < 5; i++) {
464 cPop.add(Integer.toString(i));
465 }
466
467 Object[] sets = new Object[10];
468 for (int i = 0; i < 10; i ++) {
469 HashSet hs = new HashSet();
470 hs.add(c[i][0]);
471 hs.add(c[i][1]);
472 sets[i] = hs;
473 }
474
475 for (int i = 0; i < 1000; i ++) {
476 Object[] cSamp = randomData.nextSample(cPop,2);
477 observed[findSample(sets,cSamp)]++;
478 }
479
480
481
482
483 assertTrue("chi-square test -- will fail about 1 in 1000 times",
484 testStatistic.chiSquare(expected,observed) < 27.88);
485
486
487 HashSet hs = new HashSet();
488 hs.add("one");
489 Object[] one = randomData.nextSample(hs,1);
490 String oneString = (String) one[0];
491 if ((one.length != 1) || !oneString.equals("one")){
492 fail("bad sample for set size = 1, sample size = 1");
493 }
494
495
496 try {
497 one = randomData.nextSample(hs,2);
498 fail("sample size > set size, expecting IllegalArgumentException");
499 } catch (IllegalArgumentException ex) {
500 ;
501 }
502
503
504 try {
505 hs = new HashSet();
506 one = randomData.nextSample(hs,0);
507 fail("n = k = 0, expecting IllegalArgumentException");
508 } catch (IllegalArgumentException ex) {
509 ;
510 }
511 }
512
513 private int findSample(Object[] u, Object[] samp) {
514 int result = -1;
515 for (int i = 0; i < u.length; i++) {
516 HashSet set = (HashSet) u[i];
517 HashSet sampSet = new HashSet();
518 for (int j = 0; j < samp.length; j++) {
519 sampSet.add(samp[j]);
520 }
521 if (set.equals(sampSet)) {
522 return i;
523 }
524 }
525 fail("sample not found:{" + samp[0] + "," + samp[1] + "}");
526 return -1;
527 }
528
529 /*** tests for nextPermutation */
530 public void testNextPermutation() {
531 int[][] p = {{0,1,2},{0,2,1},{1,0,2},{1,2,0},{2,0,1},{2,1,0}};
532 long[] observed = {0,0,0,0,0,0};
533 double[] expected = {100,100,100,100,100,100};
534
535 for (int i = 0; i < 600; i++) {
536 int[] perm = randomData.nextPermutation(3,3);
537 observed[findPerm(p,perm)]++;
538 }
539
540
541
542
543 assertTrue("chi-square test -- will fail about 1 in 1000 times",
544 testStatistic.chiSquare(expected,observed) < 20.52);
545
546
547 int[] perm = randomData.nextPermutation(1,1);
548 if ((perm.length != 1) || (perm[0] != 0)){
549 fail("bad permutation for n = 1, sample k = 1");
550
551
552 try {
553 perm = randomData.nextPermutation(2,3);
554 fail("permutation k > n, expecting IllegalArgumentException");
555 } catch (IllegalArgumentException ex) {
556 ;
557 }
558
559
560 try {
561 perm = randomData.nextPermutation(0,0);
562 fail("permutation k = n = 0, expecting IllegalArgumentException");
563 } catch (IllegalArgumentException ex) {
564 ;
565 }
566 }
567 }
568
569 private int findPerm(int[][] p, int[] samp) {
570 int result = -1;
571 for (int i = 0; i < p.length; i++) {
572 boolean good = true;
573 for (int j = 0; j < samp.length; j++) {
574 if (samp[j] != p[i][j]) {
575 good = false;
576 }
577 }
578 if (good) {
579 return i;
580 }
581 }
582 fail("permutation not found");
583 return -1;
584 }
585 }
586