10000 BUG: Unexpected divergence in random state with rng.choice() when sampling from single-element lists · Issue #28620 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content
/ numpy Public

BUG: Unexpected divergence in random state with rng.choice() when sampling from single-element lists #28620

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
DavCorSar opened this issue Apr 1, 2025 · 1 comment

Comments

@DavCorSar
Copy link
DavCorSar commented Apr 1, 2025

Describe the issue:

When using two random number generators (default_rng from NumPy) initialized with the same seed, I encounter unexpected divergence in their subsequent random draws if one of the generators calls choice() on a single-element list. This divergence does not happen when sampling from lists of size 2 or greater.

Reproduce the code example:

import numpy as np

print(np.__version__)  # 2.2.4

rng1 = np.random.default_rng(42)
rng2 = np.random.default_rng(42)

print(rng1.random())  # 0.7739560485559633
print(rng2.random())  # 0.7739560485559633

choices1 = ['a']
choices2 = ['a', 'b']
print(rng1.choice(choices1))  # np.str_('a')
print(rng2.choice(choices2))  # np.str_('b')

print(rng1.random())  # 0.4388784397520523  <-- Divergence here
print(rng2.random())  # 0.8585979199113825

Python and NumPy Versions:

NumPy version: 2.2.4
Sys version: 3.12.3 (main, Feb 4 2025, 14:48:35) [GCC 13.3.0]

Runtime Environment:

[{'numpy_version': '2.2.4',
'python': '3.12.3 (main, Feb 4 2025, 14:48:35) [GCC 13.3.0]',
'uname': uname_result(system='Linux', node='Syl', release='6.8.0-56-generic', version='#58-Ubuntu SMP PREEMPT_DYNAMIC Fri Feb 14 15:33:28 UTC 2025', machine='x86_64')},
{'simd_extensions': {'baseline': ['SSE', 'SSE2', 'SSE3'],
'found': ['SSSE3',
'SSE41',
'POPCNT',
'SSE42',
'AVX',
'F16C',
'FMA3',
'AVX2'],
'not_found': ['AVX512F',
'AVX512CD',
'AVX512_KNL',
'AVX512_KNM',
'AVX512_SKX',
'AVX512_CLX',
'AVX512_CNL',
'AVX512_ICL']}},
{'architecture': 'Haswell',
'filepath': '/home/david/Escritorio/Projects/report_numpy_bug/.venv/lib/python3.12/site-packages/numpy.libs/libscipy_openblas64_-6bb31eeb.so',
'internal_api': 'openblas',
'num_threads': 16,
'prefix': 'libscipy_openblas',
'threading_layer': 'pthreads',
'user_api': 'blas',
'version': '0.3.28'}]

Context for the issue:

When both lists contain more than one element, the random number generators (RNGs) initialized with the same seed remain in sync after calling choice(). For example:

import numpy as np

print(np.__version__)  # 2.2.4

rng1 = np.random.default_rng(42)
rng2 = np.random.default_rng(42)

# Both generators start in sync
print(rng1.random())  # e.g., 0.7739560485559633
print(rng2.random())  # e.g., 0.7739560485559633

choices1 = ['a', 'b']
choices2 = ['a', 'b', 'c']

print(rng1.choice(choices1))  # e.g., np.str_('b')
print(rng2.choice(choices2))  # e.g., np.str_('b')

# Subsequent draws are still aligned
print(rng1.random())  # e.g., 0.8585979199113825
print(rng2.random())  # e.g., 0.8585979199113825

In this scenario, there is no divergence between the two RNGs. By contrast, as shown above, using a single-element list in one generator (and a multi-element list in the other) leads to divergence. This suggests that rng.choice() behaves differently when the input list has exactly one element, which appears to alter or skip the random state in an unexpected way.

@WarrenWeckesser
Copy link
Member

When the length of choices1 is 1, there is only one possible outcome, so the underlying random number generator doesn't have to generate a random value and advance its internal state. So in your example, the result of this line

print(rng1.random())  # 0.4388784397520523  <-- Divergence here

is the same as the result that would be obtained if you hadn't called rng1.choice(choices1) at all.

This is not a bug. There are no guarantees that calls of a Generator method with different arguments will advance the internal state of the RNG identically.

@rkern rkern closed this as not planned Won't fix, can't repro, duplicate, stale Apr 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants
0