View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.math4.legacy.stat.descriptive.moment;
18  
19  import org.apache.commons.math4.legacy.stat.descriptive.StorelessUnivariateStatisticAbstractTest;
20  import org.apache.commons.math4.legacy.stat.descriptive.UnivariateStatistic;
21  import org.apache.commons.math4.legacy.core.MathArrays;
22  import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
23  import org.junit.Assert;
24  import org.junit.Test;
25  import org.junit.jupiter.api.Assertions;
26  
27  /**
28   * Test cases for the {@link UnivariateStatistic} class.
29   *
30   */
31  public class VarianceTest extends StorelessUnivariateStatisticAbstractTest{
32  
33      protected Variance stat;
34  
35      /**
36       * {@inheritDoc}
37       */
38      @Override
39      public UnivariateStatistic getUnivariateStatistic() {
40          return new Variance();
41      }
42  
43      /**
44       * {@inheritDoc}
45       */
46      @Override
47      public double expectedValue() {
48          return this.var;
49      }
50  
51      /**Expected value for  the testArray defined in UnivariateStatisticAbstractTest */
52      public double expectedWeightedValue() {
53          return this.weightedVar;
54      }
55  
56      /**
57       * Make sure Double.NaN is returned iff n = 0
58       *
59       */
60      @Test
61      public void testNaN() {
62          StandardDeviation std = new StandardDeviation();
63          Assert.assertTrue(Double.isNaN(std.getResult()));
64          std.increment(1d);
65          Assert.assertEquals(0d, std.getResult(), 0);
66      }
67  
68      /**
69       * Test population version of variance
70       */
71      @Test
72      public void testPopulation() {
73          double[] values = {-1.0d, 3.1d, 4.0d, -2.1d, 22d, 11.7d, 3d, 14d};
74          SecondMoment m = new SecondMoment();
75          m.incrementAll(values);  // side effect is to add values
76          Variance v1 = new Variance();
77          v1.setBiasCorrected(false);
78          Assert.assertEquals(populationVariance(values), v1.evaluate(values), 1E-14);
79          v1.incrementAll(values);
80          Assert.assertEquals(populationVariance(values), v1.getResult(), 1E-14);
81          v1 = new Variance(false, m);
82          Assert.assertEquals(populationVariance(values), v1.getResult(), 1E-14);
83          v1 = new Variance(false);
84          Assert.assertEquals(populationVariance(values), v1.evaluate(values), 1E-14);
85          v1.incrementAll(values);
86          Assert.assertEquals(populationVariance(values), v1.getResult(), 1E-14);
87      }
88  
89      /**
90       * Definitional formula for population variance
91       */
92      protected double populationVariance(double[] v) {
93          double mean = new Mean().evaluate(v);
94          double sum = 0;
95          for (int i = 0; i < v.length; i++) {
96             sum += (v[i] - mean) * (v[i] - mean);
97          }
98          return sum / v.length;
99      }
100 
101     @Test
102     public void testWeightedVariance() {
103         Variance variance = new Variance();
104         Assert.assertEquals(expectedWeightedValue(),
105                 variance.evaluate(testArray, testWeightsArray, 0, testArray.length), getTolerance());
106 
107         // All weights = 1 -> weighted variance = unweighted variance
108         Assert.assertEquals(expectedValue(),
109                 variance.evaluate(testArray, unitWeightsArray, 0, testArray.length), getTolerance());
110 
111         // All weights the same -> when weights are normalized to sum to the length of the values array,
112         // weighted variance = unweighted value
113         Assert.assertEquals(expectedValue(),
114                 variance.evaluate(testArray, MathArrays.normalizeArray(identicalWeightsArray, testArray.length),
115                         0, testArray.length), getTolerance());
116     }
117 
118     @Test
119     public void testZeroWeights() {
120         Variance variance = new Variance();
121         final double[] values = {1, 2, 3, 4};
122         final double[] weights = new double[values.length];
123 
124         // No weights
125         Assertions.assertThrows(MathIllegalArgumentException.class, () -> {
126             variance.evaluate(values, weights);
127         });
128 
129         // No length
130         final int begin = 1;
131         final int zeroLength = 0;
132         Assertions.assertEquals(Double.NaN, variance.evaluate(values, weights, begin, zeroLength));
133 
134         // One weight (must be non-zero)
135         Assertions.assertThrows(MathIllegalArgumentException.class, () -> {
136             variance.evaluate(values, weights, begin, zeroLength + 1);
137         });
138 
139         weights[begin] = Double.MIN_VALUE;
140         Assertions.assertEquals(0.0, variance.evaluate(values, weights, begin, zeroLength + 1));
141     }
142 }