View Javadoc
1   package org.djutils.stats.summarizers;
2   
3   import static org.junit.Assert.assertEquals;
4   import static org.junit.Assert.assertFalse;
5   import static org.junit.Assert.assertTrue;
6   import static org.junit.Assert.fail;
7   
8   import java.util.Calendar;
9   
10  import org.junit.Test;
11  
12  /**
13   * The TimestampWeightedTallyTest test the weighted tally that receives observations with a timestamp.
14   * <p>
15   * Copyright (c) 2002-2022 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
16   * for project information <a href="https://simulation.tudelft.nl/" target="_blank"> https://simulation.tudelft.nl</a>. The DSOL
17   * project is distributed under a three-clause BSD-style license, which can be found at
18   * <a href="https://simulation.tudelft.nl/dsol/3.0/license.html" target="_blank">
19   * https://simulation.tudelft.nl/dsol/3.0/license.html</a>.
20   * <br>
21   * @author <a href="https://www.linkedin.com/in/peterhmjacobs">Peter Jacobs </a>
22   * @since 1.5
23   */
24  public class TimestampWeightedTallyTest
25  {
26      /** Test the TimestampWeightedTally on Number based timestamps. */
27      @Test
28      public void testTimestampWeightedTallyNumber()
29      {
30          String description = "THIS TIMESTAMP WEIGHTED TALLY IS TESTED";
31          TimestampWeightedTally wt = new TimestampWeightedTally(description);
32  
33          // check the description
34          assertEquals(description, wt.getDescription());
35          assertTrue(wt.toString().contains(description));
36  
37          // now we check the initial values
38          assertTrue(wt.isActive());
39          assertTrue(Double.isNaN(wt.getMin()));
40          assertTrue(Double.isNaN(wt.getMax()));
41          assertTrue(Double.isNaN(wt.getWeightedSampleMean()));
42          assertTrue(Double.isNaN(wt.getWeightedPopulationMean()));
43          assertTrue(Double.isNaN(wt.getWeightedSampleVariance()));
44          assertTrue(Double.isNaN(wt.getWeightedSampleStDev()));
45          assertEquals(0.0, wt.getWeightedSum(), 0.0);
46          assertEquals(0L, wt.getN());
47  
48          wt.register(0.0, 1.0);
49          assertTrue(Double.isNaN(wt.getMin()));
50          assertTrue(Double.isNaN(wt.getMax()));
51          assertTrue(Double.isNaN(wt.getWeightedSampleMean()));
52          assertTrue(Double.isNaN(wt.getWeightedPopulationMean()));
53          assertTrue(Double.isNaN(wt.getWeightedSampleVariance()));
54          assertTrue(Double.isNaN(wt.getWeightedSampleStDev()));
55          wt.register(0.1, 1.1);
56          assertEquals(1.0, wt.getMin(), 0.000001);
57          assertEquals(1.0, wt.getMax(), 0.000001);
58          assertEquals(1.0, wt.getWeightedSampleMean(), 0.000001);
59          assertEquals(1.0, wt.getWeightedPopulationMean(), 0.000001);
60          assertTrue(Double.isNaN(wt.getWeightedSampleVariance()));
61          assertTrue(Double.isNaN(wt.getWeightedSampleStDev()));
62          assertEquals(0, wt.getWeightedPopulationVariance(), 0.000001);
63          assertEquals(0, wt.getWeightedPopulationStDev(), 0.0000001);
64          wt.register(0.2, 1.2);
65          assertFalse(Double.isNaN(wt.getWeightedSampleVariance()));
66          assertFalse(Double.isNaN(wt.getWeightedSampleStDev()));
67          wt.register(0.3, 1.3);
68          wt.register(0.4, 1.4);
69          wt.register(0.5, 1.5);
70          wt.register(0.6, 1.6);
71          wt.register(0.7, 1.7);
72          wt.register(0.8, 1.8);
73          wt.register(0.9, 1.9);
74          wt.register(1.0, 2.0);
75  
76          try
77          {
78              wt.register(0.8, 123.456);
79              fail("timestamp out of order should have thrown an exception");
80          }
81          catch (IllegalArgumentException iae)
82          {
83              // Ignore expected exception
84          }
85  
86          assertTrue(wt.isActive());
87          wt.endObservations(1.1);
88          assertFalse(wt.isActive());
89  
90          // Now we check the TimestampWeightedTally
91          assertEquals(2.0, wt.getMax(), 1.0E-6);
92          assertEquals(1.0, wt.getMin(), 1.0E-6);
93          assertEquals(11, wt.getN());
94          assertEquals(1.5 * 0.1 * 11, wt.getWeightedSum(), 1.0E-6);
95          assertEquals(1.5, wt.getWeightedSampleMean(), 1.0E-6);
96  
97          // Let's compute the standard deviation
98          double varianceAccumulator = 0;
99          for (int i = 0; i < 11; i++)
100         {
101             varianceAccumulator += Math.pow(1.5 - (1.0 + i / 10.0), 2);
102         }
103         double variance = varianceAccumulator / 10.0;
104         double stDev = Math.sqrt(variance);
105         assertEquals(variance, wt.getWeightedSampleVariance(), 1.0E-6);
106         assertEquals(stDev, wt.getWeightedSampleStDev(), 1.0E-6);
107         
108         variance = varianceAccumulator / 11.0;
109         stDev = Math.sqrt(variance);
110         assertEquals(variance, wt.getWeightedPopulationVariance(), 1.0E-6);
111         assertEquals(stDev, wt.getWeightedPopulationStDev(), 1.0E-6);
112 
113         try
114         {
115             wt.register(-0.1, 123.456);
116             fail("negative weight should have thrown an exception");
117         }
118         catch (IllegalArgumentException iae)
119         {
120             // Ignore expected exception
121         }
122 
123         // Adding something after the active period should not make a change
124         wt.register(10.0, 20.0);
125         assertFalse(wt.isActive());
126         assertEquals(2.0, wt.getMax(), 1.0E-6);
127         assertEquals(1.0, wt.getMin(), 1.0E-6);
128         assertEquals(11, wt.getN());
129         assertEquals(1.5 * 0.1 * 11, wt.getWeightedSum(), 1.0E-6);
130         assertEquals(1.5, wt.getWeightedSampleMean(), 1.0E-6);
131 
132     }
133 
134     /** Test the TimestampWeightedTally on a simple example. */
135     @Test
136     public void testTimestampWeightedTallySimple()
137     {
138         // From: https://sciencing.com/calculate-time-decimals-5962681.html
139         TimestampWeightedTally wt = new TimestampWeightedTally("simple TimestampWeightedTally statistic");
140         wt.initialize();
141         wt.register(0.0, 86.0);
142         wt.register(13.0, 26.0);
143         wt.register(36.0, 0.0);
144         wt.endObservations(40.0);
145 
146         assertEquals(1716.0, wt.getWeightedSum(), 0.001);
147         assertEquals(42.9, wt.getWeightedSampleMean(), 0.001);
148         assertEquals(3, wt.getN());
149 
150         // When we shift the times, we should get the same answers
151         wt = new TimestampWeightedTally("simple TimestampWeightedTally statistic");
152         wt.initialize();
153         wt.register(10.0, 86.0);
154         wt.register(23.0, 26.0);
155         wt.register(46.0, 0.0);
156         wt.endObservations(50.0);
157 
158         assertEquals(1716.0, wt.getWeightedSum(), 0.001);
159         assertEquals(42.9, wt.getWeightedSampleMean(), 0.001);
160         assertEquals(3, wt.getN());
161 
162         // When we have observations with duration 0, we should get the same answers
163         wt = new TimestampWeightedTally("simple TimestampWeightedTally statistic");
164         wt.initialize();
165         wt.register(0.0, 86.0);
166         wt.register(13.0, 26.0);
167         wt.register(13.0, 0.0);
168         wt.register(13.0, 26.0);
169         wt.register(36.0, 0.0);
170         wt.register(36.0, 0.0);
171         wt.endObservations(40.0);
172 
173         assertEquals(1716.0, wt.getWeightedSum(), 0.001);
174         assertEquals(42.9, wt.getWeightedSampleMean(), 0.001);
175         assertEquals(3, wt.getN()); // non-zero values only
176 
177         // Example from NIST: https://www.itl.nist.gov/div898/software/dataplot/refman2/ch2/weightsd.pdf
178         wt = new TimestampWeightedTally("NIST");
179         wt.register(0, 2);
180         wt.register(1, 3);
181         wt.register(2, 5);
182         wt.register(2, 7);
183         wt.register(2, 11);
184         wt.register(6, 13);
185         wt.register(7, 17);
186         wt.register(9, 19);
187         wt.register(10, 23);
188         wt.endObservations(10.0);
189 
190         assertEquals((2 + 3 + 4 * 11 + 13 + 2 * 17 + 19) / 10.0, wt.getWeightedSampleMean(), 0.001);
191         assertEquals(5.82, wt.getWeightedSampleStDev(), 0.01);
192     }
193 
194     /** Test the TimestampWeightedTally for Calendar-based timestamps. */
195     @Test
196     public void testTimestampWeightedTallyCalendar()
197     {
198         String description = "THIS TIMESTAMP WEIGHTED TALLY IS TESTED";
199         TimestampWeightedTally wt = new TimestampWeightedTally(description);
200 
201         int index = 10;
202         for (int second = 30; second <= 40; second++)
203         {
204             Calendar calendar = new Calendar.Builder().setDate(2000, 2, 2).setTimeOfDay(4, 12, second, 10).build();
205             wt.register(calendar, index++);
206         }
207         assertTrue(wt.isActive());
208         wt.endObservations(new Calendar.Builder().setDate(2000, 2, 2).setTimeOfDay(4, 12, 41, 10).build());
209         assertFalse(wt.isActive());
210 
211         // Now we check the TimestampWeightedTally
212         assertEquals(20.0, wt.getMax(), 1.0E-6);
213         assertEquals(10.0, wt.getMin(), 1.0E-6);
214         assertEquals(11, wt.getN());
215         assertEquals(1.5 * 10000 * 11, wt.getWeightedSum(), 1.0E-2);
216         assertEquals(15.0, wt.getWeightedSampleMean(), 1.0E-6);
217 
218         // Let's compute the standard deviation
219         double variance = 0;
220         for (int i = 0; i < 11; i++)
221         {
222             variance += Math.pow(15.0 - (10 + i), 2);
223         }
224         variance = variance / 10.0; // n - 1
225         double stDev = Math.sqrt(variance);
226 
227         assertEquals(variance, wt.getWeightedSampleVariance(), 1.0E-6);
228         assertEquals(stDev, wt.getWeightedSampleStDev(), 1.0E-6);
229     }
230 
231 }