/* ---------------------------------------------------------------------
* Numenta Platform for Intelligent Computing (NuPIC)
* Copyright (C) 2014, Numenta, Inc. Unless you have an agreement
* with Numenta, Inc., for a separate license for this software code, the
* following terms and conditions apply:
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Affero Public License for more details.
*
* You should have received a copy of the GNU Affero Public License
* along with this program. If not, see http://www.gnu.org/licenses.
*
* http://numenta.org/licenses/
* ---------------------------------------------------------------------
*/
package org.numenta.nupic.algorithms;
import static org.junit.Assert.*;
import gnu.trove.list.TDoubleList;
import gnu.trove.list.array.TDoubleArrayList;
import org.junit.Test;
import org.numenta.nupic.algorithms.MovingAverage.Calculation;
/**
* Test that the (internal) moving average maintains the averages correctly,
* even for null initial condition and when the number of values goes over
* windowSize. Pass in integers and floats.
*
* @author Numenta
* @author David Ray
*/
public class MovingAverageTest {
@Test
public void testMovingAverage() {
TDoubleList historicalValues = new TDoubleArrayList();
double total = 0;
int windowSize = 3;
TDoubleList expected = new TDoubleArrayList(new double[]{ 3.0 });
Calculation result = MovingAverage.compute(historicalValues, total, 3, windowSize);
assertEquals(3.0, result.getAverage(), 1.0);
assertEquals(expected, result.getHistoricalValues());
assertEquals(3.0, result.getTotal(), 1.0);
expected = new TDoubleArrayList(new double[]{ 3.0, 4.0 });
result = MovingAverage.compute(historicalValues, result.getTotal(), 4, windowSize);
assertEquals(3.5, result.getAverage(), 1.0);
assertEquals(expected, result.getHistoricalValues());
assertEquals(7.0, result.getTotal(), 1.0);
expected = new TDoubleArrayList(new double[]{ 3.0, 4.0, 5.0 });
result = MovingAverage.compute(historicalValues, result.getTotal(), 5.0, windowSize);
assertEquals(4.0, result.getAverage(), 1.0);
assertEquals(expected, result.getHistoricalValues());
assertEquals(12.0, result.getTotal(), 1.0);
// Ensure the first value gets removed
expected = new TDoubleArrayList(new double[]{ 4.0, 5.0, 6.0 });
result = MovingAverage.compute(historicalValues, result.getTotal(), 6.0, windowSize);
assertEquals(5.0, result.getAverage(), 1.0);
assertEquals(expected, result.getHistoricalValues());
assertEquals(15.0, result.getTotal(), 1.0);
}
@Test
public void testMovingAverageInstance() {
MovingAverage ma = new MovingAverage(null, 3);
TDoubleList expected = new TDoubleArrayList(new double[]{ 3.0 });
double newAverage = ma.next(3);
assertEquals(3.0, newAverage, 1.0);
assertEquals(expected, ma.getSlidingWindow());
assertEquals(3.0, ma.getTotal(), 1.0);
expected = new TDoubleArrayList(new double[]{ 3.0, 4.0 });
newAverage = ma.next(4.0);
assertEquals(3.5, newAverage, 1.0);
assertEquals(expected, ma.getSlidingWindow());
assertEquals(7.0, ma.getTotal(), 1.0);
expected = new TDoubleArrayList(new double[]{ 3.0, 4.0, 5.0 });
newAverage = ma.next(5);
assertEquals(4.0, newAverage, 1.0);
assertEquals(expected, ma.getSlidingWindow());
assertEquals(12.0, ma.getTotal(), 1.0);
// Ensure the first value gets removed
expected = new TDoubleArrayList(new double[]{ 4.0, 5.0, 6.0 });
newAverage = ma.next(6);
assertEquals(5.0, newAverage, 1.0);
assertEquals(expected, ma.getSlidingWindow());
assertEquals(15.0, ma.getTotal(), 1.0);
}
/**
* Test the slidingWindow value is correctly assigned when initializing a
* new MovingAverage object.
*/
@Test
public void testMovingAverageSlidingWindowInit() {
MovingAverage ma = new MovingAverage(new TDoubleArrayList(new double[] { 3., 4., 5., }), 3);
assertEquals(new TDoubleArrayList(new double[] { 3., 4., 5., }), ma.getSlidingWindow());
ma = new MovingAverage(null, 3);
assertEquals(new TDoubleArrayList(), ma.getSlidingWindow());
try {
MovingAverage.compute(null, 0, 0, 0);
fail();
}catch(Exception e) {
assertTrue(e.getClass().isAssignableFrom(IllegalArgumentException.class));
assertEquals("slidingWindow cannot be null.", e.getMessage());
}
}
/**
* Test that we get the expected exception and that window size specified
* must be > 0.
*/
@Test
public void testProperConstruction() {
try {
new MovingAverage(new TDoubleArrayList(new double[] { 3., 4., 5., }), 0);
fail();
}catch(Exception e) {
assertTrue(e.getClass().isAssignableFrom(IllegalArgumentException.class));
assertEquals("Window size must be > 0", e.getMessage());
}
}
/**
* Tests the equality of two separate instances with identical settings and state.
*/
@Test
public void testHashCodeAndEquals() {
MovingAverage ma = new MovingAverage(new TDoubleArrayList(new double[] { 3., 4., 5., }), 3);
MovingAverage ma2 = new MovingAverage(new TDoubleArrayList(new double[] { 3., 4., 5., }), 3);
assertTrue(ma.equals(ma2));
assertEquals(ma.hashCode(), ma2.hashCode());
// Check that internal state is changed and that the equals
// methods reflect the change.
ma.next(120.0);
assertFalse(ma.equals(ma2));
assertNotEquals(ma.hashCode(), ma2.hashCode());
}
}