<p dir="ltr">On 8 Sep 2014 14:43, "Robert Kern" <<a href="mailto:robert.kern@gmail.com">robert.kern@gmail.com</a>> wrote:<br>
><br>
> On Mon, Sep 8, 2014 at 6:05 PM, Pierre-Andre Noel<br>
> <<a href="mailto:noel.pierre.andre@gmail.com">noel.pierre.andre@gmail.com</a>> wrote:<br>
> >  > I think we could add new generators to NumPy though,<br>
> >  > perhaps with a keyword to control the algorithm (defaulting to the<br>
> > current<br>
> >  > Mersenne Twister).<br>
> ><br>
> > Why not do something like the C++11 <random>? In <random>, a "generator"<br>
> > is the engine producing randomness, and a "distribution" decides what is<br>
> > the type of outputs that you want. Here is the example on<br>
> > <a href="http://www.cplusplus.com/reference/random/">http://www.cplusplus.com/reference/random/</a> .<br>
> ><br>
> >      std::default_random_engine generator;<br>
> >      std::uniform_int_distribution<int> distribution(1,6);<br>
> >      int dice_roll = distribution(generator);  // generates number in<br>
> > the range 1..6<br>
> ><br>
> > For convenience, you can bind the generator with the distribution (still<br>
> > from the web page above).<br>
> ><br>
> >      auto dice = std::bind(distribution, generator);<br>
> >      int wisdom = dice()+dice()+dice();<br>
> ><br>
> > Here is how I propose to adapt this scheme to numpy. First, there would<br>
> > be a global generator defaulting to the current implementation of<br>
> > Mersene Twister. Calls to numpy's "RandomState", "seed", "get_state" and<br>
> > "set_state" would affect this global generator.<br>
> ><br>
> > All numpy functions associated to random number generation (i.e.,<br>
> > everything listed on<br>
> > <a href="http://docs.scipy.org/doc/numpy/reference/routines.random.html">http://docs.scipy.org/doc/numpy/reference/routines.random.html</a> except<br>
> > for "RandomState", "seed", "get_state" and "set_state") would accept the<br>
> > kwarg "generator", which defaults to the global generator (by default<br>
> > the current Mersene Twister).<br>
> ><br>
> > Now there could be other generator objects: the new Mersene Twister,<br>
> > some lightweight-but-worse generator, or some cryptographically-safe<br>
> > random generator. Each such generator would have "RandomState", "seed",<br>
> > "get_state" and "set_state" methods (except perhaps the<br>
> > criptographically-safe ones). When calling a numpy function with<br>
> > generator=my_generator, that function uses this generator instead the<br>
> > global one. Moreover, there would be be a function, say<br>
> > select_default_random_engine(generator), which changes the global<br>
> > generator to a user-specified one.<br>
><br>
> I think the Python standard library's example is more instructive. We<br>
> have new classes for each new core uniform generator. They will share<br>
> a common superclass to share the implementation of the non-uniform<br>
> distributions. numpy.random.RandomState will continue to be the<br>
> current Mersenne Twister implementation, and so will the underlying<br>
> global RandomState for all of the convenience functions in<br>
> numpy.random. If you want the SFMT variant, you instantiate<br>
> numpy.random.SFMT() and call its methods directly.</p>
<p dir="ltr">There's also another reason why generator decisions should be part of the RandomState object itself: we may want to change the distribution methods themselves over time (e.g., people have been complaining for a while that we use a suboptimal method for generating gaussian deviates), but changing these creates similar backcompat problems. So we need a way to say "please give me samples using the old gaussian implementation" or whatever.</p>
<p dir="ltr">-n</p>