10000 ENH: np.random.default_gen() by rkern · Pull Request #13840 · numpy/numpy · GitHub
[go: up one dir, main page]

Skip to content

ENH: np.random.default_gen() #13840

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

Merged
merged 10 commits into from
Jun 28, 2019
Next Next commit
ENH: Rename seed_seq argument to seed.
The most common use will certainly be to pass in an integer seed, so I want to
make sure that we talk in terms of "seeds" first and foremost. I don't want to
overload people with new concepts and terminology right out of the gate.
  • Loading branch information
rkern committed Jun 26, 2019
commit 73ebbbb60f16f1b0f19c13aae9d7503f5e682e88
23 changes: 13 additions & 10 deletions numpy/random/bit_generator.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def _coerce_to_uint32_array(x):
Examples
--------
>>> import numpy as np
>>> from seed_seq import _coerce_to_uint32_array
>>> from np.random.bit_generator import _coerce_to_uint32_array
>>> _coerce_to_uint32_array(12345)
array([12345], dtype=uint32)
>>> _coerce_to_uint32_array('12345')
Expand Down Expand Up @@ -467,17 +467,20 @@ ISpawnableSeedSequence.register(SeedSequence)

cdef class BitGenerator():
"""
BitGenerator(seed_seq=None)
BitGenerator(seed=None)

Base Class for generic BitGenerators, which provide a stream
of random bits based on different algorithms. Must be overridden.

Parameters
----------
seed_seq : {None, ISeedSequence, int, sequence[int]}, optional
A ISeedSequence to initialize the BitGenerator. If None, one will be
created. If an int or a sequence of ints, it will be used as the
entropy for creating a SeedSequence.
seed : {None, int, array_like[ints], ISeedSequence}, optional
A seed to initialize the `BitGenerator`. If None, then fresh,
unpredictable entropy will be pulled from the OS. If an ``int`` or
``array_like[ints]`` is passed, then it will be passed to
`SeedSequence` to derive the initial `BitGenerator` state. One may also
pass in an implementor of the `ISeedSequence` interface like
`SeedSequence`.

Attributes
----------
Expand All @@ -492,7 +495,7 @@ cdef class BitGenerator():
SeedSequence
"""

def __init__(self, seed_seq=None):
def __init__(self, seed=None):
self.lock = Lock()
self._bitgen.state = <void *>0
if type(self) is BitGenerator:
Expand All @@ -503,9 +506,9 @@ cdef class BitGenerator():

cdef const char *name = "BitGenerator"
self.capsule = PyCapsule_New(<void *>&self._bitgen, name, NULL)
if not isinstance(seed_seq, ISeedSequence):
seed_seq = SeedSequence(seed_seq)
self._seed_seq = seed_seq
if not isinstance(seed, ISeedSequence):
seed = SeedSequence(seed)
self._seed_seq = seed

# Pickling support:
def __getstate__(self):
Expand Down
13 changes: 8 additions & 5 deletions numpy/random/mt19937.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,19 @@ cdef uint64_t mt19937_raw(void *st) nogil:

cdef class MT19937(BitGenerator):
"""
MT19937(seed_seq=None)
MT19937(seed=None)

Container for the Mersenne Twister pseudo-random number generator.

Parameters
----------
seed_seq : {None, SeedSequence, int, array_like[ints]}, optional
A SeedSequence to initialize the BitGenerator. If None, one will be
created. If an int or array_like[ints], it will be used as the entropy
for creating a SeedSequence.
seed : {None, int, array_like[ints], ISeedSequence}, optional
A seed to initialize the `BitGenerator`. If None, then fresh,
unpredictable entropy will be pulled from the OS. If an ``int`` or
``array_like[ints]`` is passed, then it will be passed to
`SeedSequence` to derive the initial `BitGenerator` state. One may also
pass in an implementor of the `ISeedSequence` interface like
`SeedSequence`.

Attributes
----------
Expand Down
15 changes: 9 additions & 6 deletions numpy/random/pcg64.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,13 @@ cdef class PCG64(BitGenerator):

Parameters
----------
seed_seq : {None, SeedSequence, int, array_like[ints]}, optional
A SeedSequence to initialize the BitGenerator. If None, one will be
created. If an int or array_like[ints], it will be used as the entropy
for creating a SeedSequence.
seed : {None, int, array_like[ints], ISeedSequence}, optional
A seed to initialize the `BitGenerator`. If None, then fresh,
unpredictable entropy will be pulled from the OS. If an ``int`` or
``array_like[ints]`` is passed, then it will be passed to
`SeedSequence` to derive the initial `BitGenerator` state. One may also
pass in an implementor of the `ISeedSequence` interface like
`SeedSequence`.

Notes
-----
Expand Down Expand Up @@ -98,8 +101,8 @@ cdef class PCG64(BitGenerator):
cdef pcg64_state rng_state
cdef pcg64_random_t pcg64_random_state

def __init__(self, seed_seq=None):
BitGenerator.__init__(self, seed_seq)
def __init__(self, seed=None):
BitGenerator.__init__(self, seed)
self.rng_state.pcg_state = &self.pcg64_random_state

self._bitgen.state = <void *>&self.rng_state
Expand Down
45 changes: 24 additions & 21 deletions numpy/random/philox.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -62,18 +62,21 @@ cdef class Philox(BitGenerator):

Parameters
----------
seed_seq : {None, SeedSequence, int, array_like[ints]}, optional
A SeedSequence to initialize the BitGenerator. If None, one will be
created. If an int or array_like[ints], it will be used as the entropy
for creating a SeedSequence.
seed : {None, int, array_like[ints], ISeedSequence}, optional
A seed to initialize the `BitGenerator`. If None, then fresh,
unpredictable entropy will be pulled from the OS. If an ``int`` or
``array_like[ints]`` is passed, then it will be passed to
`SeedSequence` to derive the initial `BitGenerator` state. One may also
pass in an implementor of the `ISeedSequence` interface like
`SeedSequence`.
counter : {None, int, array_like}, optional
Counter to use in the Philox state. Can be either
a Python int (long in 2.x) in [0, 2**256) or a 4-element uint64 array.
If not provided, the RNG is initialized at 0.
key : {None, int, array_like}, optional
Key to use in the Philox state. Unlike seed, the value in key is
directly set. Can be either a Python int (long in 2.x) in [0, 2**128)
or a 2-element uint64 array. `key` and `seed` cannot both be used.
directly set. Can be either a Python int in [0, 2**128) or a 2-element
uint64 array. `key` and `seed` cannot both be used.

Attributes
----------
Expand All @@ -99,18 +102,16 @@ cdef class Philox(BitGenerator):

**State and Seeding**

The ``Philox`` state vector consists of a 2 256-bit values encoded as
4-element uint64 arrays. One is a counter which is incremented by 1 for
every 4 64-bit randoms produced. The second is a key which determined
the sequence produced. Using different keys produces independent
sequences.
The ``Philox`` state vector consists of a 256-bit counter encoded as
a 4-element uint64 array and a 128-bit key encoded as a 2-element uint64
array. The counter is incremented by 1 for every 4 64-bit randoms produced.
The key which determines the sequence produced. Using different keys
produces independent sequences.

``Philox`` is seeded using either a single 64-bit unsigned integer
or a vector of 64-bit unsigned integers. In either case, the seed is
used as an input for a second random number generator,
SplitMix64, and the output of this PRNG function is used as the initial state.
Using a single 64-bit value for the seed can only initialize a small range of
the possible initial state values.
By default, providing a ``seed`` value will derive the 128-bit key using
`SeedSequence`; the counter will be initialized to 0. On the other hand,
one may omit the ``seed`` and provide the ``key`` and/or ``counter``
directly if one wishes to manually control the key.

**Parallel Features**

Expand All @@ -136,7 +137,7 @@ cdef class Philox(BitGenerator):

**Compatibility Guarantee**

``Philox`` makes a guarantee that a fixed seed and will always produce
``Philox`` makes a guarantee that a fixed seed will always produce
the same random integer stream.

Examples
Expand All @@ -157,16 +158,18 @@ cdef class Philox(BitGenerator):
cdef philox4x64_key_t philox_key
cdef philox4x64_ctr_t philox_ctr

def __init__(self, seed_seq=None, counter=None, key=None):
if seed_seq is not None and key is not None:
def __init__(self, seed=None, counter=None, key=None):
if seed is not None and key is not None:
raise ValueError('seed and key cannot be both used')
BitGenerator.__init__(self, seed_seq)
BitGenerator.__init__(self, seed)
self.rng_state.ctr = &self.philox_ctr
self.rng_state.key = &self.philox_key
if key is not None:
key = int_to_array(key, 'key', 128, 64)
for i in range(2):
self.rng_state.key.v[i] = key[i]
# The seed sequence is invalid.
self._seed_seq = None
else:
key = self._seed_seq.generate_state(2, np.uint64)
for i in range(2):
Expand Down
17 changes: 10 additions & 7 deletions numpy/random/sfc64.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,19 @@ cdef double sfc64_double(void* st) nogil:

cdef class SFC64(BitGenerator):
"""
SFC64(seed_seq=None)
SFC64(seed=None)

BitGenerator for Chris Doty-Humphrey's Small Fast Chaotic PRNG.

Parameters
----------
seed_seq : {None, ISeedSequence, int, array_like[ints]}, optional
A SeedSequence to initialize the BitGenerator. If None, one will be
created. If an int or array_like[ints], it will be used as the entropy
for creating a SeedSequence.
seed : {None, int, array_like[ints], ISeedSequence}, optional
A seed to initialize the `BitGenerator`. If None, then fresh,
unpredictable entropy will be pulled from the OS. If an ``int`` or
``array_like[ints]`` is passed, then it will be passed to
`SeedSequence` to derive the initial `BitGenerator` state. One may also
pass in an implementor of the `ISeedSequence` interface like
`SeedSequence`.

Notes
-----
Expand Down Expand Up @@ -72,8 +75,8 @@ cdef class SFC64(BitGenerator):

cdef sfc64_state rng_state

def __init__(self, seed_seq=None):
BitGenerator.__init__(self, seed_seq)
def __init__(self, seed=None):
BitGenerator.__init__(self, seed)
self._bitgen.state = <void *>&self.rng_state
self._bitgen.next_uint64 = &sfc64_uint64
self._bitgen.next_uint32 = &sfc64_uint32
Expand Down
0