LevySampler.java

  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.rng.sampling.distribution;

  18. import org.apache.commons.rng.UniformRandomProvider;

  19. /**
  20.  * Sampling from a Lévy distribution.
  21.  *
  22.  * @see <a href="https://en.wikipedia.org/wiki/L%C3%A9vy_distribution">Lévy distribution</a>
  23.  * @since 1.4
  24.  */
  25. public final class LevySampler implements SharedStateContinuousSampler {
  26.     /** Gaussian sampler. */
  27.     private final NormalizedGaussianSampler gaussian;
  28.     /** Location. */
  29.     private final double location;
  30.     /** Scale. */
  31.     private final double scale;
  32.     /** RNG (used for the toString() method). */
  33.     private final UniformRandomProvider rng;

  34.     /**
  35.      * @param rng Generator of uniformly distributed random numbers.
  36.      * @param location Location of the Lévy distribution.
  37.      * @param scale Scale of the Lévy distribution.
  38.      */
  39.     private LevySampler(UniformRandomProvider rng,
  40.                         double location,
  41.                         double scale) {
  42.         this.gaussian = ZigguratSampler.NormalizedGaussian.of(rng);
  43.         this.location = location;
  44.         this.scale = scale;
  45.         this.rng = rng;
  46.     }

  47.     /**
  48.      * @param rng Generator of uniformly distributed random numbers.
  49.      * @param source Source to copy.
  50.      */
  51.     private LevySampler(UniformRandomProvider rng,
  52.                         LevySampler source) {
  53.         this.gaussian = ZigguratSampler.NormalizedGaussian.of(rng);
  54.         this.location = source.location;
  55.         this.scale = source.scale;
  56.         this.rng = rng;
  57.     }

  58.     /** {@inheritDoc} */
  59.     @Override
  60.     public double sample() {
  61.         final double n = gaussian.sample();
  62.         return scale / (n * n) + location;
  63.     }

  64.     /** {@inheritDoc} */
  65.     @Override
  66.     public String toString() {
  67.         return "Lévy deviate [" + rng.toString() + "]";
  68.     }

  69.     /** {@inheritDoc} */
  70.     @Override
  71.     public LevySampler withUniformRandomProvider(UniformRandomProvider rng) {
  72.         return new LevySampler(rng, this);
  73.     }

  74.     /**
  75.      * Create a new Lévy distribution sampler.
  76.      *
  77.      * @param rng Generator of uniformly distributed random numbers.
  78.      * @param location Location of the Lévy distribution.
  79.      * @param scale Scale of the Lévy distribution.
  80.      * @return the sampler
  81.      * @throws IllegalArgumentException if {@code scale <= 0}
  82.      */
  83.     public static LevySampler of(UniformRandomProvider rng,
  84.                                  double location,
  85.                                  double scale) {
  86.         InternalUtils.requireStrictlyPositive(scale, "scale");
  87.         return new LevySampler(rng, location, scale);
  88.     }
  89. }