2
* Licensed to the Apache Software Foundation (ASF) under one or more
3
* contributor license agreements. See the NOTICE file distributed with
4
* this work for additional information regarding copyright ownership.
5
* The ASF licenses this file to You under the Apache License, Version 2.0
6
* (the "License"); you may not use this file except in compliance with
7
* the License. You may obtain a copy of the License at
9
* http://www.apache.org/licenses/LICENSE-2.0
11
* Unless required by applicable law or agreed to in writing, software
12
* distributed under the License is distributed on an "AS IS" BASIS,
13
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
* See the License for the specific language governing permissions and
15
* limitations under the License.
17
package org.apache.commons.math.random;
19
import junit.framework.Test;
20
import junit.framework.TestSuite;
21
import java.security.NoSuchProviderException;
22
import java.security.NoSuchAlgorithmException;
23
import java.util.HashSet;
25
import org.apache.commons.math.RetryTestCase;
26
import org.apache.commons.math.stat.Frequency;
27
import org.apache.commons.math.stat.inference.ChiSquareTestImpl;
28
import org.apache.commons.math.stat.descriptive.SummaryStatistics;
31
* Test cases for the RandomData class.
33
* @version $Revision: 610789 $ $Date: 2008-01-10 06:46:49 -0700 (Thu, 10 Jan 2008) $
36
public class RandomDataTest extends RetryTestCase {
38
public RandomDataTest(String name) {
40
randomData = new RandomDataImpl();
43
protected long smallSampleSize = 1000;
44
protected double[] expected = {250,250,250,250};
45
protected int largeSampleSize = 10000;
46
private String[] hex =
47
{"0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"};
48
protected RandomDataImpl randomData = null;
49
protected ChiSquareTestImpl testStatistic = new ChiSquareTestImpl();
54
public static Test suite() {
55
TestSuite suite = new TestSuite(RandomDataTest.class);
56
suite.setName("RandomData Tests");
60
public void testNextIntExtremeValues() {
61
int x = randomData.nextInt(Integer.MIN_VALUE, Integer.MAX_VALUE);
62
int y = randomData.nextInt(Integer.MIN_VALUE, Integer.MAX_VALUE);
66
public void testNextLongExtremeValues() {
67
long x = randomData.nextLong(Long.MIN_VALUE, Long.MAX_VALUE);
68
long y = randomData.nextLong(Long.MIN_VALUE, Long.MAX_VALUE);
72
/** test dispersion and failure modes for nextInt() */
73
public void testNextInt() {
75
randomData.nextInt(4,3);
76
fail("IllegalArgumentException expected");
77
} catch (IllegalArgumentException ex) {
80
Frequency freq = new Frequency();
82
for (int i=0;i<smallSampleSize;i++) {
83
value = randomData.nextInt(0,3);
84
assertTrue("nextInt range",(value >= 0) && (value <= 3));
87
long[] observed = new long[4];
88
for (int i=0; i<4; i++) {
89
observed[i] = freq.getCount(i);
92
/* Use ChiSquare dist with df = 4-1 = 3, alpha = .001
93
* Change to 11.34 for alpha = .01
95
assertTrue("chi-square test -- will fail about 1 in 1000 times",
96
testStatistic.chiSquare(expected,observed) < 16.27);
99
/** test dispersion and failure modes for nextLong() */
100
public void testNextLong() {
102
randomData.nextLong(4,3);
103
fail("IllegalArgumentException expected");
104
} catch (IllegalArgumentException ex) {
107
Frequency freq = new Frequency();
109
for (int i=0;i<smallSampleSize;i++) {
110
value = randomData.nextLong(0,3);
111
assertTrue("nextInt range",(value >= 0) && (value <= 3));
112
freq.addValue(value);
114
long[] observed = new long[4];
115
for (int i=0; i<4; i++) {
116
observed[i] = freq.getCount(i);
119
/* Use ChiSquare dist with df = 4-1 = 3, alpha = .001
120
* Change to 11.34 for alpha = .01
122
assertTrue("chi-square test -- will fail about 1 in 1000 times",
123
testStatistic.chiSquare(expected,observed) < 16.27);
126
/** test dispersion and failure modes for nextSecureLong() */
127
public void testNextSecureLong() {
129
randomData.nextSecureLong(4,3);
130
fail("IllegalArgumentException expected");
131
} catch (IllegalArgumentException ex) {
134
Frequency freq = new Frequency();
136
for (int i=0;i<smallSampleSize;i++) {
137
value = randomData.nextSecureLong(0,3);
138
assertTrue("nextInt range",(value >= 0) && (value <= 3));
139
freq.addValue(value);
141
long[] observed = new long[4];
142
for (int i=0; i<4; i++) {
143
observed[i] = freq.getCount(i);
146
/* Use ChiSquare dist with df = 4-1 = 3, alpha = .001
147
* Change to 11.34 for alpha = .01
149
assertTrue("chi-square test -- will fail about 1 in 1000 times",
150
testStatistic.chiSquare(expected,observed) < 16.27);
153
/** test dispersion and failure modes for nextSecureInt() */
154
public void testNextSecureInt() {
156
randomData.nextSecureInt(4,3);
157
fail("IllegalArgumentException expected");
158
} catch (IllegalArgumentException ex) {
161
Frequency freq = new Frequency();
163
for (int i=0;i<smallSampleSize;i++) {
164
value = randomData.nextSecureInt(0,3);
165
assertTrue("nextInt range",(value >= 0) && (value <= 3));
166
freq.addValue(value);
168
long[] observed = new long[4];
169
for (int i=0; i<4; i++) {
170
observed[i] = freq.getCount(i);
173
/* Use ChiSquare dist with df = 4-1 = 3, alpha = .001
174
* Change to 11.34 for alpha = .01
176
assertTrue("chi-square test -- will fail about 1 in 1000 times",
177
testStatistic.chiSquare(expected,observed) < 16.27);
181
* Make sure that empirical distribution of random Poisson(4)'s
182
* has P(X <= 5) close to actual cumulative Poisson probablity
183
* and that nextPoisson fails when mean is non-positive
184
* TODO: replace with statistical test, adding test stat to TestStatistic
186
public void testNextPoisson() {
188
randomData.nextPoisson(0);
189
fail("zero mean -- expecting IllegalArgumentException");
190
} catch (IllegalArgumentException ex) {
193
Frequency f = new Frequency();
194
for (int i = 0; i<largeSampleSize; i++) {
196
f.addValue(randomData.nextPoisson(4.0d));
197
} catch (Exception ex) {
198
fail(ex.getMessage());
201
long cumFreq = f.getCount(0) + f.getCount(1) + f.getCount(2) +
202
f.getCount(3) + f.getCount(4) + f.getCount(5);
203
long sumFreq = f.getSumFreq();
205
new Double(cumFreq).doubleValue()/new Double(sumFreq).doubleValue();
206
assertEquals("cum Poisson(4)",cumPct,0.7851,0.2);
208
randomData.nextPoisson(-1);
209
fail("negative mean supplied -- IllegalArgumentException expected");
210
} catch (IllegalArgumentException ex) {
214
randomData.nextPoisson(0);
215
fail("0 mean supplied -- IllegalArgumentException expected");
216
} catch (IllegalArgumentException ex) {
222
/** test dispersion and failute modes for nextHex() */
223
public void testNextHex() {
225
randomData.nextHexString(-1);
226
fail("negative length supplied -- IllegalArgumentException expected");
227
} catch (IllegalArgumentException ex) {
231
randomData.nextHexString(0);
232
fail("zero length supplied -- IllegalArgumentException expected");
233
} catch (IllegalArgumentException ex) {
236
String hexString = randomData.nextHexString(3);
237
if (hexString.length() != 3) {
238
fail("incorrect length for generated string");
240
hexString = randomData.nextHexString(1);
241
if (hexString.length() != 1) {
242
fail("incorrect length for generated string");
245
hexString = randomData.nextHexString(0);
246
fail("zero length requested -- expecting IllegalArgumentException");
247
} catch (IllegalArgumentException ex) {
250
if (hexString.length() != 1) {
251
fail("incorrect length for generated string");
253
Frequency f = new Frequency();
254
for (int i = 0; i < smallSampleSize; i++) {
255
hexString = randomData.nextHexString(100);
256
if (hexString.length() != 100) {
257
fail("incorrect length for generated string");
259
for (int j = 0; j < hexString.length(); j++) {
260
f.addValue(hexString.substring(j,j+1));
263
double[] expected = new double[16];
264
long[] observed = new long[16];
265
for (int i = 0; i < 16; i++) {
266
expected[i] = (double)smallSampleSize*100/(double)16;
267
observed[i] = f.getCount(hex[i]);
269
/* Use ChiSquare dist with df = 16-1 = 15, alpha = .001
270
* Change to 30.58 for alpha = .01
272
assertTrue("chi-square test -- will fail about 1 in 1000 times",
273
testStatistic.chiSquare(expected,observed) < 37.70);
276
/** test dispersion and failute modes for nextHex() */
277
public void testNextSecureHex() {
279
randomData.nextSecureHexString(-1);
280
fail("negative length -- IllegalArgumentException expected");
281
} catch (IllegalArgumentException ex) {
285
randomData.nextSecureHexString(0);
286
fail("zero length -- IllegalArgumentException expected");
287
} catch (IllegalArgumentException ex) {
290
String hexString = randomData.nextSecureHexString(3);
291
if (hexString.length() != 3) {
292
fail("incorrect length for generated string");
294
hexString = randomData.nextSecureHexString(1);
295
if (hexString.length() != 1) {
296
fail("incorrect length for generated string");
299
hexString = randomData.nextSecureHexString(0);
300
fail("zero length requested -- expecting IllegalArgumentException");
301
} catch (IllegalArgumentException ex) {
304
if (hexString.length() != 1) {
305
fail("incorrect length for generated string");
307
Frequency f = new Frequency();
308
for (int i = 0; i < smallSampleSize; i++) {
309
hexString = randomData.nextSecureHexString(100);
310
if (hexString.length() != 100) {
311
fail("incorrect length for generated string");
313
for (int j = 0; j < hexString.length(); j++) {
314
f.addValue(hexString.substring(j,j+1));
317
double[] expected = new double[16];
318
long[] observed = new long[16];
319
for (int i = 0; i < 16; i++) {
320
expected[i] = (double)smallSampleSize*100/(double)16;
321
observed[i] = f.getCount(hex[i]);
323
/* Use ChiSquare dist with df = 16-1 = 15, alpha = .001
324
* Change to 30.58 for alpha = .01
326
assertTrue("chi-square test -- will fail about 1 in 1000 times",
327
testStatistic.chiSquare(expected,observed) < 37.70);
330
/** test failure modes and dispersion of nextUniform() */
331
public void testNextUniform() {
333
randomData.nextUniform(4,3);
334
fail("IllegalArgumentException expected");
335
} catch (IllegalArgumentException ex) {
339
randomData.nextUniform(3,3);
340
fail("IllegalArgumentException expected");
341
} catch (IllegalArgumentException ex) {
344
double[] expected = {500,500};
345
long[] observed = {0,0};
348
double midpoint = (lower + upper)/2d;
350
for (int i = 0; i < 1000; i++) {
351
result = randomData.nextUniform(lower,upper);
352
if ((result == lower) || (result == upper)) {
353
fail("generated value equal to an endpoint: " + result);
355
if (result < midpoint) {
361
/* Use ChiSquare dist with df = 2-1 = 1, alpha = .001
362
* Change to 6.64 for alpha = .01
364
assertTrue("chi-square test -- will fail about 1 in 1000 times",
365
testStatistic.chiSquare(expected,observed) < 10.83);
368
/** test exclusive endpoints of nextUniform **/
369
public void testNextUniformExclusiveEndpoints() {
370
for (int i = 0; i < 1000; i++) {
371
double u = randomData.nextUniform(0.99, 1);
372
assertTrue(u > 0.99 && u < 1);
376
/** test failure modes and distribution of nextGaussian() */
377
public void testNextGaussian() {
379
randomData.nextGaussian(0,0);
380
fail("zero sigma -- IllegalArgumentException expected");
381
} catch (IllegalArgumentException ex) {
384
SummaryStatistics u = new SummaryStatistics();
385
for (int i = 0; i<largeSampleSize; i++) {
386
u.addValue(randomData.nextGaussian(0,1));
388
double xbar = u.getMean();
389
double s = u.getStandardDeviation();
390
double n = (double) u.getN();
391
/* t-test at .001-level TODO: replace with externalized t-test, with
392
* test statistic defined in TestStatistic
394
assertTrue(Math.abs(xbar)/(s/Math.sqrt(n))< 3.29);
397
/** test failure modes and distribution of nextExponential() */
398
public void testNextExponential() {
400
randomData.nextExponential(-1);
401
fail("negative mean -- expecting IllegalArgumentException");
402
} catch (IllegalArgumentException ex) {
405
assertEquals("0 mean", 0,randomData.nextExponential(0),10E-8);
408
for (int i = 0; i < largeSampleSize; i++) {
409
v = randomData.nextExponential(1);
410
assertTrue("exponential deviate postive", v > 0);
411
if (v < 2) cumFreq++;
413
/* TODO: Replace with a statistical test, with statistic added to
414
* TestStatistic. Check below compares observed cumulative distribution
415
* evaluated at 2 with exponential CDF
417
assertEquals("exponential cumulative distribution",
418
(double)cumFreq/(double)largeSampleSize,0.8646647167633873,.2);
421
/** test reseeding, algorithm/provider games */
422
public void testConfig() throws NoSuchProviderException,
423
NoSuchAlgorithmException {
424
randomData.reSeed(1000);
425
double v = randomData.nextUniform(0,1);
427
assertTrue("different seeds",
428
Math.abs(v - randomData.nextUniform(0,1)) > 10E-12);
429
randomData.reSeed(1000);
430
assertEquals("same seeds",v,randomData.nextUniform(0,1),10E-12);
431
randomData.reSeedSecure(1000);
432
String hex = randomData.nextSecureHexString(40);
433
randomData.reSeedSecure();
434
assertTrue("different seeds",
435
!hex.equals(randomData.nextSecureHexString(40)));
436
randomData.reSeedSecure(1000);
437
assertTrue("same seeds",
438
!hex.equals(randomData.nextSecureHexString(40)));
440
/* remove this test back soon,
441
* since it takes about 4 seconds
444
randomData.setSecureAlgorithm("SHA1PRNG","SUN");
445
} catch (NoSuchProviderException ex) {
448
assertTrue("different seeds",
449
!hex.equals(randomData.nextSecureHexString(40)));
451
randomData.setSecureAlgorithm("NOSUCHTHING","SUN");
452
fail("expecting NoSuchAlgorithmException");
453
} catch (NoSuchProviderException ex) {
455
} catch (NoSuchAlgorithmException ex) {
460
randomData.setSecureAlgorithm("SHA1PRNG","NOSUCHPROVIDER");
461
fail("expecting NoSuchProviderException");
462
} catch (NoSuchProviderException ex) {
467
// test reseeding without first using the generators
468
RandomDataImpl rd = new RandomDataImpl();
471
RandomDataImpl rd2 = new RandomDataImpl();
472
rd2.reSeedSecure(2000);
473
rd2.nextSecureLong(1,2);
474
rd = new RandomDataImpl();
477
rd2 = new RandomDataImpl();
479
rd2.nextSecureLong(1,2);
482
/** tests for nextSample() sampling from Collection */
483
public void testNextSample() {
484
Object[][] c = {{"0","1"},{"0","2"},{"0","3"},{"0","4"},{"1","2"},
485
{"1","3"},{"1","4"},{"2","3"},{"2","4"},{"3","4"}};
486
long[] observed = {0,0,0,0,0,0,0,0,0,0};
487
double[] expected = {100,100,100,100,100,100,100,100,100,100};
489
HashSet cPop = new HashSet(); //{0,1,2,3,4}
490
for (int i = 0; i < 5; i++) {
491
cPop.add(Integer.toString(i));
494
Object[] sets = new Object[10]; // 2-sets from 5
495
for (int i = 0; i < 10; i ++) {
496
HashSet hs = new HashSet();
502
for (int i = 0; i < 1000; i ++) {
503
Object[] cSamp = randomData.nextSample(cPop,2);
504
observed[findSample(sets,cSamp)]++;
507
/* Use ChiSquare dist with df = 10-1 = 9, alpha = .001
508
* Change to 21.67 for alpha = .01
510
assertTrue("chi-square test -- will fail about 1 in 1000 times",
511
testStatistic.chiSquare(expected,observed) < 27.88);
513
// Make sure sample of size = size of collection returns same collection
514
HashSet hs = new HashSet();
516
Object[] one = randomData.nextSample(hs,1);
517
String oneString = (String) one[0];
518
if ((one.length != 1) || !oneString.equals("one")){
519
fail("bad sample for set size = 1, sample size = 1");
522
// Make sure we fail for sample size > collection size
524
one = randomData.nextSample(hs,2);
525
fail("sample size > set size, expecting IllegalArgumentException");
526
} catch (IllegalArgumentException ex) {
530
// Make sure we fail for empty collection
533
one = randomData.nextSample(hs,0);
534
fail("n = k = 0, expecting IllegalArgumentException");
535
} catch (IllegalArgumentException ex) {
540
private int findSample(Object[] u, Object[] samp) {
541
for (int i = 0; i < u.length; i++) {
542
HashSet set = (HashSet) u[i];
543
HashSet sampSet = new HashSet();
544
for (int j = 0; j < samp.length; j++) {
545
sampSet.add(samp[j]);
547
if (set.equals(sampSet)) {
551
fail("sample not found:{" + samp[0] + "," + samp[1] + "}");
555
/** tests for nextPermutation */
556
public void testNextPermutation() {
557
int[][] p = {{0,1,2},{0,2,1},{1,0,2},{1,2,0},{2,0,1},{2,1,0}};
558
long[] observed = {0,0,0,0,0,0};
559
double[] expected = {100,100,100,100,100,100};
561
for (int i = 0; i < 600; i++) {
562
int[] perm = randomData.nextPermutation(3,3);
563
observed[findPerm(p,perm)]++;
566
/* Use ChiSquare dist with df = 6-1 = 5, alpha = .001
567
* Change to 15.09 for alpha = .01
569
assertTrue("chi-square test -- will fail about 1 in 1000 times",
570
testStatistic.chiSquare(expected,observed) < 20.52);
572
// Check size = 1 boundary case
573
int[] perm = randomData.nextPermutation(1,1);
574
if ((perm.length != 1) || (perm[0] != 0)){
575
fail("bad permutation for n = 1, sample k = 1");
577
// Make sure we fail for k size > n
579
perm = randomData.nextPermutation(2,3);
580
fail("permutation k > n, expecting IllegalArgumentException");
581
} catch (IllegalArgumentException ex) {
585
// Make sure we fail for n = 0
587
perm = randomData.nextPermutation(0,0);
588
fail("permutation k = n = 0, expecting IllegalArgumentException");
589
} catch (IllegalArgumentException ex) {
595
private int findPerm(int[][] p, int[] samp) {
596
for (int i = 0; i < p.length; i++) {
598
for (int j = 0; j < samp.length; j++) {
599
if (samp[j] != p[i][j]) {
607
fail("permutation not found");