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.rng.sampling.distribution;
18  
19  import org.apache.commons.rng.UniformRandomProvider;
20  
21  /**
22   * Sampling from a Lévy distribution.
23   *
24   * @see <a href="https://en.wikipedia.org/wiki/L%C3%A9vy_distribution">Lévy distribution</a>
25   * @since 1.4
26   */
27  public final class LevySampler implements SharedStateContinuousSampler {
28      /** Gaussian sampler. */
29      private final NormalizedGaussianSampler gaussian;
30      /** Location. */
31      private final double location;
32      /** Scale. */
33      private final double scale;
34      /** RNG (used for the toString() method). */
35      private final UniformRandomProvider rng;
36  
37      /**
38       * @param rng Generator of uniformly distributed random numbers.
39       * @param location Location of the Lévy distribution.
40       * @param scale Scale of the Lévy distribution.
41       */
42      private LevySampler(UniformRandomProvider rng,
43                          double location,
44                          double scale) {
45          this.gaussian = ZigguratSampler.NormalizedGaussian.of(rng);
46          this.location = location;
47          this.scale = scale;
48          this.rng = rng;
49      }
50  
51      /**
52       * @param rng Generator of uniformly distributed random numbers.
53       * @param source Source to copy.
54       */
55      private LevySampler(UniformRandomProvider rng,
56                          LevySampler source) {
57          this.gaussian = ZigguratSampler.NormalizedGaussian.of(rng);
58          this.location = source.location;
59          this.scale = source.scale;
60          this.rng = rng;
61      }
62  
63      /** {@inheritDoc} */
64      @Override
65      public double sample() {
66          final double n = gaussian.sample();
67          return scale / (n * n) + location;
68      }
69  
70      /** {@inheritDoc} */
71      @Override
72      public String toString() {
73          return "Lévy deviate [" + rng.toString() + "]";
74      }
75  
76      /** {@inheritDoc} */
77      @Override
78      public LevySampler withUniformRandomProvider(UniformRandomProvider rng) {
79          return new LevySampler(rng, this);
80      }
81  
82      /**
83       * Create a new Lévy distribution sampler.
84       *
85       * @param rng Generator of uniformly distributed random numbers.
86       * @param location Location of the Lévy distribution.
87       * @param scale Scale of the Lévy distribution.
88       * @return the sampler
89       * @throws IllegalArgumentException if {@code scale <= 0}
90       */
91      public static LevySampler of(UniformRandomProvider rng,
92                                   double location,
93                                   double scale) {
94          if (scale <= 0) {
95              throw new IllegalArgumentException("scale is not strictly positive: " + scale);
96          }
97          return new LevySampler(rng, location, scale);
98      }
99  }