From: Kevin on
This is getting a bit too confusing. Anyway it is difficult to justify to myself spending the whole weekend learning about how to generate random numbers in Matlab. After this is Matlab and there is good reason why Matlab is so popular today (because it is very simple to use and learn).

Before knowing about these new fancy ways in the new Matlab, I would think that it is trivial to do that in Matlab. But things are not that simple anymore.

In conclusion, just change the code to use the new RandStream and forget about how to make things to be backward compatible.
From: Peter Perkins on
On 3/15/2010 1:15 PM, Kevin wrote:
> This is getting a bit too confusing.

Kevin, I'm not sure what you're reacting to, but I'd like to find out so that we can hopefully make things easier to understand in the future. In a couple threads, you've asked about several different things, some of them new since R2008b, some of them having to do with backwards compatibility. Many of new things introduced in R2008b were to support parallel random number generation, and those require learning some new ideas, as well as syntax. But for the things that 95% of MATLAB users want to do with random number generation, the syntaxes are pretty straightforward:

=== Generate random values ===
This is tha same as it has always been:

>> rand(2)
ans =
0.79814 0.78109
0.79564 0.3511
>> randn(2)
ans =
-1.3385 1.4472
0.65223 -1.2901


== Save and restore state to reproduce results ===
You now read and write directly to a state property. You can do this without needing to know what generator is active (even the legacy generators).

>> dfltStream = RandStream.getDefaultStream;
>> savedState = dfltStream.State;
>> rand(2)
ans =
0.11357 0.48166
0.91288 0.85181
>> dfltStream.State = savedState;
>> rand(2)
ans =
0.11357 0.48166
0.91288 0.85181


=== Reinitialize the generators ===
You now call a method that has a name describing exactly what it does: "reset". You can do this without needing to know what generator is active (with the caveat I mentioned earlier in the thread).

>> reset(RandStream.getDefaultStream) % just as if restarting MATLAB
>> reset(RandStream.getDefaultStream,1) % different than above
>> reset(RandStream.getDefaultStream,sum(100*clock)) % unpredictable reinitialization


There are some things in the new RandStream syntax you can't do with the legacy stream (including calling reset with a new seed), but any code that activates those ought to be considered deprecated. Is the problem you're having in writing code thatwill work with the legacy generators?
From: Kevin on
Hi Peter,

Just want to say that I really appreciate your reply. I thought that by now I probably won't get any response. I also appreciate your effort of making Matlab a good tool for us to use. So let me summarize what I think about the new RandStream class.


(1) This point is about creating new terms or new concepts. I understand that in order to provide new features, we sometimes need to create new concept. But Mathworks needs to understand that this imposes a learning curve to users. What makes Matlab so good and popular is that it is very easy to learn and understand (and so the learning curve is pretty minimal). There are not that many people (except the people working at Mathworks) producing Matlab code as a product. I would guess that most people are using Matlab code to design algorithm and to see what is possible (under 64-bit double precision math and lots of memory). This makes learning Matlab as a side job (for me, I have whole bunch of other things to learn to create the final product). I understand that you might say that "even though matlab provides new features, that does not mean that I need to learn and use every single new
feature. I can use whatever I need to get my job done". This is half true. I agree that I don't need to use every single new feature, other people in my team might use the new feature and this forces me to learn and fully understand what the new feature does. Let me give you an example. RandStream is a handle class and so I need to understand what is a handle class and its implication, eg. assignment statement like "h2 = h1" does not make a copy of the RandStream object. Steve already mentioned the rationale behind this and that is a design and usage decision made by Mathworks (and I am fine with it). But now, in order to understand how to generate random numbers in Matlab, I also need to understand Matlab's new OOP concept. Luckily I learned the new OOP before and so I am not starting from scratch.


(2) This point is about the documentation (I am using R2009b) on whether rand and randn are using the same random number stream or not. Now after thinking about it more and reading your reply, the answer is yes (if we are using the new RandStream object. this is true for both default stream and user-created stream) but the answer is no (if we are using legacy random stream).


(3) This is about your last posting on "Save and restore state to reproduce results". Even if I save the state, I still cannot guarantee that I will get the same random numbers. For example, after I save the state, someone's code changes the default stream to use different algorithm, eg.

>> dfltStream = RandStream.getDefaultStream;
>> savedState = dfltStream.State;
>> h = RandStream('mt19937ar', 'Seed', 101);
>> RandStream.setDefaultStream(h)

Things are not that simple anymore since Matlab allows user to set the default stream to something else. This is a gotcha. Correct me if I am wrong on this.


(4) I have posted this question in a new thread but I did not get any reply. So I will post it here. I got the impression from the documentation ("Legacy Mode") that I can use RandStream to generate the same random numbers as generated by the legacy code. But I did the following experiment and found out that I am wrong.

>> h = RandStream('mt19937ar', 'Seed', 0); rand(h, 1, 3)

ans =

0.8147 0.9058 0.1270

>> rand('twister', 0); rand(1,3)

ans =

0.5488 0.7152 0.6028

So am I having the wrong concept thinking that I can use RandStream to generate the same random numbers as generated by the legacy code.


(5) This is about the concept of Substream in those generator that supports multiple streams and substream. I admit that I know very little about random number generator algorithm. I would hope that the documentation would tell me the interaction between setting Substream and setting State in those generators. For example, if I want to generate the same random numbers in those generators (i.e. mlfg6331_64 and mrg32k3a), do I need to save-and-set both substream index and state or just either one of them?


(6) I like the fact that Mathworks is thinking ahead of me in providing parallel random number generators. I don't need to use this now. But it would be nice to know that it is there waiting for me to use. All I need to do is to pay the software maintenance fee to get the upgrade. Keep up the good work.


I guess I will stop for now. It is pretty late. Peter, since you are 3 hours ahead of me (I am assuming that you live in Boston area), I look forward to read your thoughts on my question tomorrow morning.

Good night.
From: Peter Perkins on
On 3/16/2010 2:40 AM, Kevin wrote:

> (4) I have posted this question in a new thread but I did not get any
> reply. So I will post it here. I got the impression from the
> documentation ("Legacy Mode") that I can use RandStream to generate the
> same random numbers as generated by the legacy code. But I did the
> following experiment and found out that I am wrong.
>
>>> h = RandStream('mt19937ar', 'Seed', 0); rand(h, 1, 3)
>
> ans =
>
> 0.8147 0.9058 0.1270
>
>>> rand('twister', 0); rand(1,3)
>
> ans =
>
> 0.5488 0.7152 0.6028
>
> So am I having the wrong concept thinking that I can use RandStream to
> generate the same random numbers as generated by the legacy code.

You've discovered the one inconsistency that I know of between old and new (other than rand and randn working separately). This is a bit arcane, and much/all of what follows is not something that anyone would really need to worry about, unless they happened to type exactly what you typed and said, huh?"

You will note that none of the old help recommended using 0 as in rand('twister',0), it used 5489, which is the default seed used by the designers of the Mersenne Twister algorithm. It was not clear if 0 is a "good" seed for the Mersenne Twister (it is "valid", but that's not the same thing), so in RandStream, we chose to make 0 map to the one that the designers chose as their default, because people like to type 0 and we want that to be "good". Presumably you used zero because that is the "default" seed for the even older generators activated by 'seed' and 'state' (in fact, those zeros also really map to something other than zero, for the same reason). Is this a real concern, i.e., that you can't reproduce those same numbers for that one seed, or just something you noticed?

Pick any other seed, or any other of the old generators, and results are identical.

>> rand('twister', 5489); rand(1,3)
ans =
0.81472 0.90579 0.12699
>> h = RandStream('mt19937ar', 'Seed', 5489); rand(h, 1, 3)
ans =
0.81472 0.90579 0.12699

>> rand('state', 0); rand(1,3)
ans =
0.95013 0.23114 0.60684
>> h = RandStream('swb2712', 'Seed', 0); rand(h, 1, 3)
ans =
0.95013 0.23114 0.60684
From: Peter Perkins on
On 3/16/2010 2:40 AM, Kevin wrote:

> (5) This is about the concept of Substream in those generator that
> supports multiple streams and substream. I admit that I know very little
> about random number generator algorithm. I would hope that the
> documentation would tell me the interaction between setting Substream
> and setting State in those generators. For example, if I want to
> generate the same random numbers in those generators (i.e. mlfg6331_64
> and mrg32k3a), do I need to save-and-set both substream index and state
> or just either one of them?

This one I know I answered on another thread. In short, either, not both. Setting the substream index alters the state. Each substream index is in effect an alias for a specific internal state. You might then say, "Isn't that what seeds are for?", and I direct you to the blog entries I cited in my full response.