[SciPy-Dev] Shim for RandomState/Generator

Andrew Nelson andyfaff at gmail.com
Tue Mar 17 21:21:17 EDT 2020


Hi all,
default random number generation is heading towards use of
np.random.Generator, with RandomState being preserved for legacy usage. It
would be nice to start using Generator's, but in order to do that in scipy
we would need to be able to write code that worked with RandomState or
Generator.
Unfortunately there are a few methods that have changed their name,
`randint `--> `integers` and `rand/random_sample` --> `random` spring to
mind

I was wondering if we could add a shim to go in `scipy._lib._util` that
would permit code to be written as if it were using the Generator front end
(at least most of it), but could be using either RandomState or Generator
as a backend.

An example for the shim code would be:

```
from scipy._lib._util import check_random_state
from numpy.random import Generator, RandomState

class RG(object):
    """
    Shim object for working across RandomState and Generator. RandomState
is legacy,
    Generator is the future.
    """
    def __init__(self, seed):
        rng = check_random_state(seed)
#         methods = [f for f in dir(np.random.default_rng()) if not
f.startswith('_')]
#         methods.remove('integers')
#         methods.remove('random')

        methods = ['beta', 'binomial', 'bytes', 'chisquare',
                   'choice', 'dirichlet', 'exponential', 'f', 'gamma',
'geometric',
                   'gumbel', 'hypergeometric', 'laplace', 'logistic',
'lognormal',
                   'logseries', 'multinomial',
                   'multivariate_normal', 'negative_binomial',
'noncentral_chisquare',
                   'noncentral_f', 'normal', 'pareto', 'permutation',
'poisson',
                   'power', 'rayleigh', 'shuffle', 'standard_cauchy',
                   'standard_exponential', 'standard_gamma',
'standard_normal',
                   'standard_t', 'triangular', 'uniform', 'vonmises',
'wald', 'weibull',
                   'zipf']

        for method in methods:
            setattr(self, method, getattr(rng, method))

        if isinstance(rng, RandomState):
            setattr(self, 'integers', rng.randint)
            setattr(self, 'random', rng.random_sample)
        elif isinstance(rng, Generator):
            setattr(self, 'integers', rng.integers)
            setattr(self, 'random', rng.random)
            setattr(self, 'multivariate_hypergeometric',
rng.multivariate_hypergeometric)

        self.rng = rng

    @property
    def state(self):
        if isinstance(self.rng, RandomState):
            return self.rng.get_state()
        elif isinstance(self.rng, Generator):
            return self.rng.bit_generator.state

    @state.setter
    def state(self, state):
        if isinstance(self.rng, RandomState):
            self.rng.set_state(state)
        elif isinstance(self.rng, Generator):
            self.rng.bit_generator.state = state
```

-- 
_____________________________________
Dr. Andrew Nelson


_____________________________________
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/scipy-dev/attachments/20200318/42906a78/attachment.html>


More information about the SciPy-Dev mailing list