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  
20  import junit.framework.Test;
21  import junit.framework.TestCase;
22  import junit.framework.TestSuite;
23  
24  import org.apache.commons.math.DimensionMismatchException;
25  import org.apache.commons.math.TestUtils;
26  import org.apache.commons.math.stat.descriptive.moment.Mean;
27  
28  /**
29   * Test cases for the {@link MultivariateSummaryStatistics} class.
30   *
31   * @version $Revision: 566833 $ $Date: 2007-08-16 13:36:33 -0700 (Thu, 16 Aug 2007) $
32   */
33  
34  public class MultivariateSummaryStatisticsTest extends TestCase {
35  
36      public MultivariateSummaryStatisticsTest(String name) {
37          super(name);
38      }
39      
40      public static Test suite() {
41          TestSuite suite = new TestSuite(MultivariateSummaryStatisticsTest.class);
42          suite.setName("MultivariateSummaryStatistics tests");
43          return suite;
44      }
45  
46      public void testSetterInjection() throws Exception {
47          MultivariateSummaryStatistics u = new MultivariateSummaryStatistics(2, true);
48          u.setMeanImpl(new StorelessUnivariateStatistic[] {
49                          new sumMean(), new sumMean()
50                        });
51          u.addValue(new double[] { 1, 2 });
52          u.addValue(new double[] { 3, 4 });
53          assertEquals(4, u.getMean()[0], 1E-14);
54          assertEquals(6, u.getMean()[1], 1E-14);
55          u.clear();
56          u.addValue(new double[] { 1, 2 });
57          u.addValue(new double[] { 3, 4 });
58          assertEquals(4, u.getMean()[0], 1E-14);
59          assertEquals(6, u.getMean()[1], 1E-14);
60          u.clear();
61          u.setMeanImpl(new StorelessUnivariateStatistic[] {
62                          new Mean(), new Mean()
63                        }); // OK after clear
64          u.addValue(new double[] { 1, 2 });
65          u.addValue(new double[] { 3, 4 });
66          assertEquals(2, u.getMean()[0], 1E-14);
67          assertEquals(3, u.getMean()[1], 1E-14);
68      }
69      
70      public void testSetterIllegalState() throws Exception {
71          MultivariateSummaryStatistics u = new MultivariateSummaryStatistics(2, true);
72          u.addValue(new double[] { 1, 2 });
73          u.addValue(new double[] { 3, 4 });
74          try {
75              u.setMeanImpl(new StorelessUnivariateStatistic[] {
76                              new sumMean(), new sumMean()
77                            });
78              fail("Expecting IllegalStateException");
79          } catch (IllegalStateException ex) {
80              // expected
81          }
82      }
83      
84      /**
85       * Bogus mean implementation to test setter injection.
86       * Returns the sum instead of the mean.
87       */
88      static class sumMean implements StorelessUnivariateStatistic {   
89          private static final long serialVersionUID = 6492471391340853423L;
90          private double sum = 0;
91          private long n = 0;
92          public double evaluate(double[] values, int begin, int length) {
93              return 0;
94          }
95          public double evaluate(double[] values) {
96              return 0;
97          }
98          public void clear() {
99            sum = 0; 
100           n = 0;
101         }
102         public long getN() {
103             return n;
104         }
105         public double getResult() {
106             return sum;
107         }
108         public void increment(double d) {
109             sum += d;
110             n++;
111         }
112         public void incrementAll(double[] values, int start, int length) {
113         }
114         public void incrementAll(double[] values) {
115         }   
116     }
117 
118     public void testDimension() {
119         try {
120             new MultivariateSummaryStatistics(2, true).addValue(new double[3]);
121         } catch (DimensionMismatchException dme) {
122             // expected behavior
123         } catch (Exception e) {
124             fail("wrong exception caught");
125         }
126     }
127 
128     /** test stats */
129     public void testStats() throws DimensionMismatchException {
130         MultivariateSummaryStatistics u = new MultivariateSummaryStatistics(2, true);
131         assertEquals(0, u.getN());
132         u.addValue(new double[] { 1, 2 });
133         u.addValue(new double[] { 2, 3 });
134         u.addValue(new double[] { 2, 3 });
135         u.addValue(new double[] { 3, 4 });
136         assertEquals( 4, u.getN());
137         assertEquals( 8, u.getSum()[0], 1.0e-10);
138         assertEquals(12, u.getSum()[1], 1.0e-10);
139         assertEquals(18, u.getSumSq()[0], 1.0e-10);
140         assertEquals(38, u.getSumSq()[1], 1.0e-10);
141         assertEquals( 1, u.getMin()[0], 1.0e-10);
142         assertEquals( 2, u.getMin()[1], 1.0e-10);
143         assertEquals( 3, u.getMax()[0], 1.0e-10);
144         assertEquals( 4, u.getMax()[1], 1.0e-10);
145         assertEquals(2.4849066497880003102, u.getSumLog()[0], 1.0e-10);
146         assertEquals( 4.276666119016055311, u.getSumLog()[1], 1.0e-10);
147         assertEquals( 1.8612097182041991979, u.getGeometricMean()[0], 1.0e-10);
148         assertEquals( 2.9129506302439405217, u.getGeometricMean()[1], 1.0e-10);
149         assertEquals( 2, u.getMean()[0], 1.0e-10);
150         assertEquals( 3, u.getMean()[1], 1.0e-10);
151         assertEquals(Math.sqrt(2.0 / 3.0), u.getStandardDeviation()[0], 1.0e-10);
152         assertEquals(Math.sqrt(2.0 / 3.0), u.getStandardDeviation()[1], 1.0e-10);
153         assertEquals(2.0 / 3.0, u.getCovariance().getEntry(0, 0), 1.0e-10);
154         assertEquals(2.0 / 3.0, u.getCovariance().getEntry(0, 1), 1.0e-10);
155         assertEquals(2.0 / 3.0, u.getCovariance().getEntry(1, 0), 1.0e-10);
156         assertEquals(2.0 / 3.0, u.getCovariance().getEntry(1, 1), 1.0e-10);
157         u.clear();
158         assertEquals(0, u.getN());    
159     }     
160 
161     public void testN0andN1Conditions() throws Exception {
162         MultivariateSummaryStatistics u = new MultivariateSummaryStatistics(1, true);
163         assertTrue(Double.isNaN(u.getMean()[0]));
164         assertTrue(Double.isNaN(u.getStandardDeviation()[0]));
165 
166         /* n=1 */
167         u.addValue(new double[] { 1 });
168         assertEquals(1.0, u.getMean()[0], 1.0e-10);
169         assertEquals(1.0, u.getGeometricMean()[0], 1.0e-10);
170         assertEquals(0.0, u.getStandardDeviation()[0], 1.0e-10);
171 
172         /* n=2 */               
173         u.addValue(new double[] { 2 });
174         assertTrue(u.getStandardDeviation()[0] > 0);
175 
176     }
177 
178     public void testNaNContracts() throws DimensionMismatchException {
179         MultivariateSummaryStatistics u = new MultivariateSummaryStatistics(1, true);
180         assertTrue(Double.isNaN(u.getMean()[0])); 
181         assertTrue(Double.isNaN(u.getMin()[0])); 
182         assertTrue(Double.isNaN(u.getStandardDeviation()[0])); 
183         assertTrue(Double.isNaN(u.getGeometricMean()[0]));
184 
185         u.addValue(new double[] { 1.0 });
186         assertFalse(Double.isNaN(u.getMean()[0])); 
187         assertFalse(Double.isNaN(u.getMin()[0])); 
188         assertFalse(Double.isNaN(u.getStandardDeviation()[0])); 
189         assertFalse(Double.isNaN(u.getGeometricMean()[0]));
190 
191     }
192 
193     public void testSerialization() throws DimensionMismatchException {
194         MultivariateSummaryStatistics u = new MultivariateSummaryStatistics(2, true);
195         // Empty test
196         TestUtils.checkSerializedEquality(u);
197         MultivariateSummaryStatistics s = (MultivariateSummaryStatistics) TestUtils.serializeAndRecover(u);
198         assertEquals(u, s);
199 
200         // Add some data
201         u.addValue(new double[] { 2d, 1d });
202         u.addValue(new double[] { 1d, 1d });
203         u.addValue(new double[] { 3d, 1d });
204         u.addValue(new double[] { 4d, 1d });
205         u.addValue(new double[] { 5d, 1d });
206 
207         // Test again
208         TestUtils.checkSerializedEquality(u);
209         s = (MultivariateSummaryStatistics) TestUtils.serializeAndRecover(u);
210         assertEquals(u, s);
211 
212     }
213 
214     public void testEqualsAndHashCode() throws DimensionMismatchException {
215         MultivariateSummaryStatistics u = new MultivariateSummaryStatistics(2, true);
216         MultivariateSummaryStatistics t = null;
217         int emptyHash = u.hashCode();
218         assertTrue(u.equals(u));
219         assertFalse(u.equals(t));
220         assertFalse(u.equals(new Double(0)));
221         t = new MultivariateSummaryStatistics(2, true);
222         assertTrue(t.equals(u));
223         assertTrue(u.equals(t));
224         assertEquals(emptyHash, t.hashCode());
225 
226         // Add some data to u
227         u.addValue(new double[] { 2d, 1d });
228         u.addValue(new double[] { 1d, 1d });
229         u.addValue(new double[] { 3d, 1d });
230         u.addValue(new double[] { 4d, 1d });
231         u.addValue(new double[] { 5d, 1d });
232         assertFalse(t.equals(u));
233         assertFalse(u.equals(t));
234         assertTrue(u.hashCode() != t.hashCode());
235 
236         //Add data in same order to t
237         t.addValue(new double[] { 2d, 1d });
238         t.addValue(new double[] { 1d, 1d });
239         t.addValue(new double[] { 3d, 1d });
240         t.addValue(new double[] { 4d, 1d });
241         t.addValue(new double[] { 5d, 1d });
242         assertTrue(t.equals(u));
243         assertTrue(u.equals(t));
244         assertEquals(u.hashCode(), t.hashCode());   
245 
246         // Clear and make sure summaries are indistinguishable from empty summary
247         u.clear();
248         t.clear();
249         assertTrue(t.equals(u));
250         assertTrue(u.equals(t));
251         assertEquals(emptyHash, t.hashCode());
252         assertEquals(emptyHash, u.hashCode());
253     }
254 
255 }