PoissonSampler.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.  * Sampler for the <a href="http://mathworld.wolfram.com/PoissonDistribution.html">Poisson distribution</a>.
  21.  *
  22.  * <ul>
  23.  *  <li>
  24.  *   For small means, a Poisson process is simulated using uniform deviates, as described in
  25.  *   <blockquote>
  26.  *    Knuth (1969). <i>Seminumerical Algorithms</i>. The Art of Computer Programming,
  27.  *    Volume 2. Chapter 3.4.1.F.3 Important integer-valued distributions: The Poisson distribution.
  28.  *    Addison Wesley.
  29.  *   </blockquote>
  30.  *   The Poisson process (and hence, the returned value) is bounded by {@code 1000 * mean}.
  31.  *  </li>
  32.  *  <li>
  33.  *   For large means, we use the rejection algorithm described in
  34.  *   <blockquote>
  35.  *    Devroye, Luc. (1981). <i>The Computer Generation of Poisson Random Variables</i><br>
  36.  *    <strong>Computing</strong> vol. 26 pp. 197-207.
  37.  *   </blockquote>
  38.  *  </li>
  39.  * </ul>
  40.  *
  41.  * <p>Sampling uses:</p>
  42.  *
  43.  * <ul>
  44.  *   <li>{@link UniformRandomProvider#nextDouble()}
  45.  *   <li>{@link UniformRandomProvider#nextLong()} (large means only)
  46.  * </ul>
  47.  *
  48.  * @since 1.0
  49.  */
  50. public class PoissonSampler
  51.     extends SamplerBase
  52.     implements SharedStateDiscreteSampler {

  53.     /**
  54.      * Value for switching sampling algorithm.
  55.      *
  56.      * <p>Package scope for the {@link PoissonSamplerCache}.
  57.      */
  58.     static final double PIVOT = 40;
  59.     /** The internal Poisson sampler. */
  60.     private final SharedStateDiscreteSampler poissonSamplerDelegate;

  61.     /**
  62.      * This instance delegates sampling. Use the factory method
  63.      * {@link #of(UniformRandomProvider, double)} to create an optimal sampler.
  64.      *
  65.      * @param rng Generator of uniformly distributed random numbers.
  66.      * @param mean Mean.
  67.      * @throws IllegalArgumentException if {@code mean <= 0} or {@code mean > 0.5 *}
  68.      * {@link Integer#MAX_VALUE}.
  69.      */
  70.     public PoissonSampler(UniformRandomProvider rng,
  71.                           double mean) {
  72.         // Delegate all work to specialised samplers.
  73.         this(of(rng, mean));
  74.     }

  75.     /**
  76.      * @param delegate Poisson sampler.
  77.      */
  78.     private PoissonSampler(SharedStateDiscreteSampler delegate) {
  79.         super(null);
  80.         poissonSamplerDelegate = delegate;
  81.     }

  82.     /** {@inheritDoc} */
  83.     @Override
  84.     public int sample() {
  85.         return poissonSamplerDelegate.sample();
  86.     }

  87.     /** {@inheritDoc} */
  88.     @Override
  89.     public String toString() {
  90.         return poissonSamplerDelegate.toString();
  91.     }

  92.     /**
  93.      * {@inheritDoc}
  94.      *
  95.      * @since 1.3
  96.      */
  97.     @Override
  98.     public SharedStateDiscreteSampler withUniformRandomProvider(UniformRandomProvider rng) {
  99.         // Direct return of the optimised sampler
  100.         return poissonSamplerDelegate.withUniformRandomProvider(rng);
  101.     }

  102.     /**
  103.      * Creates a new Poisson distribution sampler.
  104.      *
  105.      * @param rng Generator of uniformly distributed random numbers.
  106.      * @param mean Mean.
  107.      * @return the sampler
  108.      * @throws IllegalArgumentException if {@code mean <= 0} or {@code mean > 0.5 *}
  109.      * {@link Integer#MAX_VALUE}.
  110.      * @since 1.3
  111.      */
  112.     public static SharedStateDiscreteSampler of(UniformRandomProvider rng,
  113.                                                 double mean) {
  114.         // Each sampler should check the input arguments.
  115.         return mean < PIVOT ?
  116.             SmallMeanPoissonSampler.of(rng, mean) :
  117.             LargeMeanPoissonSampler.of(rng, mean);
  118.     }
  119. }