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    *      https://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  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.stat.descriptive;
23  
24  import org.hipparchus.UnitTestUtils;
25  import org.hipparchus.random.RandomDataGenerator;
26  import org.hipparchus.stat.descriptive.moment.SecondMoment;
27  import org.hipparchus.util.FastMath;
28  import org.junit.jupiter.api.Test;
29  
30  import java.util.Arrays;
31  
32  import static org.junit.jupiter.api.Assertions.assertEquals;
33  import static org.junit.jupiter.api.Assertions.assertNotEquals;
34  import static org.junit.jupiter.api.Assertions.assertTrue;
35  
36  /**
37   * Test cases for {@link StorelessUnivariateStatistic} classes.
38   */
39  public abstract class StorelessUnivariateStatisticAbstractTest
40      extends UnivariateStatisticAbstractTest {
41  
42      /** Small sample arrays */
43      protected double[][] smallSamples = {{}, {1}, {1,2}, {1,2,3}, {1,2,3,4}};
44  
45      /** Return a new instance of the statistic */
46      @Override
47      public abstract StorelessUnivariateStatistic getUnivariateStatistic();
48  
49      /**Expected value for the testArray defined in UnivariateStatisticAbstractTest */
50      @Override
51      public abstract double expectedValue();
52  
53      /**
54       * Verifies that increment() and incrementAll work properly.
55       */
56      @Test
57      public void testIncrementation() {
58  
59          StorelessUnivariateStatistic statistic = getUnivariateStatistic();
60  
61          // Add testArray one value at a time and check result
62          for (int i = 0; i < testArray.length; i++) {
63              statistic.increment(testArray[i]);
64          }
65  
66          assertEquals(expectedValue(), statistic.getResult(), getTolerance());
67          assertEquals(testArray.length, statistic.getN());
68  
69          statistic.clear();
70  
71          // Add testArray all at once and check again
72          statistic.incrementAll(testArray);
73          assertEquals(expectedValue(), statistic.getResult(), getTolerance());
74          assertEquals(testArray.length, statistic.getN());
75  
76          statistic.clear();
77  
78          // Cleared
79          checkClearValue(statistic);
80          assertEquals(0, statistic.getN());
81      }
82  
83      protected void checkClearValue(StorelessUnivariateStatistic statistic){
84          assertTrue(Double.isNaN(statistic.getResult()));
85      }
86  
87      @Test
88      public void testSerialization() {
89          StorelessUnivariateStatistic statistic = getUnivariateStatistic();
90  
91          UnitTestUtils.checkSerializedEquality(statistic);
92          statistic.clear();
93  
94          for (int i = 0; i < testArray.length; i++) {
95              statistic.increment(testArray[i]);
96              if(i % 5 == 0) {
97                  statistic = (StorelessUnivariateStatistic)UnitTestUtils.serializeAndRecover(statistic);
98              }
99          }
100 
101         UnitTestUtils.checkSerializedEquality(statistic);
102         assertEquals(expectedValue(), statistic.getResult(), getTolerance());
103 
104         statistic.clear();
105         checkClearValue(statistic);
106     }
107 
108     @Test
109     public void testEqualsAndHashCode() {
110         StorelessUnivariateStatistic statistic = getUnivariateStatistic();
111         StorelessUnivariateStatistic statistic2 = null;
112 
113         assertNotEquals(statistic, statistic2, "non-null, compared to null");
114         assertEquals(statistic, statistic, "reflexive, non-null");
115 
116         int emptyHash = statistic.hashCode();
117         statistic2 = getUnivariateStatistic();
118         assertEquals(statistic, statistic2, "empty stats should be equal");
119         assertEquals(emptyHash, statistic2.hashCode(), "empty stats should have the same hashcode");
120 
121         statistic.increment(1d);
122         assertEquals(statistic, statistic, "reflexive, non-empty");
123         assertNotEquals(statistic, statistic2, "non-empty, compared to empty");
124         assertNotEquals(statistic2, statistic, "non-empty, compared to empty");
125         assertTrue(statistic.hashCode() != emptyHash,
126                    "non-empty stat should have different hashcode from empty stat");
127 
128         statistic2.increment(1d);
129         assertEquals(statistic, statistic2, "stats with same data should be equal");
130         assertEquals(statistic.hashCode(), statistic2.hashCode(), "stats with same data should have the same hashcode");
131 
132         statistic.increment(Double.POSITIVE_INFINITY);
133         assertNotEquals(statistic2, statistic, "stats with different n's should not be equal");
134         assertTrue(statistic.hashCode() != statistic2.hashCode(),
135                    "stats with different n's should have different hashcodes");
136 
137         statistic2.increment(Double.POSITIVE_INFINITY);
138         assertEquals(statistic, statistic2, "stats with same data should be equal");
139         assertEquals(statistic.hashCode(), statistic2.hashCode(), "stats with same data should have the same hashcode");
140 
141         statistic.clear();
142         statistic2.clear();
143         assertEquals(statistic, statistic2, "cleared stats should be equal");
144         assertEquals(emptyHash, statistic2.hashCode(), "cleared stats should have thashcode of empty stat");
145         assertEquals(emptyHash, statistic.hashCode(), "cleared stats should have thashcode of empty stat");
146 
147     }
148 
149     @Test
150     public void testMomentSmallSamples() {
151         UnivariateStatistic stat = getUnivariateStatistic();
152         if (stat instanceof SecondMoment) {
153             SecondMoment moment = (SecondMoment) getUnivariateStatistic();
154             assertTrue(Double.isNaN(moment.getResult()));
155             moment.increment(1d);
156             assertEquals(0d, moment.getResult(), 0);
157         }
158     }
159 
160     /**
161      * Make sure that evaluate(double[]) and inrementAll(double[]),
162      * getResult() give same results.
163      */
164     @Test
165     public void testConsistency() {
166         StorelessUnivariateStatistic stat = getUnivariateStatistic();
167         stat.incrementAll(testArray);
168         assertEquals(stat.getResult(), stat.evaluate(testArray), getTolerance());
169         for (int i = 0; i < smallSamples.length; i++) {
170             stat.clear();
171             for (int j =0; j < smallSamples[i].length; j++) {
172                 stat.increment(smallSamples[i][j]);
173             }
174             UnitTestUtils.customAssertEquals(stat.getResult(), stat.evaluate(smallSamples[i]), getTolerance());
175         }
176     }
177 
178     /**
179      * Verifies that copied statistics remain equal to originals when
180      * incremented the same way.
181      */
182     @Test
183     public void testCopyConsistency() {
184 
185         StorelessUnivariateStatistic master = getUnivariateStatistic();
186 
187         StorelessUnivariateStatistic replica = null;
188 
189         // Randomly select a portion of testArray to load first
190         long index = FastMath.round((FastMath.random()) * testArray.length);
191 
192         // Put first half in master and copy master to replica
193         master.incrementAll(testArray, 0, (int) index);
194         replica = master.copy();
195 
196         // Check same
197         assertEquals(replica, master);
198         assertEquals(master, replica);
199 
200         // Now add second part to both and check again
201         master.incrementAll(testArray, (int) index, (int) (testArray.length - index));
202         replica.incrementAll(testArray, (int) index, (int) (testArray.length - index));
203         assertEquals(replica, master);
204         assertEquals(master, replica);
205     }
206 
207     @Test
208     public void testSerial() {
209         StorelessUnivariateStatistic s = getUnivariateStatistic();
210         assertEquals(s, UnitTestUtils.serializeAndRecover(s));
211     }
212 
213     /**
214      * Make sure that evaluate(double[]) does not alter the internal state.
215      */
216     @Test
217     public void testEvaluateInternalState() {
218         StorelessUnivariateStatistic stat = getUnivariateStatistic();
219         stat.evaluate(testArray);
220         assertEquals(0, stat.getN());
221 
222         stat.incrementAll(testArray);
223 
224         StorelessUnivariateStatistic savedStatistic = stat.copy();
225 
226         assertNotEquals(stat.getResult(), stat.evaluate(testArray, 0, 5), getTolerance());
227 
228         assertEquals(savedStatistic.getResult(), stat.getResult(), 0.0);
229         assertEquals(savedStatistic.getN(), stat.getN());
230     }
231 
232     /**
233      * Test that the aggregate operation is consistent with individual increment.
234      */
235     @Test
236     @SuppressWarnings("unchecked")
237     public <T> void testAggregate() {
238         // Union of both statistics.
239         StorelessUnivariateStatistic statU = getUnivariateStatistic();
240         if (!(statU instanceof AggregatableStatistic<?>)) {
241             return;
242         }
243 
244         // Aggregated statistic.
245         AggregatableStatistic<T> aggregated = (AggregatableStatistic<T>) getUnivariateStatistic();
246         StorelessUnivariateStatistic statAgg = (StorelessUnivariateStatistic) aggregated;
247 
248         final RandomDataGenerator randomDataGenerator = new RandomDataGenerator(100);
249         // Create Set A
250         StorelessUnivariateStatistic statA = getUnivariateStatistic();
251         for (int i = 0; i < 10; i++) {
252             final double val = randomDataGenerator.nextGaussian();
253             statA.increment(val);
254             statU.increment(val);
255         }
256 
257         aggregated.aggregate((T) statA);
258         assertEquals(statA.getN(), statAgg.getN(), getTolerance());
259         assertEquals(statA.getResult(), statAgg.getResult(), getTolerance());
260 
261         // Create Set B
262         StorelessUnivariateStatistic statB = getUnivariateStatistic();
263         for (int i = 0; i < 4; i++) {
264             final double val = randomDataGenerator.nextGaussian();
265             statB.increment(val);
266             statU.increment(val);
267         }
268 
269         aggregated.aggregate((T) statB);
270         assertEquals(statU.getN(), statAgg.getN(), getTolerance());
271         assertEquals(statU.getResult(), statAgg.getResult(), getTolerance());
272     }
273 
274     @Test
275     public void testConsume() {
276         StorelessUnivariateStatistic stat = getUnivariateStatistic();
277 
278         Arrays.stream(testArray)
279               .forEach(stat);
280 
281         assertEquals(expectedValue(), stat.getResult(), getTolerance());
282 
283         StorelessUnivariateStatistic stat2 = getUnivariateStatistic();
284         stat2.incrementAll(testArray);
285         assertEquals(stat2.getResult(), stat.getResult(), getTolerance());
286     }
287 }