InverseTransformContinuousSampler.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.  * Distribution sampler that uses the
  21.  * <a href="https://en.wikipedia.org/wiki/Inverse_transform_sampling">
  22.  * inversion method</a>.
  23.  *
  24.  * It can be used to sample any distribution that provides access to its
  25.  * <em>inverse cumulative probability function</em>.
  26.  *
  27.  * <p>Sampling uses {@link UniformRandomProvider#nextDouble()}.</p>
  28.  *
  29.  * <p>Example:</p>
  30.  * <pre><code>
  31.  * import org.apache.commons.math3.distribution.RealDistribution;
  32.  * import org.apache.commons.math3.distribution.ChiSquaredDistribution;
  33.  *
  34.  * import org.apache.commons.rng.simple.RandomSource;
  35.  * import org.apache.commons.rng.sampling.distribution.ContinuousSampler;
  36.  * import org.apache.commons.rng.sampling.distribution.InverseTransformContinuousSampler;
  37.  * import org.apache.commons.rng.sampling.distribution.ContinuousInverseCumulativeProbabilityFunction;
  38.  *
  39.  * // Distribution to sample.
  40.  * final RealDistribution dist = new ChiSquaredDistribution(9);
  41.  * // Create the sampler.
  42.  * final ContinuousSampler chiSquareSampler =
  43.  *     InverseTransformContinuousSampler.of(RandomSource.XO_RO_SHI_RO_128_PP.create(),
  44.  *                                          new ContinuousInverseCumulativeProbabilityFunction() {
  45.  *                                              public double inverseCumulativeProbability(double p) {
  46.  *                                                  return dist.inverseCumulativeProbability(p);
  47.  *                                              }
  48.  *                                          });
  49.  *
  50.  * // Generate random deviate.
  51.  * double random = chiSquareSampler.sample();
  52.  * </code></pre>
  53.  *
  54.  * @since 1.0
  55.  */
  56. public class InverseTransformContinuousSampler
  57.     extends SamplerBase
  58.     implements SharedStateContinuousSampler {
  59.     /** Inverse cumulative probability function. */
  60.     private final ContinuousInverseCumulativeProbabilityFunction function;
  61.     /** Underlying source of randomness. */
  62.     private final UniformRandomProvider rng;

  63.     /**
  64.      * Create an instance.
  65.      *
  66.      * @param rng Generator of uniformly distributed random numbers.
  67.      * @param function Inverse cumulative probability function.
  68.      */
  69.     public InverseTransformContinuousSampler(UniformRandomProvider rng,
  70.                                              ContinuousInverseCumulativeProbabilityFunction function) {
  71.         super(null);
  72.         this.rng = rng;
  73.         this.function = function;
  74.     }

  75.     /** {@inheritDoc} */
  76.     @Override
  77.     public double sample() {
  78.         return function.inverseCumulativeProbability(rng.nextDouble());
  79.     }

  80.     /** {@inheritDoc} */
  81.     @Override
  82.     public String toString() {
  83.         return function.toString() + " (inverse method) [" + rng.toString() + "]";
  84.     }

  85.     /**
  86.      * {@inheritDoc}
  87.      *
  88.      * <p>Note: The new sampler will share the inverse cumulative probability function. This
  89.      * must be suitable for concurrent use to ensure thread safety.</p>
  90.      *
  91.      * @since 1.3
  92.      */
  93.     @Override
  94.     public SharedStateContinuousSampler withUniformRandomProvider(UniformRandomProvider rng) {
  95.         return new InverseTransformContinuousSampler(rng, function);
  96.     }

  97.     /**
  98.      * Create a new inverse-transform continuous sampler.
  99.      *
  100.      * <p>To use the sampler to
  101.      * {@link org.apache.commons.rng.sampling.SharedStateSampler share state} the function must be
  102.      * suitable for concurrent use.</p>
  103.      *
  104.      * @param rng Generator of uniformly distributed random numbers.
  105.      * @param function Inverse cumulative probability function.
  106.      * @return the sampler
  107.      * @see #withUniformRandomProvider(UniformRandomProvider)
  108.      * @since 1.3
  109.      */
  110.     public static SharedStateContinuousSampler of(UniformRandomProvider rng,
  111.                                                   ContinuousInverseCumulativeProbabilityFunction function) {
  112.         return new InverseTransformContinuousSampler(rng, function);
  113.     }
  114. }