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  
23  package org.hipparchus.distribution.continuous;
24  
25  import org.hipparchus.exception.MathIllegalArgumentException;
26  import org.junit.Assert;
27  import org.junit.Test;
28  
29  /**
30   * Test cases for {@link LogNormalDistribution}.
31   */
32  public class LogNormalDistributionTest extends RealDistributionAbstractTest {
33  
34      //-------------- Implementations for abstract methods -----------------------
35  
36      /** Creates the default real distribution instance to use in tests. */
37      @Override
38      public LogNormalDistribution makeDistribution() {
39          return new LogNormalDistribution(2.1, 1.4);
40      }
41  
42      /** Creates the default cumulative probability distribution test input values */
43      @Override
44      public double[] makeCumulativeTestPoints() {
45          // quantiles computed using R
46          return new double[] { -2.226325228634938, -1.156887023657177,
47                                -0.643949578356075, -0.2027950777320613,
48                                0.305827808237559, 6.42632522863494,
49                                5.35688702365718, 4.843949578356074,
50                                4.40279507773206, 3.89417219176244 };
51      }
52  
53      /** Creates the default cumulative probability density test expected values */
54      @Override
55      public double[] makeCumulativeTestValues() {
56          return new double[] { 0, 0, 0, 0, 0.00948199951485, 0.432056525076,
57                                0.381648158697, 0.354555726206, 0.329513316888,
58                                0.298422824228 };
59      }
60  
61      /** Creates the default probability density test expected values */
62      @Override
63      public double[] makeDensityTestValues() {
64          return new double[] { 0, 0, 0, 0, 0.0594218160072, 0.0436977691036,
65                                0.0508364857798, 0.054873528325, 0.0587182664085,
66                                0.0636229042785 };
67      }
68  
69      /**
70       * Creates the default inverse cumulative probability distribution test
71       * input values.
72       */
73      @Override
74      public double[] makeInverseCumulativeTestPoints() {
75          // Exclude the test points less than zero, as they have cumulative
76          // probability of zero, meaning the inverse returns zero, and not the
77          // points less than zero.
78          double[] points = makeCumulativeTestValues();
79          double[] points2 = new double[points.length - 4];
80          System.arraycopy(points, 4, points2, 0, points2.length - 4);
81          return points2;
82          //return Arrays.copyOfRange(points, 4, points.length - 4);
83      }
84  
85      /**
86       * Creates the default inverse cumulative probability test expected
87       * values.
88       */
89      @Override
90      public double[] makeInverseCumulativeTestValues() {
91          // Exclude the test points less than zero, as they have cumulative
92          // probability of zero, meaning the inverse returns zero, and not the
93          // points less than zero.
94          double[] points = makeCumulativeTestPoints();
95          double[] points2 = new double[points.length - 4];
96          System.arraycopy(points, 4, points2, 0, points2.length - 4);
97          return points2;
98          //return Arrays.copyOfRange(points, 1, points.length - 4);
99      }
100 
101     // --------------------- Override tolerance  --------------
102     @Override
103     public void setUp() {
104         super.setUp();
105         setTolerance(1e-9);
106     }
107 
108     //---------------------------- Additional test cases -------------------------
109 
110     private void verifyQuantiles() {
111         LogNormalDistribution distribution = (LogNormalDistribution)getDistribution();
112         double mu = distribution.getLocation();
113         double sigma = distribution.getShape();
114         setCumulativeTestPoints( new double[] { mu - 2 *sigma, mu - sigma,
115                                                 mu, mu + sigma, mu + 2 * sigma,
116                                                 mu + 3 * sigma,mu + 4 * sigma,
117                                                 mu + 5 * sigma });
118         verifyCumulativeProbabilities();
119     }
120 
121     @Test
122     public void testQuantiles() {
123         setCumulativeTestValues(new double[] {0, 0.0396495152787,
124                                               0.16601209243, 0.272533253269,
125                                               0.357618409638, 0.426488363093,
126                                               0.483255136841, 0.530823013877});
127         setDensityTestValues(new double[] {0, 0.0873055825147, 0.0847676303432,
128                                            0.0677935186237, 0.0544105523058,
129                                            0.0444614628804, 0.0369750288945,
130                                            0.0312206409653});
131         verifyQuantiles();
132         verifyDensities();
133 
134         setDistribution(new LogNormalDistribution(0, 1));
135         setCumulativeTestValues(new double[] {0, 0, 0, 0.5, 0.755891404214,
136                                               0.864031392359, 0.917171480998,
137                                               0.946239689548});
138         setDensityTestValues(new double[] {0, 0, 0, 0.398942280401,
139                                            0.156874019279, 0.07272825614,
140                                            0.0381534565119, 0.0218507148303});
141         verifyQuantiles();
142         verifyDensities();
143 
144         setDistribution(new LogNormalDistribution(0, 0.1));
145         setCumulativeTestValues(new double[] {0, 0, 0, 1.28417563064e-117,
146                                               1.39679883412e-58,
147                                               1.09839325447e-33,
148                                               2.52587961726e-20,
149                                               2.0824223487e-12});
150         setDensityTestValues(new double[] {0, 0, 0, 2.96247992535e-114,
151                                            1.1283370232e-55, 4.43812313223e-31,
152                                            5.85346445002e-18,
153                                            2.9446618076e-10});
154         verifyQuantiles();
155         verifyDensities();
156     }
157 
158     @Test
159     public void testInverseCumulativeProbabilityExtremes() {
160         setInverseCumulativeTestPoints(new double[] {0, 1});
161         setInverseCumulativeTestValues(
162                 new double[] {0, Double.POSITIVE_INFINITY});
163         verifyInverseCumulativeProbabilities();
164     }
165 
166     @Test
167     public void testGetLocation() {
168         LogNormalDistribution distribution = (LogNormalDistribution)getDistribution();
169         Assert.assertEquals(2.1, distribution.getLocation(), 0);
170     }
171 
172     @Test
173     public void testGetShape() {
174         LogNormalDistribution distribution = (LogNormalDistribution)getDistribution();
175         Assert.assertEquals(1.4, distribution.getShape(), 0);
176     }
177 
178     @Test(expected=MathIllegalArgumentException.class)
179     public void testPreconditions() {
180         new LogNormalDistribution(1, 0);
181     }
182 
183     @Test
184     public void testDensity() {
185         double [] x = new double[]{-2, -1, 0, 1, 2};
186         // R 2.13: print(dlnorm(c(-2,-1,0,1,2)), digits=10)
187         checkDensity(0, 1, x, new double[] { 0.0000000000, 0.0000000000,
188                                              0.0000000000, 0.3989422804,
189                                              0.1568740193 });
190         // R 2.13: print(dlnorm(c(-2,-1,0,1,2), mean=1.1), digits=10)
191         checkDensity(1.1, 1, x, new double[] { 0.0000000000, 0.0000000000,
192                                                0.0000000000, 0.2178521770,
193                                                0.1836267118});
194     }
195 
196     private void checkDensity(double scale, double shape, double[] x,
197         double[] expected) {
198         LogNormalDistribution d = new LogNormalDistribution(scale, shape);
199         for (int i = 0; i < x.length; i++) {
200             Assert.assertEquals(expected[i], d.density(x[i]), 1e-9);
201         }
202     }
203 
204     /**
205      * Check to make sure top-coding of extreme values works correctly.
206      * Verifies fixes for JIRA MATH-167, MATH-414
207      */
208     @Test
209     public void testExtremeValues() {
210         LogNormalDistribution d = new LogNormalDistribution(0, 1);
211         for (int i = 0; i < 1e5; i++) { // make sure no convergence exception
212             double upperTail = d.cumulativeProbability(i);
213             if (i <= 72) { // make sure not top-coded
214                 Assert.assertTrue(upperTail < 1.0d);
215             }
216             else { // make sure top coding not reversed
217                 Assert.assertTrue(upperTail > 0.99999);
218             }
219         }
220 
221         Assert.assertEquals(d.cumulativeProbability(Double.MAX_VALUE), 1, 0);
222         Assert.assertEquals(d.cumulativeProbability(-Double.MAX_VALUE), 0, 0);
223         Assert.assertEquals(d.cumulativeProbability(Double.POSITIVE_INFINITY), 1, 0);
224         Assert.assertEquals(d.cumulativeProbability(Double.NEGATIVE_INFINITY), 0, 0);
225     }
226 
227     @Test
228     public void testMeanVariance() {
229         final double tol = 1e-9;
230         LogNormalDistribution dist;
231 
232         dist = new LogNormalDistribution(0, 1);
233         Assert.assertEquals(dist.getNumericalMean(), 1.6487212707001282, tol);
234         Assert.assertEquals(dist.getNumericalVariance(),
235                             4.670774270471604, tol);
236 
237         dist = new LogNormalDistribution(2.2, 1.4);
238         Assert.assertEquals(dist.getNumericalMean(), 24.046753552064498, tol);
239         Assert.assertEquals(dist.getNumericalVariance(),
240                             3526.913651880464, tol);
241 
242         dist = new LogNormalDistribution(-2000.9, 10.4);
243         Assert.assertEquals(dist.getNumericalMean(), 0.0, tol);
244         Assert.assertEquals(dist.getNumericalVariance(), 0.0, tol);
245     }
246 
247     @Test
248     public void testTinyVariance() {
249         LogNormalDistribution dist = new LogNormalDistribution(0, 1e-9);
250         double t = dist.getNumericalVariance();
251         Assert.assertEquals(1e-18, t, 1e-20);
252     }
253 
254 }