1   /*
2    * Copyright 2003-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.commons.math.random;
17  
18  import junit.framework.Test;
19  import junit.framework.TestSuite;
20  
21  import java.io.BufferedReader;
22  import java.io.File;
23  import java.io.IOException;
24  import java.io.InputStreamReader;
25  import java.net.URL;
26  import java.util.ArrayList;
27  import java.util.Iterator;
28  
29  import org.apache.commons.math.RetryTestCase;
30  import org.apache.commons.math.TestUtils;
31  import org.apache.commons.math.stat.descriptive.SummaryStatistics;
32  
33  /***
34   * Test cases for the EmpiricalDistribution class
35   *
36   * @version $Revision: 1.19 $ $Date: 2004/10/08 05:08:19 $
37   */
38  
39  public final class EmpiricalDistributionTest extends RetryTestCase {
40  
41      protected EmpiricalDistribution empiricalDistribution = null;
42      protected EmpiricalDistribution empiricalDistribution2 = null;
43      protected File file = null;
44      protected URL url = null; 
45      protected double[] dataArray = null;
46      
47      public EmpiricalDistributionTest(String name) {
48          super(name);
49      }
50  
51      public void setUp() throws IOException {
52          empiricalDistribution = new EmpiricalDistributionImpl(100);
53          url = getClass().getResource("testData.txt");
54          
55          empiricalDistribution2 = new EmpiricalDistributionImpl(100);
56          BufferedReader in = 
57                  new BufferedReader(new InputStreamReader(
58                          url.openStream()));
59          String str = null;
60          ArrayList list = new ArrayList();
61          while ((str = in.readLine()) != null) {
62              list.add(Double.valueOf(str));
63          }
64          in.close();
65          in = null;
66          
67          dataArray = new double[list.size()];
68          int i = 0;
69          for (Iterator iter = list.iterator(); iter.hasNext();) {
70              dataArray[i] = ((Double)iter.next()).doubleValue();
71              i++;
72          }                 
73      }
74  
75      public static Test suite() {
76          TestSuite suite = new TestSuite(EmpiricalDistributionTest.class);
77          suite.setName("EmpiricalDistribution Tests");
78          return suite;
79      }
80  
81      /***
82       * Test EmpiricalDistrbution.load() using sample data file.<br> 
83       * Check that the sampleCount, mu and sigma match data in 
84       * the sample data file.
85       */
86      public void testLoad() throws Exception {
87          empiricalDistribution.load(url);   
88          // testData File has 10000 values, with mean ~ 5.0, std dev ~ 1
89          // Make sure that loaded distribution matches this
90          assertEquals(empiricalDistribution.getSampleStats().getN(),1000,10E-7);
91          //TODO: replace with statistical tests
92          assertEquals
93              (empiricalDistribution.getSampleStats().getMean(),
94                  5.069831575018909,10E-7);
95          assertEquals
96            (empiricalDistribution.getSampleStats().getStandardDeviation(),
97                  1.0173699343977738,10E-7);
98      }
99  
100     /***
101      * Test EmpiricalDistrbution.load(double[]) using data taken from
102      * sample data file.<br> 
103      * Check that the sampleCount, mu and sigma match data in 
104      * the sample data file.
105      */
106     public void testDoubleLoad() throws Exception {
107         empiricalDistribution2.load(dataArray);   
108         // testData File has 10000 values, with mean ~ 5.0, std dev ~ 1
109         // Make sure that loaded distribution matches this
110         assertEquals(empiricalDistribution2.getSampleStats().getN(),1000,10E-7);
111         //TODO: replace with statistical tests
112         assertEquals
113             (empiricalDistribution2.getSampleStats().getMean(),
114                 5.069831575018909,10E-7);
115         assertEquals
116           (empiricalDistribution2.getSampleStats().getStandardDeviation(),
117                 1.0173699343977738,10E-7);
118     }
119    
120     /*** 
121       * Generate 1000 random values and make sure they look OK.<br>
122       * Note that there is a non-zero (but very small) probability that
123       * these tests will fail even if the code is working as designed.
124       */
125     public void testNext() throws Exception {
126         tstGen(0.1);
127         tstDoubleGen(0.1);
128     }
129     
130     /***
131       * Make sure exception thrown if digest getNext is attempted
132       * before loading empiricalDistribution.
133      */
134     public void testNexFail() {
135         try {
136             empiricalDistribution.getNextValue();
137             empiricalDistribution2.getNextValue();
138             fail("Expecting IllegalStateException");
139         } catch (IllegalStateException ex) {;}
140     }
141     
142     /***
143      * Make sure we can handle a grid size that is too fine
144      */
145     public void testGridTooFine() throws Exception {
146         empiricalDistribution = new EmpiricalDistributionImpl(1001);
147         tstGen(0.1);    
148         empiricalDistribution2 = new EmpiricalDistributionImpl(1001);           
149         tstDoubleGen(0.1);
150     }
151     
152     /***
153      * How about too fat?
154      */
155     public void testGridTooFat() throws Exception {
156         empiricalDistribution = new EmpiricalDistributionImpl(1);
157         tstGen(5); // ridiculous tolerance; but ridiculous grid size
158                    // really just checking to make sure we do not bomb
159         empiricalDistribution2 = new EmpiricalDistributionImpl(1);           
160         tstDoubleGen(5);           
161     }
162     
163     public void testSerialization() {
164         // Empty
165         EmpiricalDistribution dist = new EmpiricalDistributionImpl();
166         EmpiricalDistribution dist2 = (EmpiricalDistribution) TestUtils.serializeAndRecover(dist);
167         verifySame(dist, dist2);
168         
169         // Loaded
170         empiricalDistribution2.load(dataArray);   
171         dist2 = (EmpiricalDistribution) TestUtils.serializeAndRecover(empiricalDistribution2);
172         verifySame(empiricalDistribution2, dist2);
173     }
174     
175     private void verifySame(EmpiricalDistribution d1, EmpiricalDistribution d2) {
176         assertEquals(d1.isLoaded(), d2.isLoaded());
177         assertEquals(d1.getBinCount(), d2.getBinCount());
178         assertEquals(d1.getSampleStats(), d2.getSampleStats());
179         if (d1.isLoaded()) {
180             for (int i = 0;  i < d1.getUpperBounds().length; i++) {
181                 assertEquals(d1.getUpperBounds()[i], d2.getUpperBounds()[i], 0);
182             }
183             assertEquals(d1.getBinStats(), d2.getBinStats());
184         }
185     }
186     
187     private void tstGen(double tolerance)throws Exception {
188         empiricalDistribution.load(url);   
189         SummaryStatistics stats = SummaryStatistics.newInstance();
190         for (int i = 1; i < 1000; i++) {
191             stats.addValue(empiricalDistribution.getNextValue());
192         }
193         assertEquals("mean", stats.getMean(),5.069831575018909,tolerance);
194         assertEquals
195          ("std dev", stats.getStandardDeviation(),1.0173699343977738,tolerance);
196     }
197 
198     private void tstDoubleGen(double tolerance)throws Exception {
199         empiricalDistribution2.load(dataArray);   
200         SummaryStatistics stats = SummaryStatistics.newInstance();
201         for (int i = 1; i < 1000; i++) {
202             stats.addValue(empiricalDistribution2.getNextValue());
203         }
204         assertEquals("mean", stats.getMean(),5.069831575018909,tolerance);
205         assertEquals
206          ("std dev", stats.getStandardDeviation(),1.0173699343977738,tolerance);
207     }
208 }