package org.djutils.stats.summarizers; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.util.Calendar; import org.junit.Test; /** * The TimestampWeightedTallyTest test the weighted tally that receives observations with a timestamp. *
* Copyright (c) 2002-2021 Delft University of Technology, Jaffalaan 5, 2628 BX Delft, the Netherlands. All rights reserved. See
* for project information https://simulation.tudelft.nl. The DSOL
* project is distributed under a three-clause BSD-style license, which can be found at
*
* https://simulation.tudelft.nl/dsol/3.0/license.html.
*
* @author Peter Jacobs
* @since 1.5
*/
public class TimestampWeightedTallyTest
{
/** Test the TimestampWeightedTally on Number based timestamps. */
@Test
public void testTimestampWeightedTallyNumber()
{
String description = "THIS TIMESTAMP WEIGHTED TALLY IS TESTED";
TimestampWeightedTally wt = new TimestampWeightedTally(description);
// check the description
assertEquals(description, wt.getDescription());
assertTrue(wt.toString().contains(description));
// now we check the initial values
assertTrue(wt.isActive());
assertTrue(Double.isNaN(wt.getMin()));
assertTrue(Double.isNaN(wt.getMax()));
assertTrue(Double.isNaN(wt.getWeightedSampleMean()));
assertTrue(Double.isNaN(wt.getWeightedPopulationMean()));
assertTrue(Double.isNaN(wt.getWeightedSampleVariance()));
assertTrue(Double.isNaN(wt.getWeightedSampleStDev()));
assertEquals(0.0, wt.getWeightedSum(), 0.0);
assertEquals(0L, wt.getN());
wt.ingest(0.0, 1.0);
assertTrue(Double.isNaN(wt.getMin()));
assertTrue(Double.isNaN(wt.getMax()));
assertTrue(Double.isNaN(wt.getWeightedSampleMean()));
assertTrue(Double.isNaN(wt.getWeightedPopulationMean()));
assertTrue(Double.isNaN(wt.getWeightedSampleVariance()));
assertTrue(Double.isNaN(wt.getWeightedSampleStDev()));
wt.ingest(0.1, 1.1);
assertEquals(1.0, wt.getMin(), 0.000001);
assertEquals(1.0, wt.getMax(), 0.000001);
assertEquals(1.0, wt.getWeightedSampleMean(), 0.000001);
assertEquals(1.0, wt.getWeightedPopulationMean(), 0.000001);
assertTrue(Double.isNaN(wt.getWeightedSampleVariance()));
assertTrue(Double.isNaN(wt.getWeightedSampleStDev()));
assertEquals(0, wt.getWeightedPopulationVariance(), 0.000001);
assertEquals(0, wt.getWeightedPopulationStDev(), 0.0000001);
wt.ingest(0.2, 1.2);
assertFalse(Double.isNaN(wt.getWeightedSampleVariance()));
assertFalse(Double.isNaN(wt.getWeightedSampleStDev()));
wt.ingest(0.3, 1.3);
wt.ingest(0.4, 1.4);
wt.ingest(0.5, 1.5);
wt.ingest(0.6, 1.6);
wt.ingest(0.7, 1.7);
wt.ingest(0.8, 1.8);
wt.ingest(0.9, 1.9);
wt.ingest(1.0, 2.0);
try
{
wt.ingest(0.8, 123.456);
fail("timestamp out of order should have thrown an exception");
}
catch (IllegalArgumentException iae)
{
// Ignore expected exception
}
assertTrue(wt.isActive());
wt.endObservations(1.1);
assertFalse(wt.isActive());
// Now we check the TimestampWeightedTally
assertEquals(2.0, wt.getMax(), 1.0E-6);
assertEquals(1.0, wt.getMin(), 1.0E-6);
assertEquals(11, wt.getN());
assertEquals(1.5 * 0.1 * 11, wt.getWeightedSum(), 1.0E-6);
assertEquals(1.5, wt.getWeightedSampleMean(), 1.0E-6);
// Let's compute the standard deviation
double varianceAccumulator = 0;
for (int i = 0; i < 11; i++)
{
varianceAccumulator += Math.pow(1.5 - (1.0 + i / 10.0), 2);
}
double variance = varianceAccumulator / 10.0;
double stDev = Math.sqrt(variance);
assertEquals(variance, wt.getWeightedSampleVariance(), 1.0E-6);
assertEquals(stDev, wt.getWeightedSampleStDev(), 1.0E-6);
variance = varianceAccumulator / 11.0;
stDev = Math.sqrt(variance);
assertEquals(variance, wt.getWeightedPopulationVariance(), 1.0E-6);
assertEquals(stDev, wt.getWeightedPopulationStDev(), 1.0E-6);
try
{
wt.ingest(-0.1, 123.456);
fail("negative weight should have thrown an exception");
}
catch (IllegalArgumentException iae)
{
// Ignore expected exception
}
// Adding something after the active period should not make a change
wt.ingest(10.0, 20.0);
assertFalse(wt.isActive());
assertEquals(2.0, wt.getMax(), 1.0E-6);
assertEquals(1.0, wt.getMin(), 1.0E-6);
assertEquals(11, wt.getN());
assertEquals(1.5 * 0.1 * 11, wt.getWeightedSum(), 1.0E-6);
assertEquals(1.5, wt.getWeightedSampleMean(), 1.0E-6);
}
/** Test the TimestampWeightedTally on a simple example. */
@Test
public void testTimestampWeightedTallySimple()
{
// From: https://sciencing.com/calculate-time-decimals-5962681.html
TimestampWeightedTally wt = new TimestampWeightedTally("simple TimestampWeightedTally statistic");
wt.initialize();
wt.ingest(0.0, 86.0);
wt.ingest(13.0, 26.0);
wt.ingest(36.0, 0.0);
wt.endObservations(40.0);
assertEquals(1716.0, wt.getWeightedSum(), 0.001);
assertEquals(42.9, wt.getWeightedSampleMean(), 0.001);
assertEquals(3, wt.getN());
// When we shift the times, we should get the same answers
wt = new TimestampWeightedTally("simple TimestampWeightedTally statistic");
wt.initialize();
wt.ingest(10.0, 86.0);
wt.ingest(23.0, 26.0);
wt.ingest(46.0, 0.0);
wt.endObservations(50.0);
assertEquals(1716.0, wt.getWeightedSum(), 0.001);
assertEquals(42.9, wt.getWeightedSampleMean(), 0.001);
assertEquals(3, wt.getN());
// When we have observations with duration 0, we should get the same answers
wt = new TimestampWeightedTally("simple TimestampWeightedTally statistic");
wt.initialize();
wt.ingest(0.0, 86.0);
wt.ingest(13.0, 26.0);
wt.ingest(13.0, 0.0);
wt.ingest(13.0, 26.0);
wt.ingest(36.0, 0.0);
wt.ingest(36.0, 0.0);
wt.endObservations(40.0);
assertEquals(1716.0, wt.getWeightedSum(), 0.001);
assertEquals(42.9, wt.getWeightedSampleMean(), 0.001);
assertEquals(3, wt.getN()); // non-zero values only
// Example from NIST: https://www.itl.nist.gov/div898/software/dataplot/refman2/ch2/weightsd.pdf
wt = new TimestampWeightedTally("NIST");
wt.ingest(0, 2);
wt.ingest(1, 3);
wt.ingest(2, 5);
wt.ingest(2, 7);
wt.ingest(2, 11);
wt.ingest(6, 13);
wt.ingest(7, 17);
wt.ingest(9, 19);
wt.ingest(10, 23);
wt.endObservations(10.0);
assertEquals((2 + 3 + 4 * 11 + 13 + 2 * 17 + 19) / 10.0, wt.getWeightedSampleMean(), 0.001);
assertEquals(5.82, wt.getWeightedSampleStDev(), 0.01);
}
/** Test the TimestampWeightedTally for Calendar-based timestamps. */
@Test
public void testTimestampWeightedTallyCalendar()
{
String description = "THIS TIMESTAMP WEIGHTED TALLY IS TESTED";
TimestampWeightedTally wt = new TimestampWeightedTally(description);
int index = 10;
for (int second = 30; second <= 40; second++)
{
Calendar calendar = new Calendar.Builder().setDate(2000, 2, 2).setTimeOfDay(4, 12, second, 10).build();
wt.ingest(calendar, index++);
}
assertTrue(wt.isActive());
wt.endObservations(new Calendar.Builder().setDate(2000, 2, 2).setTimeOfDay(4, 12, 41, 10).build());
assertFalse(wt.isActive());
// Now we check the TimestampWeightedTally
assertEquals(20.0, wt.getMax(), 1.0E-6);
assertEquals(10.0, wt.getMin(), 1.0E-6);
assertEquals(11, wt.getN());
assertEquals(1.5 * 10000 * 11, wt.getWeightedSum(), 1.0E-2);
assertEquals(15.0, wt.getWeightedSampleMean(), 1.0E-6);
// Let's compute the standard deviation
double variance = 0;
for (int i = 0; i < 11; i++)
{
variance += Math.pow(15.0 - (10 + i), 2);
}
variance = variance / 10.0; // n - 1
double stDev = Math.sqrt(variance);
assertEquals(variance, wt.getWeightedSampleVariance(), 1.0E-6);
assertEquals(stDev, wt.getWeightedSampleStDev(), 1.0E-6);
}
}