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 _____________________________________
On Tue, Mar 17, 2020 at 9:22 PM Andrew Nelson <andyfaff@gmail.com> wrote:
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
FWIW, `random` exists in RandomState, too, so it's just a matter of using the existing common name for that one. `randint` --> `integers` is the only sticky one that I can recall.
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.
Instead of a wrapper object, which is inevitably going to be passed around and thus introducing a third API for code to be aware of, I would recommend having a set of functions for the few methods that have changed names. I.e. def rng_integers(gen, low, high=None, ...): if isinstance(gen, Generator): return gen.integers(low, high=high, ...) else: return gen.randint(low, high=high, ...) Yes, this also constitutes a third API, but it's one that can't "escape". It only affects functions that call these functions because it doesn't introduce a new object with its own lifetime to consider. It's also limited to a couple of functions. -- Robert Kern
participants (2)
-
Andrew Nelson -
Robert Kern