You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Alex Herbert (Jira)" <ji...@apache.org> on 2021/06/11 12:08:00 UTC
[jira] [Resolved] (RNG-144) AhrensDieterExponentialSampler can
infinite loop
[ https://issues.apache.org/jira/browse/RNG-144?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Alex Herbert resolved RNG-144.
------------------------------
Fix Version/s: 1.4
Resolution: Fixed
Resolved by creating the first uniform deviate in the interval {{(0, 1]}}, i.e. non-zero. If the first uniform deviate is 1 the method creates a valid sample.
The rest of the sample method is robust to zeros from the underlying generator nextDouble() method.
Fixed in commits:
585e205cb3266c6fc3074699946a080c61aa5c3e
c7779b1e32ce3533d2f9f440b46106bb1907be46
> AhrensDieterExponentialSampler can infinite loop
> ------------------------------------------------
>
> Key: RNG-144
> URL: https://issues.apache.org/jira/browse/RNG-144
> Project: Commons RNG
> Issue Type: Bug
> Components: sampling
> Affects Versions: 1.3
> Reporter: Alex Herbert
> Priority: Minor
> Fix For: 1.4
>
>
> If the RNG provides a value of 0 for a uniform deviate the sampler will infinite loop. Here is the initial part of the sample method:
> {code:java}
> public double sample() {
> // Step 1:
> double a = 0;
> // *** u can be zero ***
> double u = rng.nextDouble();
> // Step 2 and 3:
> while (u < 0.5) {
> a += EXPONENTIAL_SA_QI[0];
> // *** u is always zero => infinite loop ***
> u *= 2;
> }
> {code}
> The origin of the method is not stated in the source; the reference from the original source in Commons Math 3 is to a dead link. A brief search did not find a reference with this method.
> It is assumed the variable u should be in the open interval (0, 1), not the interval [0, 1) typically provided by a RNG supplying the 2^53 dyadic rationals in the interval 0 to 1.
> This can be fixed by using an open interval or changing the interval to (0, 1]:
> {code:java}
> double nextDouble() {
> // A value in [0, 1)
> double x = rng.nextDouble();
> // recursion if zero
> return x == 0 ? nextDouble() : x;
> }
> double nextDouble() {
> // A value in (0, 1].
> return 0x1.0p-53 * ((rng.nextLong() >>> 11) + 1L);
> }
> {code}
> Either method fixes this test:
> {code:java}
> @Test
> public void testSamplerWithZeroFromFirstRandomDeviate() {
> // Create a zero for the first call to the sampler, then non-zero after
> final UniformRandomProvider rng = new SplitMix64(0) {
> private long l = 0;
> @Override
> public long nextLong() { return l++; }
> };
> final SharedStateContinuousSampler sampler =
> AhrensDieterExponentialSampler.of(rng, 1);
> // Infinite loop
> sampler.sample();
> }
> {code}
--
This message was sent by Atlassian Jira
(v8.3.4#803005)