RandomLib  1.10
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Macros Pages
ExactNormal.hpp
Go to the documentation of this file.
1 /**
2  * \file ExactNormal.hpp
3  * \brief Header for ExactNormal
4  *
5  * Sample exactly from a normal distribution.
6  *
7  * Copyright (c) Charles Karney (2011-2012) <charles@karney.com> and licensed
8  * under the MIT/X11 License. For more information, see
9  * http://randomlib.sourceforge.net/
10  **********************************************************************/
11 
12 #if !defined(RANDOMLIB_EXACTNORMAL_HPP)
13 #define RANDOMLIB_EXACTNORMAL_HPP 1
14 
16 #include <algorithm> // for max/min
17 
18 #if defined(_MSC_VER)
19 // Squelch warnings about constant conditional expressions
20 # pragma warning (push)
21 # pragma warning (disable: 4127)
22 #endif
23 
24 namespace RandomLib {
25  /**
26  * \brief Sample exactly from a normal distribution.
27  *
28  * Sample \e x from exp(&minus;<i>x</i><sup>2</sup>/2) / sqrt(2&pi;). For
29  * background, see:
30  * - J. von Neumann, Various Techniques used in Connection with Random
31  * Digits, J. Res. Nat. Bur. Stand., Appl. Math. Ser. 12, 36--38
32  * (1951), reprinted in Collected Works, Vol. 5, 768--770 (Pergammon,
33  * 1963).
34  * - D. E. Knuth and A. C. Yao, The Complexity of Nonuniform Random Number
35  * Generation, in "Algorithms and Complexity" (Academic Press, 1976),
36  * pp. 357--428.
37  * - P. Flajolet and N. Saheb, The Complexity of Generating an Exponentially
38  * Distributed Variate, J. Algorithms 7, 463--488 (1986).
39  *
40  * The algorithm is given in
41  * - C. F. F. Karney, <i>Sampling exactly from the normal distribution</i>,
42  * http://arxiv.org/abs/1303.6257 (Mar. 2013).
43  * .
44  * In brief, the algorithm is:
45  * -# Select an integer \e k &ge; 0 with probability
46  * exp(&minus;<i>k</i>/2) (1&minus;exp(&minus;1/2)).
47  * -# Accept with probability
48  * exp(&minus; \e k (\e k &minus; 1) / 2); otherwise, reject and start
49  * over at step 1.
50  * -# Sample a random number \e x uniformly from [0,1).
51  * -# Accept with probability exp(&minus; \e x (\e x + 2\e k) / 2);
52  * otherwise, reject and start over at step 1.
53  * -# Set \e x = \e k + \e x.
54  * -# With probability 1/2, negate \e x.
55  * -# Return \e x.
56  * .
57  * It is easy to show that this algorithm returns samples from the normal
58  * distribution with zero mean and unit variance. Futhermore, all these
59  * steps can be carried out exactly as follows:
60  * - Step 1:
61  * - \e k = 0;
62  * - while (ExpProb(&minus;1/2)) increment \e k by 1.
63  * - Step 2:
64  * - \e n = \e k (\e k &minus; 1) / 2;
65  * - while (\e n > 0)
66  * { if (!ExpProb(&minus;1/2)) go to step 1; decrement \e n by 1; }
67  * - Step 4:
68  * - repeat \e k + 1 times:
69  * if (!ExpProb(&minus; \e x (\e x + 2\e k) / (2\e k + 2))) go to step 1.
70  * .
71  * Here, ExpProb(&minus;\e p) returns true with probability exp(&minus;\e p).
72  * With \e p = 1/2 (steps 1 and 2), this is implemented with von Neumann's
73  * rejection technique:
74  * - Generate a sequence of random numbers <i>U</i><sub><i>i</i></sub> and
75  * find the greatest \e n such that 1/2 > <i>U</i><sub>1</sub> >
76  * <i>U</i><sub>2</sub> > . . . > <i>U</i><sub><i>n</i></sub>. (The
77  * resulting value of \e n may be 0.)
78  * - If \e n is even, accept and return true; otherwise (\e n odd), reject
79  * and return false.
80  * .
81  * For \e p = \e x (\e x + 2\e k) / (2\e k + 2) (step 4), we generalize von
82  * Neumann's procedure as follows:
83  * - Generate two sequences of random numbers <i>U</i><sub><i>i</i></sub>
84  * and <i>V</i><sub><i>i</i></sub> and find the greatest \e n such that
85  * both the following conditions hold
86  * - \e x > <i>U</i><sub>1</sub> > <i>U</i><sub>2</sub> > . . . >
87  * <i>U</i><sub><i>n</i></sub>;
88  * - <i>V</i><sub><i>i</i></sub> &lt; (\e x + 2 \e k) / (2 \e k + 2) for
89  * all \e i in [1, \e n].
90  * .
91  * (The resulting value of \e n may be 0.)
92  * - If \e n is even, accept (return true); otherwise (\e n odd), reject
93  * (return false).
94  * .
95  * Here, instead of testing <i>V</i><sub><i>i</i></sub> &lt; (\e x + 2 \e k)
96  * / (2 \e k + 2), we carry out the following tests:
97  * - return true, with probability 2 \e k / (2 \e k + 2);
98  * - return false, with probability 1 / (2 \e k + 2);
99  * - otherwise (also with probability 1 / (2 \e k + 2)),
100  * return \e x > <i>V</i><sub><i>i</i></sub>.
101  * .
102  * The resulting method now entails evaluation of simple fractional
103  * probabilities (e.g., 1 / (2 \e k + 2)), or comparing random numbers (e.g.,
104  * <i>U</i><sub>1</sub> > <i>U</i><sub>2</sub>). These may be carried out
105  * exactly with a finite mean running time.
106  *
107  * With \e bits = 1, this consumes 30.1 digits on average and the result has
108  * 1.19 digits in the fraction. It takes about 676 ns to generate a result
109  * (1460 ns, including the time to round it to a double). With bits = 32, it
110  * takes 437 ns to generate a result (621 ns, including the time to round it
111  * to a double). In contrast, NormalDistribution takes about 44 ns to
112  * generate a double result.
113  *
114  * Another way of assessing the efficiency of the algorithm is thru the mean
115  * value of the balance = (number of random bits consumed) &minus; (number of
116  * bits in the result). If we code the result in Knuth & Yao's unary-binary
117  * notation, then the mean balance is 26.6.
118  *
119  * For example the following samples from a normal exponential distribution
120  * and prints various representations of the result.
121  * \code
122  #include <RandomLib/RandomNumber.hpp>
123  #include <RandomLib/ExactNormal.hpp>
124 
125  RandomLib::Random r;
126  const int bits = 1;
127  RandomLib::ExactNormal<bits> ndist;
128  for (size_t i = 0; i < 10; ++i) {
129  RandomLib::RandomNumber<bits> x = ndist(r); // Sample
130  std::pair<double, double> z = x.Range();
131  std::cout << x << " = " // Print in binary with ellipsis
132  << "(" << z.first << "," << z.second << ")"; // Print range
133  double v = x.Value<double>(r); // Round exactly to nearest double
134  std::cout << " = " << v << "\n";
135  }
136  \endcode
137  * Here's a possible result: \verbatim
138  -1.00... = (-1.25,-1) = -1.02142
139  -0.... = (-1,0) = -0.319708
140  0.... = (0,1) = 0.618735
141  -0.0... = (-0.5,0) = -0.396591
142  0.0... = (0,0.5) = 0.20362
143  0.0... = (0,0.5) = 0.375662
144  -1.111... = (-2,-1.875) = -1.88295
145  -1.10... = (-1.75,-1.5) = -1.68088
146  -0.... = (-1,0) = -0.577547
147  -0.... = (-1,0) = -0.890553
148  \endverbatim
149  * First number is in binary with ... indicating an infinite sequence of
150  * random bits. Second number gives the corresponding interval. Third
151  * number is the result of filling in the missing bits and rounding exactly
152  * to the nearest representable double.
153  *
154  * This class uses some mutable RandomNumber objects. So a single
155  * ExactNormal object cannot safely be used by multiple threads. In a
156  * multi-processing environment, each thread should use a thread-specific
157  * ExactNormal object. In addition, these should be invoked with
158  * thread-specific random generator objects.
159  *
160  * @tparam bits the number of bits in each digit.
161  **********************************************************************/
162  template<int bits = 1> class ExactNormal {
163  public:
164  /**
165  * Return a random deviate with a normal distribution of mean 0 and
166  * variance 1.
167  *
168  * @tparam Random the type of the random generator.
169  * @param[in,out] r a random generator.
170  * @return the random sample.
171  **********************************************************************/
172  template<class Random> RandomNumber<bits> operator()(Random& r) const;
173  private:
174  /**
175  * Return true with probability exp(&minus;1/2). For \e bits = 1, this
176  * consumes, on average, \e t = 2.846 random digits. We have \e t = \e a
177  * (1&minus;exp(&minus;1/2)) + \e b exp(&minus;1/2), where \e a is the mean
178  * bit count for false result = 3.786 and \e b is the mean bit count for
179  * true result = 2.236.
180  **********************************************************************/
181  template<class Random> bool ExpProbH(Random& r) const;
182 
183  /**
184  * Return true with probability exp(&minus;<i>n</i>/2). For \e bits = 1,
185  * this consumes, on average, \e t
186  * (1&minus;exp(&minus;<i>n</i>/2))/(1&minus;exp(&minus;1/2)) random
187  * digits. A true result uses \e n \e b random digits. A false result
188  * uses \e a + \e b [exp(&minus;1/2)/(1&minus;exp(&minus;1/2)) &minus;
189  * <i>n</i> exp(&minus;<i>n</i>/2)/(1&minus;exp(&minus;<i>n</i>/2))] random
190  * digits.
191  **********************************************************************/
192  template<class Random> bool ExpProb(Random& r, unsigned n) const;
193 
194  /**
195  * Return \e n with probability exp(&minus;<i>n</i>/2)
196  * (1&minus;exp(&minus;1/2)). For \e bits = 1, this consumes \e n \e a +
197  * \e b random digits if the result is \e n. Averaging over \e n this
198  * becomes (\e b &minus; (\e b &minus; \e a) exp(&minus;1/2))/(1 &minus;
199  * exp(&minus;1/2)) digits.
200  **********************************************************************/
201  template<class Random> unsigned ExpProbN(Random& r) const;
202 
203  /**
204  * Return true with probability 1/2. This is similar to r.Boolean() but
205  * forces all the random results to come thru RandomNumber::RandomDigit.
206  **********************************************************************/
207  template<class Random> static bool Boolean(Random& r) {
208  // A more general implementation which deals with the case where the base
209  // might be negative is:
210  //
211  // const unsigned base = 1u << bits;
212  // unsigned b;
213  // do
214  // b = RandomNumber<bits>::RandomDigit(r);
215  // while (b == (base / 2) * 2);
216  // return b & 1u;
217  return RandomNumber<bits>::RandomDigit(r) & 1u;
218  }
219 
220  /**
221  * Implement outcomes for choosing with prob (\e x + 2\e k) / (2\e k + 2);
222  * return:
223  * - 1 (succeed unconditionally) with prob (2\e k) / (2\e k + 2),
224  * - 0 (succeed with probability x) with prob 1 / (2\e k + 2),
225  * - &minus;1 (fail unconditionally) with prob 1 / (2\e k + 2).
226  * .
227  * This simulates \code
228  double x = r.Fixed(); // Uniform in [0,1)
229  x *= (2 * k + 2);
230  return x < 2 * k ? 1 : (x < 2 * k + 1 ? 0 : -1);
231  \endcode
232  **********************************************************************/
233  template<class Random> static int Choose(Random& r, int k) {
234  // Limit base to 2^15 to avoid integer overflow
235  const int b = bits > 15 ? 15 : bits;
236  const unsigned mask = (1u << b) - 1;
237  const int m = 2 * k + 2;
238  int n1 = m - 2, n2 = m - 1;
239  // Evaluate u < n/m where u is a random real number in [0,1). Write u =
240  // (d + u') / 2^b where d is a random integer in [0,2^b) and u' is in
241  // [0,1). Then u < n/m becomes u' < n'/m where n' = 2^b * n - d * m and
242  // exit if n' <= 0 (false) or n' >= m (true).
243  while (true) {
244  int d = (mask & RandomNumber<bits>::RandomDigit(r)) * m;
245  n1 = (std::max)((n1 << b) - d, 0);
246  if (n1 >= m) return 1;
247  n2 = (std::min)((n2 << b) - d, m);
248  if (n2 <= 0) return -1;
249  if (n1 == 0 && n2 == m) return 0;
250  }
251  }
252 
253  mutable RandomNumber<bits> _x;
254  mutable RandomNumber<bits> _p;
255  mutable RandomNumber<bits> _q;
256  };
257 
258  template<int bits> template<class Random>
259  bool ExactNormal<bits>::ExpProbH(Random& r) const {
260  // Bit counts
261  // ExpProbH: 2.846 = 3.786 * (1-exp(-1/2)) + 2.236 * exp(-1/2)
262  // t = a * (1-exp(-1/2)) + b * exp(-1/2)
263  // t = mean bit count for result = 2.846
264  // a = mean bit count for false result = 3.786
265  // b = mean bit count for true result = 2.236
266  //
267  // for bits large
268  // t = exp(1/2) = 1.6487
269  // a = exp(1/2)/(2*(1-exp(-1/2))) = 2.0951
270  // b = exp(1/2)/(2*exp(-1/2)) = 1.3591
271  //
272  // Results for Prob(exp(-1)), omitting first test
273  // total = 5.889, false = 5.347, true = 6.826
274  //
275  // Results for Prob(exp(-1)) using ExpProbH(r) && ExpProbH(r),
276  // total = 4.572 = (1 - exp(-1)) * a + (1 + exp(-1/2)) * exp(-1/2) * b
277  // false = 4.630 = a + b * exp(-1/2)/(1 + exp(-1/2)),
278  // true = 4.472 = 2 * b
279  _p.Init();
280  if (_p.Digit(r, 0) >> (bits - 1)) return true;
281  while (true) {
282  _q.Init(); if (!_q.LessThan(r, _p)) return false;
283  _p.Init(); if (!_p.LessThan(r, _q)) return true;
284  }
285  }
286 
287  template<int bits> template<class Random>
288  bool ExactNormal<bits>::ExpProb(Random& r, unsigned n) const {
289  // Bit counts
290  // ExpProb(n): t * (1-exp(-n/2))/(1-exp(-1/2))
291  // ExpProb(n) = true: n * b
292  // ExpProb(n) = false: a +
293  // b * (exp(-1/2)/(1-exp(-1/2)) - n*exp(-n/2)/(1-exp(-n/2)))
294  while (n--) { if (!ExpProbH(r)) return false; }
295  return true;
296  }
297 
298  template<int bits> template<class Random>
299  unsigned ExactNormal<bits>::ExpProbN(Random& r) const {
300  // Bit counts
301  // ExpProbN() = n: n * a + b
302  unsigned n = 0;
303  while (ExpProbH(r)) ++n;
304  return n;
305  }
306 
307  template<int bits> template<class Random> RandomNumber<bits>
309  // With bits = 1,
310  // - mean number of bits used = 30.10434
311  // - mean number of bits in fraction = 1.18700
312  // - mean number of bits in result = 3.55257 (unary-binary)
313  // - mean balance = 30.10434 - 3.55257 = 26.55177
314  // - mean number of bits to generate a double = 83.33398
315  // .
316  // Note
317  // - unary-binary notation (Knuth + Yao, 1976): write x = n + y, with n =
318  // integer and y in [0,1). If n >=0, then write (n+1) 1's followed by a
319  // 0; otherwise (n < 0), write (-n) 0's followed by a 1. Write y as a
320  // binary fraction.
321  // - (bits in result) - (bits in fraction) = 2 (for encoding overhead for
322  // the integer part) + 0.36557, where 0.36557 = (bits used for integer
323  // part) = sum(k*int(sqrt(2/pi)*exp(-x^2/2), x=k..k+1), k=0..inf)
324  // - (bits for double) approx (bits used) - (bits in fraction) + 1 (for
325  // guard bit) + 53.41664 where 53.41664 = (bits in fraction of double) =
326  // sum((52-l)*int(sqrt(2/pi)*exp(-x^2/2), x=2^l,2^(l+1)), l=-inf..inf)
327  // This is approximate because it doesn't account for the minimum
328  // exponent, denormalized numbers, and rounding changing the exponent.
329  //
330  while (true) {
331  // Executed sqrt(2/pi)/(1-exp(-1/2)) = 2.027818889827955 times on
332  // average.
333  unsigned k = ExpProbN(r); // the integer part of the result.
334  if (ExpProb(r, (k - 1) * k)) {
335  // Probability that this test succeeds is
336  // (1 - exp(-1/2)) * sum(exp(-k/2) * exp(-(k-1)*k/2), k=0..inf))
337  // = (1 - exp(-1/2)) * G = 0.689875359564630
338  // where G = sum(exp(-k^2/2, k=0..inf) = 1.75331414402145
339  // For k == 0, sample from exp(-x^2/2) for x in [0,1]. This succeeds
340  // with probability int(exp(-x^2/2),x=0..1).
341  //
342  // For general k, substitute x' = x + k in exp(-x'^2/2), and obtain
343  // exp(-k^2/2) * exp(-x*(x+2*k)/2). So sample from exp(-x*(x+2*k)/2).
344  // This succeeds with probability int(exp(-x*(x+2*k)/2),x=0..1) =
345  // int(exp(-x^2/2),x=k..k+1)*exp(k^2/2) =
346  //
347  // 0.8556243918921 for k = 0
348  // 0.5616593588061 for k = 1
349  // 0.3963669350376 for k = 2
350  // 0.2974440159655 for k = 3
351  // 0.2345104783458 for k = 4
352  // 0.1921445042826 for k = 5
353  //
354  // Returns a result with prob sqrt(pi/2) / G = 0.714825772431666;
355  // otherwise another trip through the outer loop is taken.
356  _x.Init();
357  unsigned s = 1;
358  for (unsigned j = 0; j <= k; ++j) { // execute k + 1 times
359  bool first;
360  for (s = 1, first = true; ; s ^= 1, first = false) {
361  // A simpler algorithm is indicated by ALT, results in
362  // - mean number of bits used = 29.99968
363  // - mean number of bits in fraction = 1.55580
364  // - mean number of bits in result = 3.92137 (unary-binary)
365  // - mean balance = 29.99968 - 3.92137 = 26.07831
366  // - mean number of bits to generate a double = 82.86049
367  // .
368  // This has a smaller balance (by 0.47 bits). However the number
369  // of bits in the fraction is larger by 0.37
370  if (first) { // ALT: if (false) {
371  // This implements the success prob (x + 2*k) / (2*k + 2).
372  int y = Choose(r, k);
373  if (y < 0) break; // the y test fails
374  _q.Init();
375  if (y > 0) { // the y test succeeds just test q < x
376  if (!_q.LessThan(r, _x)) break;
377  } else { // the y test is ambiguous
378  // Test max(q, p) < x. List _q before _p since it ends up with
379  // slightly more digits generated (and these will be used
380  // subsequently). (_p's digits are immediately thrown away.)
381  _p.Init(); if (!_x.GreaterPair(r, _q, _p)) break;
382  }
383  } else {
384  // Split off the failure test for k == 0, i.e., factor the prob
385  // x/2 test into the product: 1/2 (here) times x (in assignment
386  // of y).
387  if (k == 0 && Boolean(r)) break;
388  // ALT: _q.Init(); if (!_q.LessThan(r, first ? _x : _p)) break;
389  _q.Init(); if (!_q.LessThan(r, _p)) break;
390  // succeed with prob k == 0 ? x : (x + 2*k) / (2*k + 2)
391  int y = k == 0 ? 0 : Choose(r, k);
392  if (y < 0)
393  break;
394  else if (y == 0) {
395  _p.Init(); if (!_p.LessThan(r, _x)) break;
396  }
397  }
398  _p.swap(_q); // a fast way of doing p = q
399  }
400  if (s == 0) break;
401  }
402  if (s != 0) {
403  _x.AddInteger(k);
404  if (Boolean(r)) _x.Negate(); // half of the numbers are negative
405  return _x;
406  }
407  }
408  }
409  }
410 
411 } // namespace RandomLib
412 
413 #if defined(_MSC_VER)
414 # pragma warning (pop)
415 #endif
416 
417 #endif // RANDOMLIB_EXACTNORMAL_HPP
Header for RandomNumber.
Generate random integers, reals, and booleans.
Infinite precision random numbers.
static unsigned RandomDigit(Random &r)
RandomCanonical< RandomGenerator > Random
Definition: Random.hpp:135
Sample exactly from a normal distribution.
RandomNumber< bits > operator()(Random &r) const