Skip to content

ENH: hot-swapping a BitGenerator #21808

@rkern

Description

@rkern

Proposed new feature or change:

One of the requirements in NEP 19 was

In order to allow certain workarounds, it MUST be possible to replace the BitGenerator underneath the global RandomState with any other BitGenerator object (we leave the precise API details up to the new subsystem).

We partially overlooked this in the hectic flood of new features that we implemented. IIRC, I did successfully insist on making the _bit_generator attribute cdef public rather than cdef readonly, but failed to communicate the full intended use, so it's not really functional.

As people are transitioning away from the np.random.* global functions, they may need a transition where they are using code, especially third-party code that they can't change, that still uses the np.random.* functions. We want to give them the ability to use a single BitGenerator instance shared between their Generator-using newer code and the np.random.*-using older code. That way, they don't have to manage two different seeds to get reproducible results.

Currently, we can create a new RandomState with one of the newer BitGenerators, but we can't change the BitGenerator underneath the pre-created global instance np.random.mtrand._rand. So I would like to be able to write code that looks like this:

def synch_legacy_randomstate(rng):
    np.random.mtrand._rand._bit_generator = rng.bit_generator

rng = np.random.default_rng(one_single_seed)
synch_legacy_randomstate(rng)

# newer code
rng.uniform(100)
# older code
np.random.uniform(100)

The _bit_generator attribute is cdef public, so we can technically assign a new BitGenerator to it, but this is essentially a no-op because the bitgen_t * is extracted from the BitGenerator object only in the __init__(). After re-assigning _bit_generator, all of the distribution methods still draw from the old bitgen_t *.

We can probably implement this by lifting the cdef public _bit_generator attribute to a property and factoring out the bitgen_t * extraction so that it can be used in both the __init__() and the setter.

@bashtage Any thoughts?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions