1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.hipparchus.stat.descriptive.rank;
18
19 import static org.junit.Assert.assertEquals;
20 import static org.junit.Assert.assertFalse;
21 import static org.junit.Assert.assertTrue;
22
23 import java.lang.reflect.Constructor;
24 import java.lang.reflect.Method;
25 import java.util.ArrayList;
26 import java.util.Arrays;
27 import java.util.List;
28 import java.util.SplittableRandom;
29
30 import org.hipparchus.UnitTestUtils;
31 import org.hipparchus.distribution.RealDistribution;
32 import org.hipparchus.distribution.continuous.ExponentialDistribution;
33 import org.hipparchus.distribution.continuous.GammaDistribution;
34 import org.hipparchus.distribution.continuous.LogNormalDistribution;
35 import org.hipparchus.distribution.continuous.NormalDistribution;
36 import org.hipparchus.exception.MathIllegalArgumentException;
37 import org.hipparchus.random.MersenneTwister;
38 import org.hipparchus.random.RandomDataGenerator;
39 import org.hipparchus.random.RandomGenerator;
40 import org.hipparchus.random.Well19937c;
41 import org.hipparchus.stat.StatUtils;
42 import org.hipparchus.stat.descriptive.StorelessUnivariateStatistic;
43 import org.hipparchus.stat.descriptive.StorelessUnivariateStatisticAbstractTest;
44 import org.hipparchus.stat.inference.AlternativeHypothesis;
45 import org.hipparchus.stat.inference.BinomialTest;
46 import org.hipparchus.util.FastMath;
47 import org.junit.Test;
48
49
50
51
52
53 public class RandomPercentileTest extends
54 StorelessUnivariateStatisticAbstractTest {
55
56 protected double tolerance = 10E-12;
57
58 private final RandomGenerator randomGenerator = new Well19937c(1000);
59
60 @Override
61 public RandomPercentile getUnivariateStatistic() {
62 return new RandomPercentile();
63 }
64
65 @Override
66 public double expectedValue() {
67 return this.median;
68 }
69
70
71
72
73
74
75 @Test
76 public void testCopyConsistencyWithInitialMostElements() {
77
78 StorelessUnivariateStatistic master = getUnivariateStatistic();
79 StorelessUnivariateStatistic replica = null;
80
81
82 long index = FastMath.round(0.75 * testArray.length);
83
84
85 master.incrementAll(testArray, 0, (int) index);
86 replica = master.copy();
87
88
89 assertTrue(replica.equals(master));
90 assertTrue(master.equals(replica));
91
92
93 master.incrementAll(testArray, (int) index, (int) (testArray.length - index));
94 replica.incrementAll(testArray, (int) index, (int) (testArray.length - index));
95 assertTrue(replica.equals(master));
96 assertTrue(master.equals(replica));
97 }
98
99
100
101
102
103
104 @Test
105 public void testCopyConsistencyWithInitialFirstFewElements() {
106
107 StorelessUnivariateStatistic master = getUnivariateStatistic();
108 StorelessUnivariateStatistic replica = null;
109
110
111
112 long index = FastMath.round(0.1 * testArray.length);
113
114
115 master.incrementAll(testArray, 0, (int) index);
116 replica = master.copy();
117
118
119 assertTrue(replica.equals(master));
120 assertTrue(master.equals(replica));
121
122 master.incrementAll(testArray, (int) index, (int) (testArray.length - index));
123 replica.incrementAll(testArray, (int) index, (int) (testArray.length - index));
124 assertTrue(master.equals(master));
125 assertTrue(replica.equals(replica));
126 assertTrue(replica.equals(master));
127 assertTrue(master.equals(replica));
128 }
129
130 @Test
131 public void testPercentileSmallSample() {
132 double[] d = new double[] { 1, 3, 2, 4 };
133 final RandomPercentile randomPercentile = new RandomPercentile();
134 randomPercentile.incrementAll(d);
135 Percentile p = new Percentile(30d);
136 assertEquals(p.evaluate(d), randomPercentile.getResult(30d), 1.0e-5);
137 p = new Percentile(25);
138 assertEquals(p.evaluate(d), randomPercentile.getResult(25d), 1.0e-5);
139 p = new Percentile(75);
140 assertEquals(p.evaluate(d),randomPercentile.getResult(75d), 1.0e-5);
141 p = new Percentile(50);
142 assertEquals(p.evaluate(d),randomPercentile.getResult(50d), 1.0e-5);
143 }
144
145 @Test(expected = MathIllegalArgumentException.class)
146 public void testNonPositiveEpsilon() {
147 double[] d =
148 new double[] { 95.1772, 95.1567, 95.1937, 95.1959, 95.1442,
149 95.0610, 95.1591, 95.1195, 95.1772, 95.0925, 95.1990,
150 95.1682 };
151 RandomPercentile p = new RandomPercentile(0);
152 p.evaluate(d, 0, d.length);
153 }
154
155 @Test
156 public void testNISTExample() {
157 double[] d =
158 new double[] { 95.1772, 95.1567, 95.1937, 95.1959, 95.1442,
159 95.0610, 95.1591, 95.1195, 95.1772, 95.0925, 95.1990,
160 95.1682 };
161 assertEquals(95.1981, new RandomPercentile().evaluate(90d, d), 1.0e-4);
162 assertEquals(95.061, new RandomPercentile().evaluate(0d, d), 0);
163 assertEquals(95.1990, new RandomPercentile().evaluate(100d, d, 0, d.length), 0);
164 }
165
166 @Test
167 public void test5() {
168 RandomPercentile percentile = new RandomPercentile();
169 assertEquals(this.percentile5, percentile.evaluate(5, testArray), 0.0001);
170 }
171
172 @Test
173 public void testSingleton() {
174 RandomPercentile percentile = new RandomPercentile();
175 double[] singletonArray = new double[] { 1d };
176 assertEquals(1d, percentile.evaluate(singletonArray), 0);
177 assertEquals(1d, percentile.evaluate(singletonArray, 0, 1), 0);
178 percentile = new RandomPercentile();
179 assertEquals(1d, percentile.evaluate(5, singletonArray, 0, 1), 0);
180 percentile = new RandomPercentile();
181 assertEquals(1d, percentile.evaluate(100, singletonArray, 0, 1), 0);
182 percentile = new RandomPercentile();
183 assertTrue(Double.isNaN(percentile.evaluate(100, singletonArray, 0, 0)));
184 }
185
186 @Test
187 public void testSpecialValues() {
188 RandomPercentile percentile = new RandomPercentile();
189 double[] specialValues = new double[] { 0d, 1d, 2d, 3d, 4d, Double.NaN };
190 assertEquals(2d, percentile.evaluate(specialValues), 0);
191 specialValues =
192 new double[] { Double.NEGATIVE_INFINITY, 1d, 2d, 3d, Double.NaN, Double.POSITIVE_INFINITY };
193 assertEquals(2d, percentile.evaluate(specialValues), 0);
194 specialValues =
195 new double[] { 1d, 1d, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY };
196 assertTrue(Double.isInfinite(percentile.evaluate(specialValues)));
197 specialValues = new double[] { 1d, 1d, Double.NaN, Double.NaN };
198 assertFalse(Double.isNaN(percentile.evaluate(specialValues)));
199 specialValues =
200 new double[] { 1d, 1d, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY };
201 percentile = new RandomPercentile();
202 assertTrue(Double.isNaN(percentile.evaluate(specialValues)));
203 }
204
205 @Test
206 public void testAggregateSmallSamplesA() {
207 doTestAggregateSmallSamples(0.5, 11.0);
208 }
209
210 @Test
211 public void testAggregateSmallSamplesB() {
212 doTestAggregateSmallSamples(0.1, 7.0);
213 }
214
215 @Test
216 public void testAggregateSmallSamplesC() {
217 doTestAggregateSmallSamples(0.01, 7.0);
218 }
219
220 private void doTestAggregateSmallSamples(double epsilon, double expected) {
221 SplittableRandom seeds = new SplittableRandom(0x218560e08c8df220l);
222
223 RandomPercentile rp1 = new RandomPercentile(epsilon, new Well19937c(seeds.nextLong()));
224 double[] data1 = new double[] { 3, 5, -2, 7, 14, 6 };
225 for (double d : data1 ) {
226 rp1.accept(d);
227 }
228 RandomPercentile rp2 = new RandomPercentile(epsilon, new Well19937c(seeds.nextLong()));
229 double[] data2 = new double[] { 9, 12, 15 };
230 for (double d : data2 ) {
231 rp2.accept(d);
232 }
233
234 rp1.aggregate(rp2);
235
236 assertEquals(expected, rp1.getResult(), 1.0e-10);
237
238 }
239
240 @Test
241 public void testBufferConsumeLevel0() throws Exception {
242 final int len = testArray.length;
243 final double[] sorted = Arrays.copyOf(testArray, len);
244 Arrays.sort(sorted);
245 BufferMock buffer = new BufferMock(len, 0, randomGenerator);
246 for (int i = 0; i < len; i++) {
247 buffer.consume(testArray[i]);
248 }
249 UnitTestUtils.assertEquals(sorted, buffer.getData(), Double.MIN_VALUE);
250 assertFalse(buffer.hasCapacity());
251 assertEquals(StatUtils.min(testArray),buffer.min(), Double.MIN_VALUE);
252 assertEquals(StatUtils.max(testArray),buffer.max(), Double.MIN_VALUE);
253 }
254
255 @Test
256 public void testBufferSampling() throws Exception {
257
258 BufferMock buffer = new BufferMock(10, 2, randomGenerator);
259 for (int i = 0; i < 40; i++) {
260 buffer.consume(i);
261 }
262
263 assertFalse(buffer.hasCapacity());
264 final double[] data = buffer.getData();
265 for (int i = 0; i < 10; i++) {
266 assertTrue(data[i] < 4 * (i + 1));
267 assertTrue(data[i] >= 4 * i);
268
269 assertEquals(i + 1, buffer.rankOf((i + 1) * 4));
270
271 assertEquals(0, buffer.rankOf(-1));
272 assertEquals(10, buffer.rankOf(100));
273 }
274 }
275
276 @Test
277 public void testBufferMergeWith() throws Exception {
278
279 BufferMock buffer1 = new BufferMock(20, 0, randomGenerator);
280 BufferMock buffer2 = new BufferMock(20, 0, randomGenerator);
281
282
283 for (int i = 0; i < 20; i++) {
284 buffer1.consume(i);
285 buffer2.consume(i + 20);
286 }
287 assertEquals(0, buffer1.getLevel());
288 assertEquals(0, buffer2.getLevel());
289
290
291 buffer1.mergeWith(buffer2.getInstance());
292
293
294 assertEquals(1,buffer1.getLevel());
295 assertFalse(buffer1.hasCapacity());
296 assertEquals(1,buffer2.getLevel());
297 assertTrue(buffer2.hasCapacity());
298
299
300 final double[] data = buffer1.getData();
301 int nSmall = 0;
302 for (double value : data) {
303 assertTrue(value >=0 && value < 40);
304 if (value < 20) {
305 nSmall++;
306 }
307 }
308
309
310 BinomialTest bTest = new BinomialTest();
311 assertFalse(bTest.binomialTest(20, nSmall, 0.5, AlternativeHypothesis.TWO_SIDED, 0.01));
312
313
314 buffer1.checkSorted();
315 }
316
317 @Test
318 public void testBufferMergeInto() throws Exception {
319 BufferMock buffer1 = new BufferMock(20, 0, randomGenerator);
320 BufferMock buffer2 = new BufferMock(20, 2, randomGenerator);
321
322
323 for (int i = 0; i < 20; i++) {
324 buffer1.consume(i);
325 }
326
327
328 for (int i = 0; i < 80; i++) {
329 buffer2.consume(i + 20);
330 }
331 assertFalse(buffer1.hasCapacity());
332 assertFalse(buffer2.hasCapacity());
333 buffer1.mergeInto(buffer2.getInstance());
334
335
336 assertEquals(0, buffer1.getLevel());
337 assertEquals(2, buffer2.getLevel());
338
339
340 final double[] data = buffer2.getData();
341 int nSmall = 0;
342 for (double value : data) {
343 assertTrue(value >=0 && value < 100);
344 if (value < 20) {
345 nSmall++;
346 }
347 }
348 BinomialTest bTest = new BinomialTest();
349 assertFalse(bTest.binomialTest(20, nSmall, 0.25, AlternativeHypothesis.TWO_SIDED, 0.01));
350
351
352 buffer2.checkSorted();
353 }
354
355 static class BufferMock {
356 private Object instance;
357 private Method consumeMethod;
358 private Method getDataMethod;
359 private Method hasCapacityMethod;
360 private Method minMethod;
361 private Method maxMethod;
362 private Method rankOfMethod;
363 private Method getLevelMethod;
364 private Method mergeWithMethod;
365 private Method mergeIntoMethod;
366 @SuppressWarnings({ "unchecked", "rawtypes" })
367 public BufferMock(int size, int level, RandomGenerator randomGenerator) throws Exception {
368 final Class[] classes = RandomPercentile.class.getDeclaredClasses();
369 for (Class cls : classes) {
370 if (cls.getName().endsWith("$Buffer")) {
371 Constructor constructor = cls.getDeclaredConstructor(Integer.TYPE, Integer.TYPE, RandomGenerator.class);
372 instance = constructor.newInstance(size, level, randomGenerator);
373 consumeMethod = cls.getDeclaredMethod("consume", Double.TYPE);
374 getDataMethod = cls.getDeclaredMethod("getData");
375 hasCapacityMethod = cls.getDeclaredMethod("hasCapacity");
376 minMethod = cls.getDeclaredMethod("min");
377 maxMethod = cls.getDeclaredMethod("max");
378 rankOfMethod = cls.getDeclaredMethod("rankOf", Double.TYPE);
379 getLevelMethod = cls.getDeclaredMethod("getLevel");
380 mergeWithMethod = cls.getDeclaredMethod("mergeWith", cls);
381 mergeIntoMethod = cls.getDeclaredMethod("mergeInto", cls);
382 }
383 }
384 }
385
386 public void consume(double value) throws Exception {
387 consumeMethod.invoke(instance, value);
388 }
389
390 public boolean hasCapacity() throws Exception {
391 return (boolean) hasCapacityMethod.invoke(instance);
392 }
393
394 public double[] getData() throws Exception {
395 return (double[]) getDataMethod.invoke(instance);
396 }
397
398 public double min() throws Exception {
399 return (double) minMethod.invoke(instance);
400 }
401
402 public double max() throws Exception {
403 return (double) maxMethod.invoke(instance);
404 }
405
406 public int rankOf(double value) throws Exception {
407 return (int) rankOfMethod.invoke(instance, value);
408 }
409
410 public int getLevel() throws Exception {
411 return (int) getLevelMethod.invoke(instance);
412 }
413
414 public void mergeWith(Object other) throws Exception {
415 mergeWithMethod.invoke(instance, other);
416 }
417
418 public void mergeInto(Object other) throws Exception {
419 mergeIntoMethod.invoke(instance, other);
420 }
421
422 public Object getInstance() {
423 return instance;
424 }
425
426 public void checkSorted() throws Exception {
427 final double[] data = getData();
428 final double[] copy = Arrays.copyOf(data, data.length);
429 Arrays.sort(copy);
430 UnitTestUtils.assertEquals(data, copy, Double.MIN_VALUE);
431 }
432
433 }
434
435 @Test
436 public void testArrayExample() {
437 assertEquals(this.percentile95, new RandomPercentile().evaluate(95d,testArray), getTolerance());
438 }
439
440 @Test
441 public void testReduceSmallDataSet() {
442 final RandomDataGenerator random = new RandomDataGenerator(1000);
443 final long n = 1000;
444 double[] combined = new double[10000];
445 int i = 0;
446 final List<RandomPercentile> aggregates = new ArrayList<RandomPercentile>();
447 for (int j = 0; j < 10; j++) {
448 final RandomPercentile randomPercentile = new RandomPercentile();
449 for (int k = 0; k < n; k++) {
450 final double value = random.nextGaussian();
451 randomPercentile.accept(value);
452 combined[i++] = value;
453 }
454 aggregates.add(randomPercentile);
455 }
456
457 final Percentile master = new Percentile();
458 final RandomPercentile randomMaster = new RandomPercentile();
459 for (int l = 0; l < 5; l++) {
460 final double percentile = l * 15 + 1;
461 assertEquals(master.evaluate(combined, percentile),
462 randomMaster.reduce(percentile, aggregates), Double.MIN_VALUE);
463 }
464 }
465
466 @Test
467 public void testReduceLargeDataSet() {
468 final RandomDataGenerator random = new RandomDataGenerator(1000);
469 final long n = 1000000;
470 final RandomGenerator randomGenerator = new RandomDataGenerator(1000);
471 final RandomPercentile randomMaster = new RandomPercentile(randomGenerator);
472 final PSquarePercentile pSquare = new PSquarePercentile(1);
473 final List<RandomPercentile> aggregates = new ArrayList<RandomPercentile>();
474 for (int j = 0; j < 5; j++) {
475 final RandomPercentile randomPercentile = new RandomPercentile(randomGenerator);
476 for (int k = 0; k < n; k++) {
477 final double value = random.nextGaussian();
478 randomPercentile.accept(value);
479 randomMaster.accept(value);
480 pSquare.increment(value);
481 }
482 aggregates.add(randomPercentile);
483 }
484
485 for (int l = 0; l < 5; l++) {
486 final double percentile = l * 13 + 1;
487 assertEquals("percentile = " + percentile, randomMaster.getResult(percentile),
488 randomMaster.reduce(percentile, aggregates), 5E-3);
489 }
490 }
491
492 private Double[] randomTestData(int factor, int values) {
493 Double[] test = new Double[values];
494 for (int i = 0; i < test.length; i++) {
495 test[i] = Math.abs(randomGenerator.nextDouble() * factor);
496 }
497 return test;
498 }
499
500
501 public void testAccept() {
502 final RandomPercentile randomPercentile = new RandomPercentile();
503 assertTrue(Double.isNaN(randomPercentile.getResult()));
504 Double[] test = randomTestData(100, 10000);
505
506 for (Double value : test) {
507 randomPercentile.increment(value);
508 assertTrue(randomPercentile.getResult() >= 0);
509 }
510 }
511
512 private void assertValues(Double a, Double b, double delta) {
513 if (Double.isNaN(a)) {
514 assertTrue("" + b + " is not NaN.", Double.isNaN(a));
515 } else if (Double.isInfinite(a)) {
516 assertTrue(a.equals(b));
517 } else {
518 double max = FastMath.max(a, b);
519 double percentage = FastMath.abs(a - b) / max;
520 double deviation = delta;
521 assertTrue(String.format("Deviated = %f and is beyond %f as a=%f, b=%f",
522 percentage, deviation, a, b), percentage < deviation);
523 }
524 }
525
526
527
528
529
530
531
532
533
534
535 private void checkQuantileError(double[] data, double value, double quantile, double tolerance,
536 double referenceValue) {
537 final double n = (double) data.length;
538 int nLess = 0;
539 for (double val : data) {
540 if (val < value) {
541 nLess++;
542 }
543 }
544 if (Double.isNaN(referenceValue)) {
545 assertTrue(Double.isNaN(value));
546 } else if (Double.isInfinite(value)) {
547 assertTrue(value == referenceValue);
548 } else {
549 assertTrue("Quantile error exceeded: value returned = " + value +
550 " Reference value = " + referenceValue +
551 " quantile = " + quantile + " n = " + n +
552 " error = " + (quantile - (double) nLess / n),
553 FastMath.abs(quantile - (double) nLess / n) < tolerance);
554 }
555 }
556
557
558 private void doCalculatePercentile(Double percentile, Number[] test) {
559 doCalculatePercentile(percentile, test, Double.MAX_VALUE);
560 }
561
562
563 private void doCalculatePercentile(Double percentile, Number[] test, double delta) {
564 RandomPercentile random = new RandomPercentile(new Well19937c(200));
565 for (Number value : test) {
566 random.increment(value.doubleValue());
567 }
568
569 Percentile p2 = new Percentile(percentile * 100);
570
571 double[] dall = new double[test.length];
572 for (int i = 0; i < test.length; i++) {
573 dall[i] = test[i].doubleValue();
574 }
575
576 Double referenceValue = p2.evaluate(dall);
577 assertValues(random.getResult(percentile), referenceValue, delta);
578 }
579
580 private void doCalculatePercentile(double percentile, double[] test, double delta) {
581 RandomPercentile randomEstimated = new RandomPercentile(new Well19937c(200));
582 for (double value : test) {
583 randomEstimated.increment(value);
584 }
585
586 Percentile p2 = new Percentile(percentile < 1 ? percentile * 100 : percentile);
587
588
589
590
591 Double referenceValue = p2.evaluate(test);
592 if (test.length < LARGE) {
593 assertValues(randomEstimated.getResult(percentile), referenceValue, delta);
594 } else {
595 checkQuantileError(test,randomEstimated.getResult(percentile), percentile / 100, delta, referenceValue);
596 }
597 }
598
599 @Test
600 public void testCannedDataSet() {
601 Integer[] seedInput =
602 new Integer[] { 283, 285, 298, 304, 310, 31, 319, 32, 33, 339,
603 342, 348, 350, 354, 354, 357, 36, 36, 369, 37, 37, 375,
604 378, 383, 390, 396, 405, 408, 41, 414, 419, 416, 42,
605 420, 430, 430, 432, 444, 447, 447, 449, 45, 451, 456,
606 468, 470, 471, 474, 600, 695, 70, 83, 97, 109, 113, 128 };
607 Integer[] input = new Integer[seedInput.length * 100];
608 for (int i = 0; i < input.length; i++) {
609 input[i] = seedInput[i % seedInput.length] + i;
610 }
611 doCalculatePercentile(0.50d, input);
612 doCalculatePercentile(0.95d, input);
613 }
614
615 @Test
616 public void test99Percentile() {
617 Double[] test = randomTestData(100, 10000);
618 doCalculatePercentile(0.99d, test);
619 }
620
621 @Test
622 public void test90Percentile() {
623 Double[] test = randomTestData(100, 10000);
624 doCalculatePercentile(0.90d, test);
625 }
626
627 @Test
628 public void test20Percentile() {
629 Double[] test = randomTestData(100, 100000);
630 doCalculatePercentile(0.20d, test);
631 }
632
633 @Test
634 public void test5Percentile() {
635 Double[] test = randomTestData(50, 990000);
636 doCalculatePercentile(0.50d, test);
637 }
638
639 @Test
640 public void test99PercentileHighValues() {
641 Double[] test = randomTestData(100000, 10000);
642 doCalculatePercentile(0.99d, test);
643 }
644
645 @Test
646 public void test90PercentileHighValues() {
647 Double[] test = randomTestData(100000, 100000);
648 doCalculatePercentile(0.90d, test);
649 }
650
651 @Test
652 public void test20PercentileHighValues() {
653 Double[] test = randomTestData(100000, 100000);
654 doCalculatePercentile(0.20d, test);
655 }
656
657 @Test
658 public void test5PercentileHighValues() {
659 Double[] test = randomTestData(100000, 100000);
660 doCalculatePercentile(0.05d, test);
661 }
662
663 @Test
664 public void test0PercentileValuesWithFewerThan5Values() {
665 double[] test = { 1d, 2d, 3d, 4d };
666 RandomPercentile p = new RandomPercentile();
667 assertEquals(1d, p.evaluate(0d,test), 0);
668 }
669
670 @Test
671 public void testMaxValuesRetained() {
672 assertEquals(546795, RandomPercentile.maxValuesRetained(RandomPercentile.DEFAULT_EPSILON));
673 assertEquals(34727, RandomPercentile.maxValuesRetained(1E-3));
674 assertEquals(2064, RandomPercentile.maxValuesRetained(1E-2));
675 }
676
677 @Test(expected = MathIllegalArgumentException.class)
678 public void testMaxValuesRetained0Epsilon() {
679 RandomPercentile.maxValuesRetained(0);
680 }
681
682 @Test(expected = MathIllegalArgumentException.class)
683 public void testMaxValuesRetained1Epsilon() {
684 RandomPercentile.maxValuesRetained(1);
685 }
686
687
688 final int TINY = 10, SMALL = 50, NOMINAL = 100, MEDIUM = 500,
689 STANDARD = 1000, BIG = 10000, VERY_BIG = 50000, LARGE = 1000000,
690 VERY_LARGE = 10000000;
691
692 private void doDistributionTest(RealDistribution distribution) {
693 double[] data;
694
695 final RandomDataGenerator randomDataGenerator = new RandomDataGenerator(100);
696 data = randomDataGenerator.nextDeviates(distribution, LARGE);
697 doCalculatePercentile(50, data, 0.0005);
698 doCalculatePercentile(95, data, 0.0005);
699
700 data = randomDataGenerator.nextDeviates(distribution, VERY_BIG);
701 doCalculatePercentile(50, data, 0.0001);
702 doCalculatePercentile(95, data, 0.0001);
703
704 data = randomDataGenerator.nextDeviates(distribution, BIG);
705 doCalculatePercentile(50, data, 0.0001);
706 doCalculatePercentile(95, data, 0.0001);
707
708 data = randomDataGenerator.nextDeviates(distribution, STANDARD);
709 doCalculatePercentile(50, data, 0.0001);
710 doCalculatePercentile(95, data, 0.0001);
711
712 data = randomDataGenerator.nextDeviates(distribution, MEDIUM);
713 doCalculatePercentile(50, data, 0.0001);
714 doCalculatePercentile(95, data, 0.0001);
715
716 data = randomDataGenerator.nextDeviates(distribution, NOMINAL);
717 doCalculatePercentile(50, data, 0.0001);
718 doCalculatePercentile(95, data, 0.0001);
719
720 data = randomDataGenerator.nextDeviates(distribution, SMALL);
721 doCalculatePercentile(50, data, 0.0001);
722 doCalculatePercentile(95, data, 0.0001);
723
724 data = randomDataGenerator.nextDeviates(distribution, TINY);
725 doCalculatePercentile(50, data, 0.0001);
726 doCalculatePercentile(95, data, 0.0001);
727 }
728
729
730
731
732 @Test
733 public void testDistribution() {
734 doDistributionTest(new NormalDistribution(4000, 50));
735 doDistributionTest(new LogNormalDistribution(4000, 50));
736 doDistributionTest(new ExponentialDistribution(4000));
737 doDistributionTest(new GammaDistribution(5d,1d));
738 }
739
740
741
742
743 @Test
744 public void testDistributionStreaming() {
745 checkQuartiles(new NormalDistribution(), 1000000, 5E-4);
746 checkQuartiles(new ExponentialDistribution(1), 600000, 5E-4);
747 checkQuartiles(new GammaDistribution(4d,2d), 600000, 5E-4);
748 }
749
750
751
752
753 @Test
754 public void testSequentialData() {
755 final long seed = 1000;
756 double epsilon = 1e-4;
757 for (int j = 0; j < 3; j++) {
758 epsilon *= 10;
759 final RandomPercentile randomPercentile = new RandomPercentile(epsilon,
760 new MersenneTwister(seed));
761 final int n = 5000000;
762 for (int i = 1; i <= n; i++) {
763 randomPercentile.accept(i);
764 }
765 for (int i = 1; i < 5; i++) {
766 assertEquals(0.2 * i, randomPercentile.getResult(i * 20) / n, 2 * epsilon);
767 }
768 }
769 }
770
771
772
773
774
775
776
777
778 private void checkQuartiles(RealDistribution dist, int sampleSize, double tolerance) {
779 final long seed = 1000;
780 RandomDataGenerator randomDataGenerator = RandomDataGenerator.of(new MersenneTwister(seed));
781 final RandomPercentile randomPercentile = new RandomPercentile(RandomPercentile.DEFAULT_EPSILON,
782 randomGenerator);
783 for (int i = 0; i < sampleSize; i++) {
784 randomPercentile.increment(randomDataGenerator.nextDeviate(dist));
785 }
786 final double q1 = randomPercentile.getResult(25);
787 final double q2 = randomPercentile.getResult();
788 final double q3 = randomPercentile.getResult(75);
789
790
791 randomDataGenerator.setSeed(seed);
792 double v;
793 double ct1 = 0;
794 double ct2 = 0;
795 double ct3 = 0;
796 for (int i = 0; i < sampleSize; i++) {
797 v = randomDataGenerator.nextDeviate(dist);
798 if (v < q1) {
799 ct1++;
800 ct2++;
801 ct3++;
802 } else if (v < q2) {
803 ct2++;
804 ct3++;
805 } else if (v < q3) {
806 ct3++;
807 }
808 }
809 assertEquals(0.25, ct1/sampleSize, tolerance);
810 assertEquals(0.5, ct2/sampleSize, tolerance);
811 assertEquals(0.75, ct3/sampleSize, tolerance);
812 }
813 }