View Javadoc
1   package org.djutils.stats.summarizers.quantileaccumulator;
2   
3   import static org.junit.Assert.assertEquals;
4   import static org.junit.Assert.assertTrue;
5   import static org.junit.Assert.fail;
6   
7   import org.djutils.stats.summarizers.Tally;
8   import org.junit.Test;
9   
10  /**
11   * AccumulatorTest tests the quantile accumulators for the right exceptions. <br>
12   * <br>
13   * Copyright (c) 2020-2022 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
14   * for project information <a href="https://djutils.org" target="_blank"> https://djutils.org</a>. The DJUTILS project is
15   * distributed under a three-clause BSD-style license, which can be found at
16   * <a href="https://djutils.org/docs/license.html" target="_blank"> https://djutils.org/docs/license.html</a>. <br>
17   * @author <a href="https://www.tudelft.nl/averbraeck">Alexander Verbraeck</a>
18   * @author <a href="https://www.tudelft.nl/pknoppers">Peter Knoppers</a>
19   */
20  public class AccumulatorTest
21  {
22      /** Test the accumulators for null and wrong probabilities. */
23      @Test
24      public void testAccumulators()
25      {
26          testErrors(new NoStorageAccumulator());
27          testErrors(new FullStorageAccumulator());
28          testErrors(new TDigestAccumulator());
29      }
30  
31      /**
32       * test null and wrong probabilities on an accumulator.
33       * @param acc QuantileAccumulator; the accumulator to test
34       */
35      private void testErrors(final QuantileAccumulator acc)
36      {
37          try
38          {
39              acc.getQuantile(null, 0.5);
40              fail("null tally should have caused exception");
41          }
42          catch (Exception exception)
43          {
44              // ok
45          }
46  
47          Tally tally = new Tally("test");
48          try
49          {
50              acc.getQuantile(tally, -0.1);
51              fail("negative probability should have caused exception");
52          }
53          catch (Exception exception)
54          {
55              // ok
56          }
57  
58          try
59          {
60              acc.getQuantile(tally, 1.1);
61              fail("probability greater than 1 should have caused exception");
62          }
63          catch (Exception exception)
64          {
65              // ok
66          }
67      }
68  
69      /**
70       * Test the getCumulativeProbability method of the FullStorageAccumulator.
71       */
72      @Test
73      public void testFullStorageAccumulator()
74      {
75          FullStorageAccumulator fsa = new FullStorageAccumulator();
76          assertTrue("getCumulativeProbability with no data returns NaN", Double.isNaN(fsa.getCumulativeProbability(null, 12.3)));
77          // Ingest one value
78          fsa.register(10.0);
79          assertEquals("below single value returns 0", 0.0, fsa.getCumulativeProbability(null, 9.0), 0);
80          assertEquals("at single value returns 0", 0.5, fsa.getCumulativeProbability(null, 10.0), 0);
81          assertEquals("above single value returns 0", 1.0, fsa.getCumulativeProbability(null, 20.0), 0);
82          fsa.register(10.0);
83          assertEquals("below range value returns 0", 0.0, fsa.getCumulativeProbability(null, 9.0), 0);
84          assertEquals("at single value returns 0", 0.5, fsa.getCumulativeProbability(null, 10.0), 0);
85          assertEquals("above range value returns 0", 1.0, fsa.getCumulativeProbability(null, 20.0), 0);
86          fsa.register(10.0);
87          assertEquals("below range value returns 0", 0.0, fsa.getCumulativeProbability(null, 9.0), 0);
88          assertEquals("at single value returns 0", 0.5, fsa.getCumulativeProbability(null, 10.0), 0);
89          assertEquals("above range value returns 0", 1.0, fsa.getCumulativeProbability(null, 20.0), 0);
90          fsa.register(8.0);
91          assertEquals("below range value returns 0", 0.0, fsa.getCumulativeProbability(null, 7.0), 0);
92          assertEquals("at bottom range of length 4 value returns 0.125", 0.125, fsa.getCumulativeProbability(null, 8.0), 0);
93          assertEquals("between 0 and 1 of length 4 returns 0.25", 0.25, fsa.getCumulativeProbability(null, 9.0), 0);
94          assertEquals("in range of length 4 value returns 0.625", 0.625, fsa.getCumulativeProbability(null, 10.0), 0);
95          assertEquals("above range value returns 0", 1.0, fsa.getCumulativeProbability(null, 20.0), 0);
96          fsa.register(15.0);
97          assertEquals("below range value returns 0", 0.0, fsa.getCumulativeProbability(null, 7.0), 0);
98          assertEquals("at bottom range of length 5 value returns 0.1", 0.1, fsa.getCumulativeProbability(null, 8.0), 0.00001);
99          assertEquals("between 0 and 1 of length 5 returns 0.2", 0.2, fsa.getCumulativeProbability(null, 9.0), 0.00001);
100         assertEquals("in range of length 5 value returns 0.5", 0.5, fsa.getCumulativeProbability(null, 10.0), 0);
101         assertEquals("between beforelast and last of length 5 value returns 0.8", 0.8, fsa.getCumulativeProbability(null, 13.0),
102                 0.00001);
103         assertEquals("above range value returns 0", 1.0, fsa.getCumulativeProbability(null, 20.0), 0);
104         fsa.initialize();
105         for (int i = 0; i < 10; i++)
106         {
107             fsa.register(i + 10);
108         }
109         for (int i = 0; i < 30; i++)
110         {
111             double expect = 0;
112             if (i >= 20)
113             {
114                 expect = 1;
115             }
116             else if (i >= 10)
117             {
118                 expect = (i - 10 + 0.5) / 10;
119             }
120             // System.out.println(String.format("i=%d, expect=%.3f, got=%.3f", i, expect, fsa.getCumulativeProbability(i)));
121             assertEquals("p", expect, fsa.getCumulativeProbability(null, i), 0.0);
122         }
123     }
124 
125     /**
126      * Test the getCumulativeProbability method of the FixedBinsAccumulator. This test does not cover cases where some of the
127      * ingested values are out of range; as we have not decided how to compute cumulative probabilities for such cases.
128      */
129     @Test
130     public void testFixedBinsAccumulator()
131     {
132         FixedBinsAccumulator fba = new FixedBinsAccumulator(5.0, 0.5, 5);
133         // Bins are centered at 5.0, 5.5, 6.0, 6.5, 7.0
134         assertTrue("getCumulativeProbability with no data returns NaN", Double.isNaN(fba.getCumulativeProbability(null, 12.3)));
135         // Ingest one value
136         fba.register(5.7); // should be counted in bin 5.5
137         assertEquals("cumulative probability of value below any bin is 0.0", 0.0, fba.getCumulativeProbability(null, 2.2), 0);
138         assertEquals("cumulative probability of value below any filled bin is 0.0", 0.0,
139                 fba.getCumulativeProbability(null, 5.2), 0);
140         assertEquals("cumulatove probability of value exactly in center of the only filled bin is 0.5", 0.5,
141                 fba.getCumulativeProbability(null, 5.5), 0);
142         assertEquals("cumulative probability of value above any filled bin is 1.0", 1.0,
143                 fba.getCumulativeProbability(null, 5.8), 0);
144         assertEquals("cumulative probability of value above any bin is 1.0", 1.0, fba.getCumulativeProbability(null, 25.8), 0);
145         for (int i = 0; i <= 10; i++)
146         {
147             double quantile = 5.25 + 0.5 * i / 10;
148             double expect = 1.0 * i / 10;
149             double got = fba.getCumulativeProbability(null, quantile);
150             assertEquals("quantile at fraction in used bin", expect, got, 0.0001);
151         }
152         // Put some data in other buckets
153         fba.register(6.1);
154         fba.register(5.9);
155         assertEquals("cumulative probability of value below any bin is 0.0", 0.0, fba.getCumulativeProbability(null, 2.2), 0);
156         assertEquals("cumulative probability of value below any filled bin is 0.0", 0.0,
157                 fba.getCumulativeProbability(null, 5.2), 0);
158         assertEquals("cumulatove probability of value exactly in center of bin 5.5 is 1/6", 1.0 / 6,
159                 fba.getCumulativeProbability(null, 5.5), 0.0001);
160         assertEquals("cumulative probability of value above any filled bin is 1.0", 1.0,
161                 fba.getCumulativeProbability(null, 6.3), 0);
162         assertEquals("cumulative probability of value above any bin is 1.0", 1.0, fba.getCumulativeProbability(null, 25.8), 0);
163         // Step through the value range in small steps
164         for (int i = 405; i < 800; i += 10)
165         {
166             double quantile = i / 100.0;
167             double expect = 0.0;
168             if (i > 625)
169             {
170                 expect = 1.0;
171             }
172             else if (i > 575)
173             {
174                 expect = 1.0 / 3 + 2 * (i - 575) / 50.0 / 3;
175             }
176             else if (i > 525)
177             {
178                 expect = (i - 525) / 50.0 / 3;
179             }
180             double got = fba.getCumulativeProbability(null, quantile);
181             // System.out.println(String.format("i=%d, quantile=%.3f, expect=%.3f, got=%.3f", i, quantile, expect, got));
182             assertEquals("cumulative probability at quantile", expect, got, 0.0001);
183         }
184     }
185 
186     /**
187      * Test the getCumulativeProbability method of the NoStorageAccumulator.
188      */
189     @Test
190     public void testNoStorageAccumulator()
191     {
192         // This one can only be tested when cooperating with a Tally.
193         Tally tally = new Tally("test Tally with NoStorageAccumulator");
194         assertTrue("cumulative probability with no values ingested is NaN", Double.isNaN(tally.getCumulativeProbability(4)));
195         tally.register(10);
196         assertEquals("cumulative probability at single inserted value is 0.5", 0.5, tally.getCumulativeProbability(10), 0);
197         assertEquals("cummulative probability below single inserted value is 0.0", 0.0,
198                 tally.getCumulativeProbability(10 - Math.ulp(10)), 0);
199         assertEquals("cummulative probability above single inserted value is 1.0", 1.0,
200                 tally.getCumulativeProbability(10 + Math.ulp(10)), 0);
201         tally.register(20);
202         assertEquals("cumulative probability at mean is 0.5", 0.5, tally.getCumulativeProbability(15), 0);
203         assertEquals("cumulative probability at mean -sigma is about 0.16", 0.16, tally.getCumulativeProbability(10), 0.01);
204         assertEquals("cumulative probability at mean +sigma is about 0.84", 0.84, tally.getCumulativeProbability(20), 0.01);
205     }
206 
207     /**
208      * Test the getCumulativeProbability method of the TDigestAccumulator.
209      */
210     @Test
211     public void testTDigestAccumulator()
212     {
213         TDigestAccumulator tda = new TDigestAccumulator();
214         assertTrue("cumulative probability with no values ingested is NaN",
215                 Double.isNaN(tda.getCumulativeProbability(null, 4)));
216         tda.register(10);
217         assertEquals("cumulative probability at single inserted value is 0.5", 0.5, tda.getCumulativeProbability(null, 10), 0);
218         assertEquals("cummulative probability below single inserted value is 0.0", 0.0,
219                 tda.getCumulativeProbability(null, 10 - Math.ulp(10)), 0);
220         assertEquals("cummulative probability above single inserted value is 1.0", 1.0,
221                 tda.getCumulativeProbability(null, 10 + Math.ulp(10)), 0);
222         tda.register(20);
223         assertEquals("cumulative probability at mean is 0.5", 0.5, tda.getCumulativeProbability(null, 15), 0);
224         assertEquals("cumulative probability at 0.25 of range is between 0 and 0.5 0.26", 0.25,
225                 tda.getCumulativeProbability(null, 12.5), 0.15);
226         assertEquals("cumulative probability at 0.75 of range is between 0.5 and 1.0", 0.75,
227                 tda.getCumulativeProbability(null, 17.5), 0.15);
228         assertEquals("cumulative probability at start of range is 0.0", 0.0, tda.getCumulativeProbability(null, 10), 0);
229         assertEquals("cumulative probability at end of range is 1.0", 1.0, tda.getCumulativeProbability(null, 20), 0);
230     }
231 
232 }