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    *      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.statistics.distribution;
18  
19  import java.math.BigDecimal;
20  import org.junit.jupiter.api.Assertions;
21  import org.junit.jupiter.api.Test;
22  import org.junit.jupiter.params.ParameterizedTest;
23  import org.junit.jupiter.params.provider.CsvFileSource;
24  
25  /**
26   * Test cases for {@link ExponentialDistribution}.
27   * Extends {@link BaseContinuousDistributionTest}. See javadoc of that class for details.
28   */
29  class ExponentialDistributionTest extends BaseContinuousDistributionTest {
30      @Override
31      ContinuousDistribution makeDistribution(Object... parameters) {
32          final double mean = (Double) parameters[0];
33          return ExponentialDistribution.of(mean);
34      }
35  
36      @Override
37      Object[][] makeInvalidParameters() {
38          return new Object[][] {
39              {0.0},
40              {-0.1}
41          };
42      }
43  
44      @Override
45      String[] getParameterNames() {
46          return new String[] {"Mean"};
47      }
48  
49      @Override
50      protected double getRelativeTolerance() {
51          // Tolerance is 8.881784197001252E-16
52          return 4 * RELATIVE_EPS;
53      }
54  
55      //------------ Additional tests -------------------------------------------
56  
57      @Test
58      void testProbabilityRange() {
59          final double actual = ExponentialDistribution.of(5).probability(0.25, 0.75);
60          TestUtils.assertEquals(0.0905214480756562, actual, DoubleTolerances.ulps(1));
61      }
62  
63      @Test
64      void testAdditionalDensity() {
65          final ExponentialDistribution d1 = ExponentialDistribution.of(1);
66          Assertions.assertEquals(0.0, d1.density(-1e-9));
67          Assertions.assertEquals(1.0, d1.density(0.0));
68          Assertions.assertEquals(0.0, d1.density(1000.0));
69          Assertions.assertEquals(Math.exp(-1), d1.density(1.0));
70          Assertions.assertEquals(Math.exp(-2), d1.density(2.0));
71  
72          final ExponentialDistribution d2 = ExponentialDistribution.of(3);
73          Assertions.assertEquals(1 / 3.0, d2.density(0.0));
74  
75          // computed using R 3.4.0: print(dexp(1, rate=1/3), digits=20)
76          Assertions.assertEquals(0.23884377019126309949, d2.density(1.0), 1e-15);
77  
78          // computed using R 3.4.0: print(dexp(2, rate=1/3), digits=20)
79          Assertions.assertEquals(0.17113903967753066326, d2.density(2.0), 1e-15);
80      }
81  
82      @ParameterizedTest
83      @CsvFileSource(resources = "exppdf.csv")
84      void testPDF(double mean, double x, BigDecimal expected) {
85          final double e = expected.doubleValue();
86          final double a = ExponentialDistribution.of(mean).density(x);
87          // Require high precision.
88          // This has max error of 3 ulp if using exp(logDensity(x)).
89          Assertions.assertEquals(e, a, 2 * Math.ulp(e),
90              () -> "ULP error: " + expected.subtract(new BigDecimal(a)).doubleValue() / Math.ulp(e));
91      }
92  }