You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ah...@apache.org on 2024/08/16 10:29:58 UTC
(commons-statistics) branch master updated: STATISTICS-88: Add a log uniform distribution
This is an automated email from the ASF dual-hosted git repository.
aherbert pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-statistics.git
The following commit(s) were added to refs/heads/master by this push:
new 7c6a763 STATISTICS-88: Add a log uniform distribution
7c6a763 is described below
commit 7c6a7637e569ca3904a82b880cd290c9b662f28c
Author: Alex Herbert <ah...@apache.org>
AuthorDate: Thu Aug 15 18:35:36 2024 +0100
STATISTICS-88: Add a log uniform distribution
---
.../distribution/LogUniformDistribution.java | 239 +++++++++++++++++++++
.../distribution/LogUniformDistributionTest.java | 115 ++++++++++
.../distribution/test.loguniform.1.properties | 33 +++
.../distribution/test.loguniform.2.properties | 32 +++
.../distribution/test.loguniform.3.properties | 32 +++
.../distribution/DistributionsApplication.java | 1 +
.../examples/distribution/LogUniformCommand.java | 156 ++++++++++++++
src/changes/changes.xml | 3 +
8 files changed, 611 insertions(+)
diff --git a/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LogUniformDistribution.java b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LogUniformDistribution.java
new file mode 100644
index 0000000..196b413
--- /dev/null
+++ b/commons-statistics-distribution/src/main/java/org/apache/commons/statistics/distribution/LogUniformDistribution.java
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.statistics.distribution;
+
+import org.apache.commons.rng.UniformRandomProvider;
+import org.apache.commons.rng.sampling.distribution.ContinuousUniformSampler;
+import org.apache.commons.rng.sampling.distribution.SharedStateContinuousSampler;
+
+/**
+ * Implementation of the log-uniform distribution. This is also known as the reciprocal distribution.
+ *
+ * <p>The probability density function of \( X \) is:
+ *
+ * <p>\[ f(x; a, b) = \frac{1}{x \ln \frac b a} \]
+ *
+ * <p>for \( 0 \lt a \lt b \lt \infty \) and
+ * \( x \in [a, b] \).
+ *
+ * @see <a href="https://en.wikipedia.org/wiki/Reciprocal_distribution">Reciprocal distribution (Wikipedia)</a>
+ * @since 1.1
+ */
+public final class LogUniformDistribution extends AbstractContinuousDistribution {
+ /** Lower bound (a) of this distribution (inclusive). */
+ private final double lower;
+ /** Upper bound (b) of this distribution (exclusive). */
+ private final double upper;
+ /** log(a). */
+ private final double logA;
+ /** log(b). */
+ private final double logB;
+ /** log(b) - log(a). */
+ private final double logBmLogA;
+ /** log(log(b) - log(a)). */
+ private final double logLogBmLogA;
+
+ /**
+ * @param lower Lower bound of this distribution (inclusive).
+ * @param upper Upper bound of this distribution (inclusive).
+ */
+ private LogUniformDistribution(double lower,
+ double upper) {
+ this.lower = lower;
+ this.upper = upper;
+ logA = Math.log(lower);
+ logB = Math.log(upper);
+ logBmLogA = logB - logA;
+ logLogBmLogA = Math.log(logBmLogA);
+ }
+
+ /**
+ * Creates a log-uniform distribution.
+ *
+ * @param lower Lower bound of this distribution (inclusive).
+ * @param upper Upper bound of this distribution (inclusive).
+ * @return the distribution
+ * @throws IllegalArgumentException if {@code lower >= upper}; the range between the bounds
+ * is not finite; or {@code lower <= 0}
+ */
+ public static LogUniformDistribution of(double lower,
+ double upper) {
+ if (lower >= upper) {
+ throw new DistributionException(DistributionException.INVALID_RANGE_LOW_GTE_HIGH,
+ lower, upper);
+ }
+ if (!Double.isFinite(upper - lower)) {
+ throw new DistributionException("Range %s is not finite", upper - lower);
+ }
+ if (lower <= 0) {
+ throw new DistributionException(DistributionException.NOT_STRICTLY_POSITIVE, lower);
+ }
+ return new LogUniformDistribution(lower, upper);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double density(double x) {
+ if (x < lower || x > upper) {
+ return 0;
+ }
+ return Math.exp(logDensity(x));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double logDensity(double x) {
+ if (x < lower || x > upper) {
+ return Double.NEGATIVE_INFINITY;
+ }
+ return -Math.log(x) - logLogBmLogA;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double cumulativeProbability(double x) {
+ if (x <= lower) {
+ return 0;
+ }
+ if (x >= upper) {
+ return 1;
+ }
+ return (Math.log(x) - logA) / logBmLogA;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double survivalProbability(double x) {
+ if (x <= lower) {
+ return 1;
+ }
+ if (x >= upper) {
+ return 0;
+ }
+ return (logB - Math.log(x)) / logBmLogA;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public double inverseCumulativeProbability(double p) {
+ ArgumentUtils.checkProbability(p);
+ // Avoid floating-point error at the bounds
+ return clipToRange(Math.exp(logA + p * logBmLogA));
+ }
+
+ @Override
+ public double inverseSurvivalProbability(double p) {
+ ArgumentUtils.checkProbability(p);
+ // Avoid floating-point error at the bounds
+ return clipToRange(Math.exp(logB - p * logBmLogA));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>For lower bound \( a \) and upper bound \( b \), the mean is:
+ *
+ * <p>\[ \frac{b - a}{\ln \frac b a} \]
+ */
+ @Override
+ public double getMean() {
+ return (upper - lower) / logBmLogA;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>For lower bound \( a \) and upper bound \( b \), the variance is:
+ *
+ * <p>\[ \frac{b^2 - a^2}{2 \ln \frac b a} - \left( \frac{b - a}{\ln \frac b a} \right)^2 \]
+ */
+ @Override
+ public double getVariance() {
+ // Compute u_2 via a stabilising rearrangement:
+ // https://docs.scipy.org/doc/scipy/tutorial/stats/continuous_loguniform.html
+ final double a = lower;
+ final double b = upper;
+ final double d = -logBmLogA;
+ return (a - b) * (a * (d - 2) + b * (d + 2)) / (2 * d * d);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>The lower bound of the support is equal to the lower bound parameter
+ * of the distribution.
+ */
+ @Override
+ public double getSupportLowerBound() {
+ return lower;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>The upper bound of the support is equal to the upper bound parameter
+ * of the distribution.
+ */
+ @Override
+ public double getSupportUpperBound() {
+ return upper;
+ }
+
+ /**
+ * Clip the value to the range [lower, upper].
+ * This is used to handle floating-point error at the support bound.
+ *
+ * @param x Value x
+ * @return x clipped to the range
+ */
+ private double clipToRange(double x) {
+ return clip(x, lower, upper);
+ }
+
+ /**
+ * Clip the value to the range [lower, upper].
+ *
+ * @param x Value x
+ * @param lower Lower bound (inclusive)
+ * @param upper Upper bound (inclusive)
+ * @return x clipped to the range
+ */
+ private static double clip(double x, double lower, double upper) {
+ if (x <= lower) {
+ return lower;
+ }
+ return x < upper ? x : upper;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ double getMedian() {
+ // Overridden for the probability(double, double) method.
+ // This is intentionally not a public method.
+ // sqrt(ab) avoiding overflow
+ return Math.exp(0.5 * (logA + logB));
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ContinuousDistribution.Sampler createSampler(final UniformRandomProvider rng) {
+ // Exponentiate a uniform distribution sampler of the logarithmic range.
+ final SharedStateContinuousSampler s = ContinuousUniformSampler.of(rng, logA, logB);
+ return () -> Math.exp(s.sample());
+ }
+}
diff --git a/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LogUniformDistributionTest.java b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LogUniformDistributionTest.java
new file mode 100644
index 0000000..e4aac72
--- /dev/null
+++ b/commons-statistics-distribution/src/test/java/org/apache/commons/statistics/distribution/LogUniformDistributionTest.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.statistics.distribution;
+
+import java.util.stream.Stream;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.junit.jupiter.params.provider.MethodSource;
+
+/**
+ * Test cases for {@link LogUniformDistribution}.
+ * Extends {@link BaseContinuousDistributionTest}. See javadoc of that class for details.
+ */
+class LogUniformDistributionTest extends BaseContinuousDistributionTest {
+ @Override
+ ContinuousDistribution makeDistribution(Object... parameters) {
+ final double a = (Double) parameters[0];
+ final double b = (Double) parameters[1];
+ return LogUniformDistribution.of(a, b);
+ }
+
+ @Override
+ Object[][] makeInvalidParameters() {
+ return new Object[][] {
+ // lower >= upper
+ {0.0, 0.0},
+ {1.0, 0.5},
+ // Range not finite
+ {Double.NaN, 1.0},
+ {0.5, Double.NaN},
+ // lower <= 0
+ {-1.0, 1.0},
+ {0.0, 1.0},
+ };
+ }
+
+ @Override
+ String[] getParameterNames() {
+ return new String[] {"SupportLowerBound", "SupportUpperBound"};
+ }
+
+ @Override
+ protected double getRelativeTolerance() {
+ return 5e-15;
+ }
+
+ //-------------------- Additional test cases -------------------------------
+
+ /**
+ * Test the moments using the canonical formulas (from the javadoc).
+ */
+ @ParameterizedTest
+ @MethodSource
+ void testAdditionalMoments(double a, double b) {
+ final double diff = b - a;
+ final double denom = Math.log(b / a);
+ final double mean = diff / denom;
+ // Note: b^2 - a^2 = (b-a)*(b+a)
+ final double variance = mean * (b + a) / 2 - mean * mean;
+ TestUtils.assertEquals(mean, LogUniformDistribution.of(a, b).getMean(),
+ DoubleTolerances.relative(1e-14), "Mean");
+ TestUtils.assertEquals(variance, LogUniformDistribution.of(a, b).getVariance(),
+ DoubleTolerances.relative(1e-10), "Variance");
+ }
+
+ static Stream<Arguments> testAdditionalMoments() {
+ final Stream.Builder<Arguments> builder = Stream.builder();
+ for (final double a : new double[] {1, 10, 100}) {
+ for (final double x : new double[] {10, 20, 40}) {
+ builder.add(Arguments.of(a, a + x));
+ }
+ }
+ return builder.build();
+ }
+
+ /**
+ * Test the survival function for extreme values is computed using high precision,
+ * i.e. is not the default of 1 - CDF.
+ */
+ @ParameterizedTest
+ @CsvSource({
+ "1e-100, 1e100",
+ "1e-10, 1e10",
+ })
+ void testExtremeSurvivalFunction(double a, double b) {
+ final LogUniformDistribution d = LogUniformDistribution.of(a, b);
+ // Find a small non-zero survival probability
+ final double u = Math.ulp(b);
+ int i = 1;
+ double p;
+ do {
+ p = d.survivalProbability(b - i * u);
+ i *= 2;
+ } while (p == 0);
+ Assertions.assertTrue(p < 0x1.0p-53, "sf is not small enough for high precision");
+ Assertions.assertNotEquals(1 - d.cumulativeProbability(b - i * u), p, "sf is not high precision: sf == 1 - cdf");
+ }
+}
diff --git a/commons-statistics-distribution/src/test/resources/org/apache/commons/statistics/distribution/test.loguniform.1.properties b/commons-statistics-distribution/src/test/resources/org/apache/commons/statistics/distribution/test.loguniform.1.properties
new file mode 100644
index 0000000..dbb3e0a
--- /dev/null
+++ b/commons-statistics-distribution/src/test/resources/org/apache/commons/statistics/distribution/test.loguniform.1.properties
@@ -0,0 +1,33 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+parameters = 1.0 10.0
+
+# Computed using scipy.stats reciprocal (v1.13.0)
+mean = 3.9086503371292665
+variance = 6.220029396270247
+lower = 1
+upper = 10
+cdf.points = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
+cdf.values = \
+ 0. , 0.30102999566398114, 0.47712125471966244, \
+ 0.6020599913279623 , 0.6989700043360187 , 0.7781512503836435 , \
+ 0.8450980400142567 , 0.9030899869919434 , 0.9542425094393249 , \
+ 1.
+pdf.values = \
+ 0.43429448190325176 , 0.21714724095162585 , 0.14476482730108392 , \
+ 0.10857362047581297 , 0.08685889638065038 , 0.07238241365054196 , \
+ 0.062042068843321696, 0.05428681023790648 , 0.04825494243369463 , \
+ 0.04342944819032517
diff --git a/commons-statistics-distribution/src/test/resources/org/apache/commons/statistics/distribution/test.loguniform.2.properties b/commons-statistics-distribution/src/test/resources/org/apache/commons/statistics/distribution/test.loguniform.2.properties
new file mode 100644
index 0000000..8f3a069
--- /dev/null
+++ b/commons-statistics-distribution/src/test/resources/org/apache/commons/statistics/distribution/test.loguniform.2.properties
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+parameters = 1e3 1e10
+
+# Computed using scipy.stats reciprocal (v1.13.0)
+mean = 620420626.3911486
+variance = 2.7171816885144796e+18
+lower = 1e3
+upper = 1e10
+cdf.points = 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10
+cdf.values = \
+ 0. , 0.14285714285714293, 0.28571428571428575, \
+ 0.42857142857142855, 0.5714285714285715 , 0.7142857142857144 , \
+ 0.8571428571428571 , 1.
+pdf.values = \
+ 6.204206884332176e-05, 6.204206884332170e-06, \
+ 6.204206884332163e-07, 6.204206884332178e-08, \
+ 6.204206884332171e-09, 6.204206884332165e-10, \
+ 6.204206884332179e-11, 6.204206884332173e-12
diff --git a/commons-statistics-distribution/src/test/resources/org/apache/commons/statistics/distribution/test.loguniform.3.properties b/commons-statistics-distribution/src/test/resources/org/apache/commons/statistics/distribution/test.loguniform.3.properties
new file mode 100644
index 0000000..cfef804
--- /dev/null
+++ b/commons-statistics-distribution/src/test/resources/org/apache/commons/statistics/distribution/test.loguniform.3.properties
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+parameters = 1e-10 1e-3
+
+# Computed using scipy.stats reciprocal (v1.13.0)
+mean = 6.204206263911483e-05
+variance = 2.717181688514468e-08
+lower = 1e-10
+upper = 1e-3
+cdf.points = 1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3
+cdf.values = \
+ 0. , 0.14285714285714293, 0.28571428571428564, \
+ 0.42857142857142855, 0.5714285714285715 , 0.7142857142857143 , \
+ 0.8571428571428572 , 1.
+pdf.values = \
+ 6.204206884332178e+08, 6.204206884332171e+07, \
+ 6.204206884332187e+06, 6.204206884332179e+05, \
+ 6.204206884332172e+04, 6.204206884332166e+03, \
+ 6.204206884332165e+02, 6.204206884332169e+01
diff --git a/commons-statistics-examples/examples-distribution/src/main/java/org/apache/commons/statistics/examples/distribution/DistributionsApplication.java b/commons-statistics-examples/examples-distribution/src/main/java/org/apache/commons/statistics/examples/distribution/DistributionsApplication.java
index 0fbfd27..2477049 100644
--- a/commons-statistics-examples/examples-distribution/src/main/java/org/apache/commons/statistics/examples/distribution/DistributionsApplication.java
+++ b/commons-statistics-examples/examples-distribution/src/main/java/org/apache/commons/statistics/examples/distribution/DistributionsApplication.java
@@ -83,6 +83,7 @@ public final class DistributionsApplication {
LevyCommand.class,
LogisticCommand.class,
LogNormalCommand.class,
+ LogUniformCommand.class,
NakagamiCommand.class,
NormalCommand.class,
ParetoCommand.class,
diff --git a/commons-statistics-examples/examples-distribution/src/main/java/org/apache/commons/statistics/examples/distribution/LogUniformCommand.java b/commons-statistics-examples/examples-distribution/src/main/java/org/apache/commons/statistics/examples/distribution/LogUniformCommand.java
new file mode 100644
index 0000000..8592ddc
--- /dev/null
+++ b/commons-statistics-examples/examples-distribution/src/main/java/org/apache/commons/statistics/examples/distribution/LogUniformCommand.java
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.commons.statistics.examples.distribution;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.statistics.distribution.ContinuousDistribution;
+import org.apache.commons.statistics.distribution.LogUniformDistribution;
+import picocli.CommandLine.ArgGroup;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Option;
+
+/**
+ * Command for the {@link LogUniformDistribution}.
+ */
+@Command(name = "logunif",
+ aliases = {"reciprocal"},
+ description = "Log uniform distribution.",
+ subcommands = {
+ LogUniformCommand.Check.class,
+ LogUniformCommand.PDF.class,
+ LogUniformCommand.LPDF.class,
+ LogUniformCommand.CDF.class,
+ LogUniformCommand.SF.class,
+ LogUniformCommand.ICDF.class,
+ LogUniformCommand.ISF.class,
+ })
+class LogUniformCommand extends AbstractDistributionCommand {
+
+ /** Base command for the distribution that defines the parameters. */
+ private abstract static class BaseCommand extends AbstractContinuousDistributionCommand {
+ /** Distribution parameters. */
+ @ArgGroup(validate = false, heading = "Distribution parameters:%n", order = 1)
+ private Params params = new Params();
+
+ /** Parameters class. */
+ static class Params {
+ /** The distribution lower limit. */
+ @Option(names = {"-a", "--lower"},
+ paramLabel = "a",
+ arity = "1..*",
+ split = ",",
+ description = {"lower bound (default: ${DEFAULT-VALUE})."})
+ private double[] lower = {1, 2};
+
+ /** The distribution upper limit. */
+ @Option(names = {"-b", "--upper"},
+ paramLabel = "b",
+ arity = "1..*",
+ split = ",",
+ description = {"upper bound (default: ${DEFAULT-VALUE})."})
+ private double[] upper = {4, 6};
+ }
+
+ /** Extend the options to set the default values for this distribution. */
+ static final class Options extends ContinuousDistributionOptions {
+ /** Set defaults. */
+ private Options() {
+ min = -5;
+ max = 5;
+ }
+ }
+
+ @Override
+ protected List<Distribution<ContinuousDistribution>> getDistributions() {
+ double[] lower = params.lower;
+ double[] upper = params.upper;
+ final int n = DistributionUtils.validateLengths(lower.length, upper.length);
+
+ lower = DistributionUtils.expandToLength(lower, n);
+ upper = DistributionUtils.expandToLength(upper, n);
+
+ // Create distributions
+ final ArrayList<Distribution<ContinuousDistribution>> list = new ArrayList<>();
+ for (int i = 0; i < n; i++) {
+ final ContinuousDistribution d = LogUniformDistribution.of(lower[i], upper[i]);
+ list.add(new Distribution<>(d, "a=" + lower[i] + ",b=" + upper[i]));
+ }
+ return list;
+ }
+ }
+
+ /** Base command for the distribution that defines the parameters. */
+ private abstract static class ProbabilityCommand extends BaseCommand {
+ /** The distribution options. */
+ @ArgGroup(validate = false, heading = "Evaluation options:%n", order = 2)
+ private Options distributionOptions = new Options();
+
+ @Override
+ protected DistributionOptions getDistributionOptions() {
+ return distributionOptions;
+ }
+ }
+
+ /** Base command for the distribution that defines the parameters for inverse probability functions. */
+ private abstract static class InverseProbabilityCommand extends BaseCommand {
+ /** The distribution options. */
+ @ArgGroup(validate = false, heading = "Evaluation options:%n", order = 2)
+ private InverseContinuousDistributionOptions distributionOptions = new InverseContinuousDistributionOptions();
+
+ @Override
+ protected DistributionOptions getDistributionOptions() {
+ return distributionOptions;
+ }
+ }
+
+ /** Verification checks command. */
+ @Command(name = "check",
+ hidden = true,
+ description = "Log uniform distribution verification checks.")
+ static class Check extends ProbabilityCommand {}
+
+ /** PDF command. */
+ @Command(name = "pdf",
+ description = "Log uniform distribution PDF.")
+ static class PDF extends ProbabilityCommand {}
+
+ /** LPDF command. */
+ @Command(name = "lpdf",
+ description = "Log uniform distribution natural logarithm of the PDF.")
+ static class LPDF extends ProbabilityCommand {}
+
+ /** CDF command. */
+ @Command(name = "cdf",
+ description = "Log uniform distribution CDF.")
+ static class CDF extends ProbabilityCommand {}
+
+ /** SF command. */
+ @Command(name = "sf",
+ description = "Log uniform distribution survival probability.")
+ static class SF extends ProbabilityCommand {}
+
+ /** ICDF command. */
+ @Command(name = "icdf",
+ description = "Log uniform distribution inverse CDF.")
+ static class ICDF extends InverseProbabilityCommand {}
+
+ /** ISF command. */
+ @Command(name = "isf",
+ description = "Log uniform distribution inverse SF.")
+ static class ISF extends InverseProbabilityCommand {}
+}
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 4b5a1eb..82fffef 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -56,6 +56,9 @@ If the output is not quite correct, check for invisible trailing spaces!
<release version="1.1" date="TBD" description="
Adds ranking, inference, descriptive and bom modules. (requires Java 8).
">
+ <action dev="aherbert" type="add" issue="STATISTICS-88">
+ "LogUniformDistribution": Add a log uniform distribution.
+ </action>
<action dev="aherbert" type="add" issue="STATISTICS-87">
"FoldedNormalDistribution": Add a folded normal distribution implementation with
specialized support for a half-normal distribution.