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 InternalUtils.requireStrictlyPositive(scale, "scale");
95 return new LevySampler(rng, location, scale);
96 }
97 }