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.random;
18  
19  import junit.framework.Test;
20  import junit.framework.TestSuite;
21  
22  import java.io.BufferedReader;
23  import java.io.File;
24  import java.io.IOException;
25  import java.io.InputStreamReader;
26  import java.net.URL;
27  import java.util.ArrayList;
28  import java.util.Iterator;
29  
30  import org.apache.commons.math.RetryTestCase;
31  import org.apache.commons.math.TestUtils;
32  import org.apache.commons.math.stat.descriptive.SummaryStatistics;
33  
34  /**
35   * Test cases for the EmpiricalDistribution class
36   *
37   * @version $Revision: 610789 $ $Date: 2008-01-10 06:46:49 -0700 (Thu, 10 Jan 2008) $
38   */
39  
40  public final class EmpiricalDistributionTest extends RetryTestCase {
41  
42      protected EmpiricalDistribution empiricalDistribution = null;
43      protected EmpiricalDistribution empiricalDistribution2 = null;
44      protected File file = null;
45      protected URL url = null; 
46      protected double[] dataArray = null;
47      
48      public EmpiricalDistributionTest(String name) {
49          super(name);
50      }
51  
52      public void setUp() throws IOException {
53          empiricalDistribution = new EmpiricalDistributionImpl(100);
54          url = getClass().getResource("testData.txt");
55          
56          empiricalDistribution2 = new EmpiricalDistributionImpl(100);
57          BufferedReader in = 
58                  new BufferedReader(new InputStreamReader(
59                          url.openStream()));
60          String str = null;
61          ArrayList list = new ArrayList();
62          while ((str = in.readLine()) != null) {
63              list.add(Double.valueOf(str));
64          }
65          in.close();
66          in = null;
67          
68          dataArray = new double[list.size()];
69          int i = 0;
70          for (Iterator iter = list.iterator(); iter.hasNext();) {
71              dataArray[i] = ((Double)iter.next()).doubleValue();
72              i++;
73          }                 
74      }
75  
76      public static Test suite() {
77          TestSuite suite = new TestSuite(EmpiricalDistributionTest.class);
78          suite.setName("EmpiricalDistribution Tests");
79          return suite;
80      }
81  
82      /**
83       * Test EmpiricalDistrbution.load() using sample data file.<br> 
84       * Check that the sampleCount, mu and sigma match data in 
85       * the sample data file.
86       */
87      public void testLoad() throws Exception {
88          empiricalDistribution.load(url);   
89          // testData File has 10000 values, with mean ~ 5.0, std dev ~ 1
90          // Make sure that loaded distribution matches this
91          assertEquals(empiricalDistribution.getSampleStats().getN(),1000,10E-7);
92          //TODO: replace with statistical tests
93          assertEquals
94              (empiricalDistribution.getSampleStats().getMean(),
95                  5.069831575018909,10E-7);
96          assertEquals
97            (empiricalDistribution.getSampleStats().getStandardDeviation(),
98                  1.0173699343977738,10E-7);
99      }
100 
101     /**
102      * Test EmpiricalDistrbution.load(double[]) using data taken from
103      * sample data file.<br> 
104      * Check that the sampleCount, mu and sigma match data in 
105      * the sample data file.
106      */
107     public void testDoubleLoad() throws Exception {
108         empiricalDistribution2.load(dataArray);   
109         // testData File has 10000 values, with mean ~ 5.0, std dev ~ 1
110         // Make sure that loaded distribution matches this
111         assertEquals(empiricalDistribution2.getSampleStats().getN(),1000,10E-7);
112         //TODO: replace with statistical tests
113         assertEquals
114             (empiricalDistribution2.getSampleStats().getMean(),
115                 5.069831575018909,10E-7);
116         assertEquals
117           (empiricalDistribution2.getSampleStats().getStandardDeviation(),
118                 1.0173699343977738,10E-7);
119         
120         double[] bounds = empiricalDistribution2.getUpperBounds();
121         assertEquals(bounds.length, 100);
122         assertEquals(bounds[99], 1.0, 10e-12);
123           
124     }
125    
126     /** 
127       * Generate 1000 random values and make sure they look OK.<br>
128       * Note that there is a non-zero (but very small) probability that
129       * these tests will fail even if the code is working as designed.
130       */
131     public void testNext() throws Exception {
132         tstGen(0.1);
133         tstDoubleGen(0.1);
134     }
135     
136     /**
137       * Make sure exception thrown if digest getNext is attempted
138       * before loading empiricalDistribution.
139      */
140     public void testNexFail() {
141         try {
142             empiricalDistribution.getNextValue();
143             empiricalDistribution2.getNextValue();
144             fail("Expecting IllegalStateException");
145         } catch (IllegalStateException ex) {;}
146     }
147     
148     /**
149      * Make sure we can handle a grid size that is too fine
150      */
151     public void testGridTooFine() throws Exception {
152         empiricalDistribution = new EmpiricalDistributionImpl(1001);
153         tstGen(0.1);    
154         empiricalDistribution2 = new EmpiricalDistributionImpl(1001);           
155         tstDoubleGen(0.1);
156     }
157     
158     /**
159      * How about too fat?
160      */
161     public void testGridTooFat() throws Exception {
162         empiricalDistribution = new EmpiricalDistributionImpl(1);
163         tstGen(5); // ridiculous tolerance; but ridiculous grid size
164                    // really just checking to make sure we do not bomb
165         empiricalDistribution2 = new EmpiricalDistributionImpl(1);           
166         tstDoubleGen(5);           
167     }
168     
169     /**
170      * Test bin index overflow problem (BZ 36450)
171      */
172     public void testBinIndexOverflow() throws Exception {
173         double[] x = new double[] {9474.94326071674, 2080107.8865462579};
174         new EmpiricalDistributionImpl().load(x);
175     }
176     
177     public void testSerialization() {
178         // Empty
179         EmpiricalDistribution dist = new EmpiricalDistributionImpl();
180         EmpiricalDistribution dist2 = (EmpiricalDistribution) TestUtils.serializeAndRecover(dist);
181         verifySame(dist, dist2);
182         
183         // Loaded
184         empiricalDistribution2.load(dataArray);   
185         dist2 = (EmpiricalDistribution) TestUtils.serializeAndRecover(empiricalDistribution2);
186         verifySame(empiricalDistribution2, dist2);
187     }
188     
189     private void verifySame(EmpiricalDistribution d1, EmpiricalDistribution d2) {
190         assertEquals(d1.isLoaded(), d2.isLoaded());
191         assertEquals(d1.getBinCount(), d2.getBinCount());
192         assertEquals(d1.getSampleStats(), d2.getSampleStats());
193         if (d1.isLoaded()) {
194             for (int i = 0;  i < d1.getUpperBounds().length; i++) {
195                 assertEquals(d1.getUpperBounds()[i], d2.getUpperBounds()[i], 0);
196             }
197             assertEquals(d1.getBinStats(), d2.getBinStats());
198         }
199     }
200     
201     private void tstGen(double tolerance)throws Exception {
202         empiricalDistribution.load(url);   
203         SummaryStatistics stats = new SummaryStatistics();
204         for (int i = 1; i < 1000; i++) {
205             stats.addValue(empiricalDistribution.getNextValue());
206         }
207         assertEquals("mean", stats.getMean(),5.069831575018909,tolerance);
208         assertEquals
209          ("std dev", stats.getStandardDeviation(),1.0173699343977738,tolerance);
210     }
211 
212     private void tstDoubleGen(double tolerance)throws Exception {
213         empiricalDistribution2.load(dataArray);   
214         SummaryStatistics stats = new SummaryStatistics();
215         for (int i = 1; i < 1000; i++) {
216             stats.addValue(empiricalDistribution2.getNextValue());
217         }
218         assertEquals("mean", stats.getMean(),5.069831575018909,tolerance);
219         assertEquals
220          ("std dev", stats.getStandardDeviation(),1.0173699343977738,tolerance);
221     }
222 }