Skip to content
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

ENH: np.random.default_gen() #13840

Merged
merged 10 commits into from Jun 28, 2019
2 changes: 2 additions & 0 deletions doc/source/reference/random/generator.rst
Expand Up @@ -12,6 +12,8 @@ random values from useful distributions. The default BitGenerator used by
can be changed by passing an instantized BitGenerator to ``Generator``.


.. autofunction:: default_gen

.. autoclass:: Generator
:exclude-members:

Expand Down
7 changes: 4 additions & 3 deletions doc/source/reference/random/index.rst
Expand Up @@ -48,9 +48,10 @@ the random values are generated by `~.PCG64`. The

.. code-block:: python
# As replacement for RandomState()
from numpy.random import Generator
rg = Generator()
# As replacement for RandomState(); default_gen() instantiates Generator with
# the default PCG64 BitGenerator.
from numpy.random import default_gen
rg = default_gen()
rg.standard_normal()
rg.bit_generator
Expand Down
16 changes: 8 additions & 8 deletions doc/source/reference/random/new-or-different.rst
Expand Up @@ -19,15 +19,15 @@ Quick comparison of legacy `mtrand <legacy>`_ to the new `Generator`
================== ==================== =============
Feature Older Equivalent Notes
------------------ -------------------- -------------
`Generator` `RandomState` ``Generator`` requires a stream
`~.Generator` `~.RandomState` ``Generator`` requires a stream
source, called a `BitGenerator
<bit_generators>` A number of these
are provided. ``RandomState`` uses
only the Box- Muller method.
only the Mersenne Twister.
------------------ -------------------- -------------
``np.random.`` ``np.random.`` Access the values in a BitGenerator,
``Generator().`` ``random_sample()`` convert them to ``float64`` in the
``random()`` interval ``[0.0.,`` `` 1.0)``.
``random`` ``random_sample`` Access the values in a BitGenerator,
convert them to ``float64`` in the
interval ``[0.0.,`` `` 1.0)``.
In addition to the ``size`` kwarg, now
supports ``dtype='d'`` or ``dtype='f'``,
and an ``out`` kwarg to fill a user-
Expand All @@ -36,8 +36,8 @@ Feature Older Equivalent Notes
Many other distributions are also
supported.
------------------ -------------------- -------------
``Generator().`` ``randint``, Use the ``endpoint`` kwarg to adjust
``integers()`` ``random_integers`` the inclusion or exclution of the
``integers`` ``randint``, Use the ``endpoint`` kwarg to adjust
``random_integers`` the inclusion or exclution of the
``high`` interval endpoint
================== ==================== =============

Expand All @@ -56,7 +56,7 @@ And in more detail:
random numbers from a discrete uniform distribution. The ``rand`` and
``randn`` methods are only available through the legacy `~.RandomState`.
This replaces both ``randint`` and the deprecated ``random_integers``.
* The Box-Muller used to produce NumPy's normals is no longer available.
* The Box-Muller method used to produce NumPy's normals is no longer available.
* All bit generators can produce doubles, uint64s and
uint32s via CTypes (`~PCG64.ctypes`) and CFFI (`~PCG64.cffi`).
This allows these bit generators to be used in numba.
Expand Down
54 changes: 33 additions & 21 deletions numpy/random/__init__.py
Expand Up @@ -3,16 +3,42 @@
Random Number Generation
========================

Instantiate a BitGenerator and wrap it in a Generator
which will convert the uniform stream to a number of distributions. The "bare"
functions are kept for legacy code, they should be called with the newer API
via ``np.random.Generator().function`` instead
Use ``default_gen()`` to create a `Generator` and call its methods.

=============== =========================================================
Generator
--------------- ---------------------------------------------------------
Generator Class implementing all of the random number distributions
default_gen Default constructor for ``Generator``
=============== =========================================================

============================================= ===
BitGenerator Streams that work with Generator
--------------------------------------------- ---
MT19937
PCG64
Philox
SFC64
============================================= ===

============================================= ===
Getting entropy to initialize a BitGenerator
--------------------------------------------- ---
SeedSequence
============================================= ===


Legacy
------

For backwards compatibility with previous versions of numpy before 1.17, the
various aliases to the global `RandomState` methods are left alone and do not
use the new `Generator` API.

==================== =========================================================
Utility functions
-------------------- ---------------------------------------------------------
random Uniformly distributed floats over ``[0, 1)``
integers Uniformly distributed integers, replaces ``randint``
bytes Uniformly distributed random bytes.
permutation Randomly permute a sequence / generate a random sequence.
shuffle Randomly permute a sequence in place.
Expand Down Expand Up @@ -94,20 +120,6 @@
set_state Set state of generator.
==================== =========================================================

============================================= ===
BitGenerator Streams that work with Generator
--------------------------------------------- ---
MT19937
PCG64
Philox
SFC64
============================================= ===

============================================= ===
Getting entropy to initialize a BitGenerator
--------------------------------------------- ---
SeedSequence
============================================= ===

"""
from __future__ import division, absolute_import, print_function
Expand Down Expand Up @@ -167,7 +179,7 @@

from . import mtrand
from .mtrand import *
from .generator import Generator
from .generator import Generator, default_gen
Copy link
Member

@mattip mattip Jun 27, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 9 Generator().function -> default_gen().function

from .bit_generator import SeedSequence
from .mt19937 import MT19937
from .pcg64 import PCG64
Expand All @@ -176,7 +188,7 @@
from .mtrand import RandomState

__all__ += ['Generator', 'RandomState', 'SeedSequence', 'MT19937',
'Philox', 'PCG64', 'SFC64']
'Philox', 'PCG64', 'SFC64', 'default_gen']


def __RandomState_ctor():
Expand Down
1 change: 0 additions & 1 deletion numpy/random/bit_generator.pxd
Expand Up @@ -13,7 +13,6 @@ cdef class BitGenerator():

cdef class SeedSequence():
cdef readonly object entropy
cdef readonly object program_entropy
cdef readonly tuple spawn_key
cdef readonly int pool_size
cdef readonly object pool
Expand Down
23 changes: 13 additions & 10 deletions numpy/random/bit_generator.pyx
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 @@ -473,17 +473,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 @@ -498,7 +501,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 @@ -509,9 +512,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