From: Kevin on
Just started to learn about RandStream (the new way to generate uniform or normal random numbers).

RandStream is a handle class and I get a bit confused about that. I am a bit behind on learning the new Matlab OOP. I am pretty comfortable with value class but not with handle class.

For example,

function foo
h = RandStream('mt19937ar');
end


Everytime I call this function, does Matlab create an instance of RandStream (i.e. allocate memory) and then delete the instance (i.e. free memory)? So after the function returns, I won't have access to the object created inside foo( ). Right?

Why do we want to implement a random number generator as a handle class? I think in this case, a value class will serve the purpose.
From: Steven Lord on

"Kevin " <kevin(a)northpole.com> wrote in message
news:hn960u$2jm$1(a)fred.mathworks.com...
> Just started to learn about RandStream (the new way to generate uniform or
> normal random numbers).
>
> RandStream is a handle class and I get a bit confused about that. I am a
> bit behind on learning the new Matlab OOP. I am pretty comfortable with
> value class but not with handle class.
> For example,
>
> function foo
> h = RandStream('mt19937ar');
> end
>
>
> Everytime I call this function, does Matlab create an instance of
> RandStream (i.e. allocate memory) and then delete the instance (i.e. free
> memory)? So after the function returns, I won't have access to the object
> created inside foo( ). Right?

That is correct. But if you returned the handle h from the foo function,
you could use the generator from outside the function.

> Why do we want to implement a random number generator as a handle class? I
> think in this case, a value class will serve the purpose.

h1 = RandStream('mt19937ar');
h2 = h1;
x1 = rand(h1, 1, 10);
x2 = rand(h2, 1, 10);

Should x1 and x2 be the same? If the RandStream class were a value class,
they would be because h2 would be _a copy_ of h1 from before it was used to
generate random numbers, and so its state would be a copy of the state of
h1.

Because RandStream is a handle class, h1 and h2 refer to _the same random
stream_. Thus after using the stream (via h1) to generate 10 numbers, its
state has changed and so using that same stream (via h2) to generate 10
numbers generates different values in x1 and x2.

I believe the latter behavior is what users would expect from a random
number generator. If you wanted to restore the state of the generator to
the state it was in prior to the first of those RAND calls, use the RESET
method.

reset(h1);
x3 = rand(h2, 1, 10); % should be the same as x1
x4 = rand(h1, 1, 10); % should be the same as x2

And yes, I did swap the order in which I used the variables in the
construction of x3 and x4. Since they refer to the same stream, that's
okay.

Note that if you don't want to worry about the RandStream class, you can
just call RAND or RANDN like you used to -- they will draw numbers from a
"default" random stream.

--
Steve Lord
slord(a)mathworks.com
comp.soft-sys.matlab (CSSM) FAQ: http://matlabwiki.mathworks.com/MATLAB_FAQ


From: Peter Perkins on
On 3/10/2010 5:21 PM, Kevin wrote:
> function foo
> h = RandStream('mt19937ar');
> end
>
> Everytime I call this function, does Matlab create an instance of
> RandStream (i.e. allocate memory) and then delete the instance (i.e.
> free memory)? So after the function returns, I won't have access to the
> object created inside foo( ). Right?

The same thing can be said about this function

function foo
x = 0;
end

x is a value, not a handle, and after the function returns, you won't have access to it. I realize that that doesn't answer your question, but it's hard for me to say what you need to do, because I don't know what you're trying to do. Let me take a shot, and bear with me.

First, there's no rule that says to generate random values, you have to create a random stream. You can simply call rand, and randn, and randi, as you always have. Even if you want to control how random values are generated, you need not necessarily create a stream. Many times you can just get the (global) default stream, as

dfltStream = RandStream.getDefaultStream;

and then read or write its properties (e.g., dfltStream.State) or reset it. The three most common reasons for doing the latter are

a) You want to put the default stream back to its beginning, as if you'd restarted MATLAB. This is most easily done as

reset(RandStream.getDefaultStream);

b) You want to be able to put it in some predictable state so that when you run a simulation repeatedly in the same MATLAB session, you get the same result over and over. This is most easily done as

reset(RandStream.getDefaultStream,1);

b) You want to put it in some unpredictable state when you start up a new MATLAB session so that when you run a simulation, you get a different result each in each session. This is most easily done as

reset(RandStream.getDefaultStream,sum(100*clock));


But there are two reasons why you might _want_ to create a random stream instead of just getting the default stream:

1) You want to create a stream s and execute a statement such as

x = rand(s,10,1) % note the first input

that generates random values, but does not affect what other parts of your code would get when they call rand in the ordinary way, e.g.

y = rand(5,1) % note _no_ stream input

In other words, that first example draws numbers from the stream s, while the second draws from the default stream. Ordinarily, you probably would not care what specific random values you get when you call rand, because after all, they're supposed to be "random". But it's sometimes easier to debug or reproduce results if you can isolate the different sources of randomness. Thus, "private" streams. Create as many as you want, but understand why you want them. Often, you don't.

2) You might want to make sure the default stream uses a particular generator algorithm. Notice that the three reset examples above make the assumption that you're happy with the generator algorithm that the current default stream uses, or that you don't care. And not caring is perfectly valid -- if all you want is to repeat the same "random" calculations while you're debugging something, and then never care about repeating that again, then it's just a matter of getting the same values repeatedly over the short term.

On the other hand, you might be building an algorithm that uses random numbers, and you want to benchmark the algorithm by running it using a fixed set of random values, and checking for a specific result. You want that benchmark test to work forever, no matter what MATLAB session or version run it's run in, no matter what code has been executed previously in that session. In other words, you need repeatability over the long term. To get that, you'll not only want to reset the default stream, but make sure it's using a specific generator algorithm.

It's important to realize that "the" default stream is really "the stream that is current designated as" the default stream in same way that you computer has a printer designated as the default. You, or code that you call, can designate another stream as the global default. if code that you call does that, it's probably bad etiquette, but, for example, the line

rand('state',0)

does just that.

The different generator algorithms spit out different sequences of values, so even if you reset the default stream, you might get different values than you expect if the default stream is not what you think it is. So if you want to be absolutely guaranteed that the first "random" number you get from RAND is

>> rand
ans =
0.81472

then you need to be sure that the default stream is one that uses the Mersenne Twister, and was seeded with zero. To do that, you can create such a stream and designate it as the default stream:

mtStream = RandStream('mt19937ar','Seed',0);
RandStream.setDefaultStream(mtStream);

But it's important to remember that this is often not at all necessary.


> Why do we want to implement a random number generator as a handle class?
> I think in this case, a value class will serve the purpose.

The short answer is that you want to be able to pass around a single stream and have every function that gets it be drawing numbers from that same stream. If RandStream was value-based, everyone would be working with copies. In particular, MATLAB creates a default random stream at startup, and you need to be able to modify the properties of that same stream, not of a copy of it.

Hope this all helps.

- Peter Perkins
The MathWorks, Inc.
From: Kevin on
Firstly, I would like to say that I really appreciate the replies from Steve and Peter. This is a very good explanation of RandStream.

I guess it is safe to assume that Matlab would keep the legacy mode, i.e. the old way of using rand(...) and randn(...). I had some bad experience with the Link to Code Composer Toolbox. The toolbox has made a lot of incompatible changes to its functions going from one version to the next version (this happened couple years ago). I hope that this would not happen to Matlab.

Now I understand the reason why RandStream is a handle class. I just need to remember that the statement "h2 = h1" does not create a new object but both h1 and h2 "point" to the same object. Also if I create h1 in the Matlab workspace and pass h1 to a function, although the function does not return h1 as an output argument, h1 in the Matlab workspace has different property values after the function returns. This is another thing about handle class.

I was reading R2009b documentation (User Guide -> Mathematics -> Random Numbers) and this statement (under "Managing the Default Stream"):

rand, randn, and randi draw random numbers from an underlying random number
stream, called the default stream.

I think this statement is half true. Under "Legacy Mode", there is this statement:

Prior to MATLAB Version 7.7, the rand and randn functions used a different syntax
for controlling the random number generators. In addition, rand and randn had
separate underlying random number streams.

So I think it is true that rand and randn had separate underlying random number streams. I verify this by the following example code:

>> clear all
>> defaultStream=RandStream.getDefaultStream

defaultStream =

legacy random stream (current default)
RAND algorithm: V7.4 (Mersenne Twister)
RANDN algorithm: V5 (Ziggurat)
>> myState=defaultStream.State;
>> A=rand(1,100);
>> defaultStream.State=myState;
>> randn(100);
>> B=rand(1,100);
>> isequal(A,B)

ans =

1


Peter Perkins <Peter.Perkins(a)MathRemoveThisWorks.com> wrote in message <hnb49n$755$1(a)fred.mathworks.com>...
> On 3/10/2010 5:21 PM, Kevin wrote:
> > function foo
> > h = RandStream('mt19937ar');
> > end
> >
> > Everytime I call this function, does Matlab create an instance of
> > RandStream (i.e. allocate memory) and then delete the instance (i.e.
> > free memory)? So after the function returns, I won't have access to the
> > object created inside foo( ). Right?
>
> The same thing can be said about this function
>
> function foo
> x = 0;
> end
>
> x is a value, not a handle, and after the function returns, you won't have access to it. I realize that that doesn't answer your question, but it's hard for me to say what you need to do, because I don't know what you're trying to do. Let me take a shot, and bear with me.
>
> First, there's no rule that says to generate random values, you have to create a random stream. You can simply call rand, and randn, and randi, as you always have. Even if you want to control how random values are generated, you need not necessarily create a stream. Many times you can just get the (global) default stream, as
>
> dfltStream = RandStream.getDefaultStream;
>
> and then read or write its properties (e.g., dfltStream.State) or reset it. The three most common reasons for doing the latter are
>
> a) You want to put the default stream back to its beginning, as if you'd restarted MATLAB. This is most easily done as
>
> reset(RandStream.getDefaultStream);
>
> b) You want to be able to put it in some predictable state so that when you run a simulation repeatedly in the same MATLAB session, you get the same result over and over. This is most easily done as
>
> reset(RandStream.getDefaultStream,1);
>
> b) You want to put it in some unpredictable state when you start up a new MATLAB session so that when you run a simulation, you get a different result each in each session. This is most easily done as
>
> reset(RandStream.getDefaultStream,sum(100*clock));
>
>
> But there are two reasons why you might _want_ to create a random stream instead of just getting the default stream:
>
> 1) You want to create a stream s and execute a statement such as
>
> x = rand(s,10,1) % note the first input
>
> that generates random values, but does not affect what other parts of your code would get when they call rand in the ordinary way, e.g.
>
> y = rand(5,1) % note _no_ stream input
>
> In other words, that first example draws numbers from the stream s, while the second draws from the default stream. Ordinarily, you probably would not care what specific random values you get when you call rand, because after all, they're supposed to be "random". But it's sometimes easier to debug or reproduce results if you can isolate the different sources of randomness. Thus, "private" streams. Create as many as you want, but understand why you want them. Often, you don't.
>
> 2) You might want to make sure the default stream uses a particular generator algorithm. Notice that the three reset examples above make the assumption that you're happy with the generator algorithm that the current default stream uses, or that you don't care. And not caring is perfectly valid -- if all you want is to repeat the same "random" calculations while you're debugging something, and then never care about repeating that again, then it's just a matter of getting the same values repeatedly over the short term.
>
> On the other hand, you might be building an algorithm that uses random numbers, and you want to benchmark the algorithm by running it using a fixed set of random values, and checking for a specific result. You want that benchmark test to work forever, no matter what MATLAB session or version run it's run in, no matter what code has been executed previously in that session. In other words, you need repeatability over the long term. To get that, you'll not only want to reset the default stream, but make sure it's using a specific generator algorithm.
>
> It's important to realize that "the" default stream is really "the stream that is current designated as" the default stream in same way that you computer has a printer designated as the default. You, or code that you call, can designate another stream as the global default. if code that you call does that, it's probably bad etiquette, but, for example, the line
>
> rand('state',0)
>
> does just that.
>
> The different generator algorithms spit out different sequences of values, so even if you reset the default stream, you might get different values than you expect if the default stream is not what you think it is. So if you want to be absolutely guaranteed that the first "random" number you get from RAND is
>
> >> rand
> ans =
> 0.81472
>
> then you need to be sure that the default stream is one that uses the Mersenne Twister, and was seeded with zero. To do that, you can create such a stream and designate it as the default stream:
>
> mtStream = RandStream('mt19937ar','Seed',0);
> RandStream.setDefaultStream(mtStream);
>
> But it's important to remember that this is often not at all necessary.
>
>
> > Why do we want to implement a random number generator as a handle class?
> > I think in this case, a value class will serve the purpose.
>
> The short answer is that you want to be able to pass around a single stream and have every function that gets it be drawing numbers from that same stream. If RandStream was value-based, everyone would be working with copies. In particular, MATLAB creates a default random stream at startup, and you need to be able to modify the properties of that same stream, not of a copy of it.
>
> Hope this all helps.
>
> - Peter Perkins
> The MathWorks, Inc.
From: Peter Perkins on
On 3/13/2010 2:42 AM, Kevin wrote:

> I was reading R2009b documentation (User Guide -> Mathematics -> Random
> Numbers) and this statement (under "Managing the Default Stream"):
>
> rand, randn, and randi draw random numbers from an underlying random
> number stream, called the default stream.
> I think this statement is half true. Under "Legacy Mode", there is this
> statement:
>
> Prior to MATLAB Version 7.7, the rand and randn functions used a
> different syntax for controlling the random number generators. In
> addition, rand and randn had separate underlying random number streams.
>
> So I think it is true that rand and randn had separate underlying random
> number streams. I verify this by the following example code:

Correct, at least in one sense. If the legacy generators are active (if you typed rand('state',0), for example), then rand and randn do not affect each other's numbers. The old syntax (whic as I said is all still supported) had you go to rand and randn separately to control those two streams. In that sense, it's two streams. This one special case is for backwards compatibility.

On the other hand, for the purposes of resetting and saving/restoring state, even with the legacy generators, the new RandStream syntax lets you go to one place and work with one stream object, so in that sense it's one stream.

But you have to go out of your way to make the legacy generators active -- since R2008b, a fresh MATLAB session will get you

>> RandStream.getDefaultStream
ans =
mt19937ar random stream (current default)
Seed: 0
RandnAlg: Ziggurat

and rand, randn, and randi all draw from the same stream.