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.math.stat.descriptive;
18  
19  import junit.framework.TestCase;
20  
21  import org.apache.commons.math.TestUtils;
22  import org.apache.commons.math.random.RandomData;
23  import org.apache.commons.math.random.RandomDataImpl;
24  
25  /**
26   * Test cases for the DescriptiveStatistics implementations.
27   *
28   * @version $Revision: 610790 $ $Date: 2008-01-10 06:49:11 -0700 (Thu, 10 Jan 2008) $
29   * @deprecated should be moved down into DescriptiveStatisticsTest
30   *   when DescriptiveStatisticsImpl is removed in 2.0
31   */
32  public abstract class DescriptiveStatisticsAbstractTest extends TestCase {
33      private double var = 0.666666666666666666667;
34      private double max = 3;
35      private double mean = 2;
36      private double min = 1;
37      private double n = 4;
38      private double one = 1;
39      private double std = Math.sqrt(var);
40      private double sum = 8;
41      private double sumSq = 18;
42      private int three = 3;
43      private double tolerance = 10E-15;
44      private float two = 2;
45      
46      public DescriptiveStatisticsAbstractTest(String name) {
47          super(name);
48      }
49      
50      protected abstract DescriptiveStatistics createDescriptiveStatistics();
51      
52      public void setUp() {  
53      }
54  
55      public void testAddValue() {
56          double[] test1 = {5,4,3,2,1,0};
57          double[] test2 = {5,2,1,0,4,3};
58  
59          DescriptiveStatistics stats = createDescriptiveStatistics();
60          stats.setWindowSize(12);
61          
62          for(int i = 0; i < test1.length; i++){
63              stats.addValue(test1[i]);
64          }     
65          
66          double[] test3 = stats.getValues();
67          
68          for(int i = 0; i < 6; i++){
69              assertEquals( "Added value ["+i+"] not equal", 
70              test3[i], test1[i],0.0);
71              //System.out.println(test3[i] + " "+test1[i]);
72          }     
73                  
74          for(int i = 0; i < test2.length; i++){
75              stats.addValue(test2[i]);
76          }     
77   
78          test3 = stats.getValues();  
79          
80          for(int i = 6; i < 12; i++){
81              assertEquals( "Added value ["+i+"] not equal", 
82              test3[i], test2[i-6],0.0);
83              //System.out.println(test3[i] + " "+test2[i-6]);
84          }    
85          
86          for(int i = 0; i < test2.length; i++){
87              stats.addValue(test2[i]);
88          }     
89   
90          test3 = stats.getValues();  
91          
92          for(int i = 0; i < 6; i++){
93              assertEquals( "Added value ["+i+"] not equal", 
94              test3[i], test2[i],0.0);
95              //System.out.println(test3[i] + " "+test2[i]);
96          }  
97          
98          for(int i = 6; i < 12; i++){
99              assertEquals( "Added value ["+i+"] not equal", 
100             test3[i], test2[i-6],0.0);
101             //System.out.println(test3[i] + " "+test2[i-6]);
102         }  
103          
104     }     
105     
106     public void testGetSortedValues() {
107         double[] test1 = {5,4,3,2,1};
108         double[] test2 = {5,2,1,3,4,0};
109         double[] test3 = {1};
110         int[] testi = null;
111         double[] test4 = null;
112         RandomData rd = new RandomDataImpl();
113         tstGetSortedValues(test1);
114         tstGetSortedValues(test2);
115         tstGetSortedValues(test3);
116         for (int i = 0; i < 10; i++) {
117             testi = rd.nextPermutation(10,6);
118             test4 = new double[6];
119             for (int j = 0; j < testi.length; j++) {
120                 test4[j] = (double) testi[j];
121             }
122             tstGetSortedValues(test4);
123         }
124         for (int i = 0; i < 10; i++) {
125             testi = rd.nextPermutation(10,5);
126             test4 = new double[5];
127             for (int j = 0; j < testi.length; j++) {
128                 test4[j] = (double) testi[j];
129             }
130             tstGetSortedValues(test4);
131         }        
132     }
133     
134     public void testN0andN1Conditions() throws Exception {
135         DescriptiveStatistics u = createDescriptiveStatistics();
136                 
137             assertTrue("Mean of n = 0 set should be NaN", 
138                 Double.isNaN( u.getMean() ) );
139             assertTrue("Standard Deviation of n = 0 set should be NaN", 
140                 Double.isNaN( u.getStandardDeviation() ) );
141             assertTrue("Variance of n = 0 set should be NaN",
142                 Double.isNaN(u.getVariance() ) );
143 
144             u.addValue(one);
145 
146             assertTrue( "Mean of n = 1 set should be value of single item n1",
147                 u.getMean() == one);
148             assertTrue( "StdDev of n = 1 set should be zero, instead it is: " 
149                 + u.getStandardDeviation(), u.getStandardDeviation() == 0);
150             assertTrue( "Variance of n = 1 set should be zero", 
151                 u.getVariance() == 0);  
152     }
153 
154     public void testNewInstanceClassNull() {
155         try {
156             DescriptiveStatistics.newInstance((Class)null);
157             fail("null is not a valid descriptive statistics class");
158         } catch (NullPointerException ex) {
159             // success
160         } catch (Exception ex) {
161             fail();
162         }
163         
164     }
165     
166     public void testNewInstanceClassValid() {
167         try {
168             DescriptiveStatistics u = DescriptiveStatistics.newInstance(
169                 DescriptiveStatisticsImpl.class);
170             assertNotNull(u);
171             assertTrue(u instanceof DescriptiveStatisticsImpl);
172         } catch (InstantiationException ex) {
173             fail();
174         } catch (IllegalAccessException ex) {
175             fail();
176         }
177     }
178     
179     public void testPercentiles() {
180         double[] test = {5,4,3,2,1};
181         DescriptiveStatistics u = createDescriptiveStatistics();
182         u.setWindowSize(110);
183         for (int i = 0; i < test.length; i++) {
184             u.addValue(test[i]);
185         }
186         assertEquals("expecting min",1,u.getPercentile(5),10E-12);
187         assertEquals("expecting max",5,u.getPercentile(99),10E-12);
188         assertEquals("expecting middle",3,u.getPercentile(50),10E-12);
189         try {
190             u.getPercentile(0);
191             fail("expecting IllegalArgumentException for getPercentile(0)");
192         } catch (IllegalArgumentException ex) {
193             ;
194         }
195         try {
196             u.getPercentile(120);
197             fail("expecting IllegalArgumentException for getPercentile(120)");
198         } catch (IllegalArgumentException ex) {
199             ;
200         }
201         
202         u.clear();
203         double[] test2 = {1,2,3,4};
204         for (int i = 0; i < test2.length; i++) {
205             u.addValue(test2[i]);
206         }
207         assertEquals("Q1",1.25,u.getPercentile(25),10E-12);
208         assertEquals("Q3",3.75,u.getPercentile(75),10E-12);
209         assertEquals("Q2",2.5,u.getPercentile(50),10E-12);
210         
211         u.clear();
212         double[] test3 = {1};
213         for (int i = 0; i < test3.length; i++) {
214             u.addValue(test3[i]);
215         }
216         assertEquals("Q1",1,u.getPercentile(25),10E-12);
217         assertEquals("Q3",1,u.getPercentile(75),10E-12);
218         assertEquals("Q2",1,u.getPercentile(50),10E-12);
219         
220         u.clear();
221         RandomData rd = new RandomDataImpl();
222         int[] testi = rd.nextPermutation(100,100); // will contain 0-99
223         for (int j = 0; j < testi.length; j++) {
224             u.addValue((double) testi[j]);  //OK, laugh at me for the cast
225         }
226         for (int i = 1; i < 100; i++) {
227             assertEquals("percentile " + i,
228                 (double) i-1 + (double) i*(.01), u.getPercentile(i),10E-12);
229         }
230         
231         u.clear();
232         double[] test4 = {1,2,3,4,100};
233         for (int i = 0; i < test4.length; i++) {
234             u.addValue(test4[i]);
235         }
236         assertEquals("80th",80.8,u.getPercentile(80),10E-12);
237         
238         u.clear();
239         assertTrue("empty value set should return NaN",
240             Double.isNaN(u.getPercentile(50)));
241     }
242     
243         
244         
245     public void testProductAndGeometricMean() throws Exception {
246         DescriptiveStatistics u = createDescriptiveStatistics();
247         u.setWindowSize(10);
248                 
249         u.addValue( 1.0 );
250         u.addValue( 2.0 );
251         u.addValue( 3.0 );
252         u.addValue( 4.0 );
253 
254         //assertEquals( "Product not expected", 
255         //    24.0, u.getProduct(), Double.MIN_VALUE );
256         assertEquals( "Geometric mean not expected", 
257             2.213364, u.getGeometricMean(), 0.00001 );
258 
259         // Now test rolling - StorelessDescriptiveStatistics should discount the contribution
260         // of a discarded element
261         for( int i = 0; i < 10; i++ ) {
262             u.addValue( i + 2 );
263         }
264         // Values should be (2,3,4,5,6,7,8,9,10,11)
265         
266         //assertEquals( "Product not expected", 39916800.0, 
267         //    u.getProduct(), 0.00001 );
268         assertEquals( "Geometric mean not expected", 5.755931, 
269             u.getGeometricMean(), 0.00001 );
270     }
271     
272     /** test stats */
273     public void testSerialization() {
274         DescriptiveStatistics u = createDescriptiveStatistics(); 
275         assertEquals("total count",0,u.getN(),tolerance);
276         u.addValue(one);
277         u.addValue(two);
278         
279         DescriptiveStatistics u2 = (DescriptiveStatistics)TestUtils.serializeAndRecover(u); 
280  
281         u2.addValue(two);
282         u2.addValue(three);
283         
284         assertEquals("N",n,u2.getN(),tolerance);
285         assertEquals("sum",sum,u2.getSum(),tolerance);
286         assertEquals("sumsq",sumSq,u2.getSumsq(),tolerance);
287         assertEquals("var",var,u2.getVariance(),tolerance);
288         assertEquals("std",std,u2.getStandardDeviation(),tolerance);
289         assertEquals("mean",mean,u2.getMean(),tolerance);
290         assertEquals("min",min,u2.getMin(),tolerance);
291         assertEquals("max",max,u2.getMax(),tolerance);
292 
293         u2.clear();
294         assertEquals("total count",0,u2.getN(),tolerance);    
295     }
296                       
297     public void testSkewAndKurtosis() {
298         DescriptiveStatistics u = createDescriptiveStatistics();
299         
300         double[] testArray = 
301         { 12.5, 12, 11.8, 14.2, 14.9, 14.5, 21, 8.2, 10.3, 11.3, 14.1,
302           9.9, 12.2, 12, 12.1, 11, 19.8, 11, 10, 8.8, 9, 12.3 };
303         for( int i = 0; i < testArray.length; i++) {
304             u.addValue( testArray[i]);
305         }
306         
307         assertEquals("mean", 12.40455, u.getMean(), 0.0001);
308         assertEquals("variance", 10.00236, u.getVariance(), 0.0001);
309         assertEquals("skewness", 1.437424, u.getSkewness(), 0.0001);
310         assertEquals("kurtosis", 2.37719, u.getKurtosis(), 0.0001);
311     }       
312 
313     /** test stats */
314     public void testStats() {
315         DescriptiveStatistics u = createDescriptiveStatistics(); 
316         assertEquals("total count",0,u.getN(),tolerance);
317         u.addValue(one);
318         u.addValue(two);
319         u.addValue(two);
320         u.addValue(three);
321         assertEquals("N",n,u.getN(),tolerance);
322         assertEquals("sum",sum,u.getSum(),tolerance);
323         assertEquals("sumsq",sumSq,u.getSumsq(),tolerance);
324         assertEquals("var",var,u.getVariance(),tolerance);
325         assertEquals("std",std,u.getStandardDeviation(),tolerance);
326         assertEquals("mean",mean,u.getMean(),tolerance);
327         assertEquals("min",min,u.getMin(),tolerance);
328         assertEquals("max",max,u.getMax(),tolerance);
329         u.clear();
330         assertEquals("total count",0,u.getN(),tolerance);    
331     }
332     
333     public void testToString() {
334         DescriptiveStatistics u = createDescriptiveStatistics();
335         assertTrue(u.toString().indexOf("NaN") > 0);  
336         assertTrue(u.toString().startsWith("DescriptiveStatistics"));
337         double[] testArray = 
338             { 12.5, 12, 11.8, 14.2, 14.9, 14.5, 21, 8.2, 10.3, 11.3, 14.1,
339                 9.9, 12.2, 12, 12.1, 11, 19.8, 11, 10, 8.8, 9, 12.3 };
340         for( int i = 0; i < testArray.length; i++) {
341             u.addValue( testArray[i]);
342         }        
343         assertTrue(u.toString().indexOf("NaN") == -1);  
344         assertTrue(u.toString().startsWith("DescriptiveStatistics"));
345     }
346     
347     public void testWindowing() {
348         DescriptiveStatistics u = createDescriptiveStatistics();
349         u.setWindowSize(2);
350         
351         u.addValue(1.0);
352         assertEquals(1.0, u.getMean(), tolerance);
353         
354         u.addValue(2.0);
355         assertEquals(1.5, u.getMean(), tolerance);
356         
357         u.addValue(3.0);
358         assertEquals(2.5, u.getMean(), tolerance);
359         
360         u.setWindowSize(1);
361         assertEquals(3.0, u.getMean(), tolerance);
362     }
363     
364     public void testWindowSize() {
365         DescriptiveStatistics u = createDescriptiveStatistics();
366         u.setWindowSize(1234);
367         assertEquals(1234, u.getWindowSize());
368         
369         u.addValue(1.0);
370         u.addValue(2.0);
371         u.addValue(3.0);
372         u.addValue(4.0);
373         u.addValue(5.0);
374         assertEquals(5, u.getN());
375         
376         u.setWindowSize(DescriptiveStatistics.INFINITE_WINDOW);
377         assertEquals(5, u.getN());
378     }
379     
380     private void tstGetSortedValues(double[] test) {
381         DescriptiveStatistics u = createDescriptiveStatistics();
382         u.setWindowSize(test.length);
383         for (int i = 0; i < test.length; i++) {
384             u.addValue(test[i]);
385         }
386         double[] sorted = u.getSortedValues();
387         if (sorted.length != test.length) {
388             fail("wrong length for sorted values array");
389         }
390         for (int i = 0; i < sorted.length-1; i++) {
391             if (sorted[i] > sorted[i+1]) {
392                 fail("sorted values out of sequence");
393             }
394         }
395     }
396     
397 }
398