RNG-36: New log normal sampler implementation. The new class uses the (faster) polar method as the underlying Gaussian sampler.
Project: http://git-wip-us.apache.org/repos/asf/commons-rng/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-rng/commit/44945881 Tree: http://git-wip-us.apache.org/repos/asf/commons-rng/tree/44945881 Diff: http://git-wip-us.apache.org/repos/asf/commons-rng/diff/44945881 Branch: refs/heads/master Commit: 4494588190d5fc8f84e93b79ba81780f6d91eefd Parents: c1a2b82 Author: Gilles <[email protected]> Authored: Sun Apr 9 13:14:00 2017 +0200 Committer: Gilles <[email protected]> Committed: Sun Apr 9 13:14:00 2017 +0200 ---------------------------------------------------------------------- .../jmh/distribution/SamplersPerformance.java | 11 ++++ .../distribution/MarsagliaLogNormalSampler.java | 62 ++++++++++++++++++++ .../distribution/ContinuousSamplersList.java | 5 +- 3 files changed, 77 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-rng/blob/44945881/commons-rng-jmh/src/main/java/org/apache/commons/rng/jmh/distribution/SamplersPerformance.java ---------------------------------------------------------------------- diff --git a/commons-rng-jmh/src/main/java/org/apache/commons/rng/jmh/distribution/SamplersPerformance.java b/commons-rng-jmh/src/main/java/org/apache/commons/rng/jmh/distribution/SamplersPerformance.java index 4d338e6..d24664c 100644 --- a/commons-rng-jmh/src/main/java/org/apache/commons/rng/jmh/distribution/SamplersPerformance.java +++ b/commons-rng-jmh/src/main/java/org/apache/commons/rng/jmh/distribution/SamplersPerformance.java @@ -41,6 +41,7 @@ import org.apache.commons.rng.sampling.distribution.MarsagliaNormalizedGaussianS import org.apache.commons.rng.sampling.distribution.AhrensDieterExponentialSampler; import org.apache.commons.rng.sampling.distribution.AhrensDieterMarsagliaTsangGammaSampler; import org.apache.commons.rng.sampling.distribution.BoxMullerLogNormalSampler; +import org.apache.commons.rng.sampling.distribution.MarsagliaLogNormalSampler; import org.apache.commons.rng.sampling.distribution.ChengBetaSampler; import org.apache.commons.rng.sampling.distribution.ContinuousUniformSampler; import org.apache.commons.rng.sampling.distribution.DiscreteUniformSampler; @@ -197,6 +198,16 @@ public class SamplersPerformance { * @param bh Data sink. */ @Benchmark + public void runMarsagliaLogNormalSampler(Sources sources, + Blackhole bh) { + runSample(new MarsagliaLogNormalSampler(sources.getGenerator(), 12.3, 4.6), bh); + } + + /** + * @param sources Source of randomness. + * @param bh Data sink. + */ + @Benchmark public void runChengBetaSampler(Sources sources, Blackhole bh) { runSample(new ChengBetaSampler(sources.getGenerator(), 0.45, 6.7), bh); http://git-wip-us.apache.org/repos/asf/commons-rng/blob/44945881/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/MarsagliaLogNormalSampler.java ---------------------------------------------------------------------- diff --git a/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/MarsagliaLogNormalSampler.java b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/MarsagliaLogNormalSampler.java new file mode 100644 index 0000000..885aeb9 --- /dev/null +++ b/commons-rng-sampling/src/main/java/org/apache/commons/rng/sampling/distribution/MarsagliaLogNormalSampler.java @@ -0,0 +1,62 @@ +/* + * 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.rng.sampling.distribution; + +import org.apache.commons.rng.UniformRandomProvider; + +/** + * <a href="https://en.wikipedia.org/wiki/Marsaglia_polar_method"> + * polar method</a> for sampling from a Log normal distribution. + * + * @since 1.1 + */ +public class MarsagliaLogNormalSampler + extends SamplerBase + implements ContinuousSampler { + /** Scale. */ + private final double scale; + /** Shape. */ + private final double shape; + /** Gaussian sampling. */ + private final NormalizedGaussianSampler gaussian; + + /** + * @param rng Generator of uniformly distributed random numbers. + * @param scale Scale of the Log normal distribution. + * @param shape Shape of the Log normal distribution. + */ + public MarsagliaLogNormalSampler(UniformRandomProvider rng, + double scale, + double shape) { + super(null); // Not used. + this.scale = scale; + this.shape = shape; + gaussian = new MarsagliaNormalizedGaussianSampler(rng); + } + + /** {@inheritDoc} */ + @Override + public double sample() { + return Math.exp(scale + shape * gaussian.sample()); + } + + /** {@inheritDoc} */ + @Override + public String toString() { + return "Marsaglia Log Normal [" + gaussian.toString() + "]"; + } +} http://git-wip-us.apache.org/repos/asf/commons-rng/blob/44945881/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/ContinuousSamplersList.java ---------------------------------------------------------------------- diff --git a/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/ContinuousSamplersList.java b/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/ContinuousSamplersList.java index 0383928..cf89a4d 100644 --- a/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/ContinuousSamplersList.java +++ b/commons-rng-sampling/src/test/java/org/apache/commons/rng/sampling/distribution/ContinuousSamplersList.java @@ -48,7 +48,7 @@ public class ContinuousSamplersList { add(LIST, new org.apache.commons.math3.distribution.NormalDistribution(meanNormal, sigmaNormal), new GaussianSampler(new BoxMullerNormalizedGaussianSampler(RandomSource.create(RandomSource.MT)), meanNormal, sigmaNormal)); - // Gaussian ("Box-Muller" with rejection). + // Gaussian ("Marsaglia"). add(LIST, new org.apache.commons.math3.distribution.NormalDistribution(meanNormal, sigmaNormal), new GaussianSampler(new MarsagliaNormalizedGaussianSampler(RandomSource.create(RandomSource.MT)), meanNormal, sigmaNormal)); @@ -137,6 +137,9 @@ public class ContinuousSamplersList { // Log normal ("Box-Muller"). add(LIST, new org.apache.commons.math3.distribution.LogNormalDistribution(scaleLogNormal, shapeLogNormal), new BoxMullerLogNormalSampler(RandomSource.create(RandomSource.XOR_SHIFT_1024_S), scaleLogNormal, shapeLogNormal)); + // Log normal ("Marsaglia"). + add(LIST, new org.apache.commons.math3.distribution.LogNormalDistribution(scaleLogNormal, shapeLogNormal), + new MarsagliaLogNormalSampler(RandomSource.create(RandomSource.MT_64), scaleLogNormal, shapeLogNormal)); // Logistic ("inverse method"). final double muLogistic = -123.456;
