RandomLib
1.10
|
The discrete normal distribution. More...
#include <RandomLib/DiscreteNormal.hpp>
Public Member Functions | |
DiscreteNormal (IntType sigma_num, IntType sigma_den=1, IntType mu_num=0, IntType mu_den=1) | |
template<class Random > | |
IntType | operator() (Random &r) const |
The discrete normal distribution.
Sample integers i with probability proportional to
\[ \exp\biggl[-\frac12\biggl(\frac{i-\mu}{\sigma}\biggr)^2\biggr], \]
where σ and μ are given as rationals (the ratio of two integers). The sampling is exact (provided that the random generator is ideal). For example
prints out 100 samples with σ = 7 and μ = 1/3.
The algorithm is much the same as for ExactNormal; for details see
That algorithm samples the integer part of the result k, samples x in [0,1], and (unless rejected) returns s(k + x), where s = ±1. For the discrete case, we sample x in [0,1) such that
\[ s(k + x) = (i - \mu)/\sigma, \]
or
\[ x = s(i - \mu)/\sigma - k \]
The value of i which results in the smallest x ≥ 0 is
\[ i_0 = s\lceil k \sigma + s \mu\rceil \]
so sample
\[ i = i_0 + sj \]
where j is uniformly distributed in [0, ⌈σ⌉). The corresponding value of x is
\[ \begin{aligned} x &= \bigl(si_0 - (k\sigma + s\mu)\bigr)/\sigma + j/\sigma\\ &= x_0 + j/\sigma,\\ x_0 &= \bigl(\lceil k \sigma + s \mu\rceil - (k \sigma + s \mu)\bigr)/\sigma. \end{aligned} \]
After x is sampled in this way, it should be rejected if x ≥ 1 (this is counted with the next larger value of k) or if x = 0, k = 0, and s = −1 (to avoid double counting the origin). If x is accepted (in Step 4 of the ExactNormal algorithm), then return i.
When σ and μ are given as rationals, all the arithmetic outlined above can be carried out exactly. The basic rejection techniques used by ExactNormal are exact. Thus the result of this discrete form of the algorithm is also exact.
RandomLib provides two classes to sample from this distribution:
The basic algorithm is the same in the two cases. The main advantages of this method are:
The possible drawbacks of this method are:
long long
),This class uses a mutable private vector. So a single DiscreteNormal object cannot safely be used by multiple threads. In a multi-processing environment, each thread should use a thread-specific DiscreteNormal object.
Some timing results for IntType = int, μ = 0, and 108 samples (time = time per sample, including setup time, rv = mean number of random variables per sample)
IntType | the integer type to use (default int). |
Definition at line 140 of file DiscreteNormal.hpp.
RandomLib::DiscreteNormal< IntType >::DiscreteNormal | ( | IntType | sigma_num, |
IntType | sigma_den = 1 , |
||
IntType | mu_num = 0 , |
||
IntType | mu_den = 1 |
||
) |
Constructor.
[in] | sigma_num | the numerator of σ. |
[in] | sigma_den | the denominator of σ (default 1). |
[in] | mu_num | the numerator of μ (default 0). |
[in] | mu_den | the denominator of μ (default 1). |
The constructor creates a DiscreteNormal objects for sampling with specific values of σ and μ. This may throw an exception if the parameters are such that overflow is possible. Internally σ and μ are expressed with a common denominator, so it may be possible to avoid overflow by picking the fractions of these quantities so that sigma_den and mu_den have many common factors.
Definition at line 237 of file DiscreteNormal.hpp.
References STATIC_ASSERT.
IntType RandomLib::DiscreteNormal< IntType >::operator() | ( | Random & | r | ) | const |
Return a sample.
Random | the type of the random generator. |
[in,out] | r | a random generator. |
Definition at line 288 of file DiscreteNormal.hpp.
References RandomLib::RandomCanonical< Generator >::Boolean().