10

I would like to reset random sequences by using different seed numbers. When running this test code:

boost::mt19937 gener(1); boost::normal_distribution<> normal(0,1); boost::variate_generator<boost::mt19937&,boost::normal_distribution<> > rng(gener, normal); cout << rng() << endl; cout << rng() << endl; cout << rng() << endl; gener.seed(2); cout << rng() << endl; cout << rng() << endl; gener.seed(1); cout << rng() << endl; gener.seed(2); cout << rng() << endl; gener.seed(3); cout << rng() << endl; 

I get the following output:

# seed(1) via constructor -2.971829031 1.706951063 -0.430498971 # seed(2) -2.282022417 -0.5887503675 # seed(1) 0.2504171986 # seed(2) -0.5887503675 # seed(3) 0.2504171986 

Obviously I'm doing something very wrong. How may I overcome this problem?

4 Answers 4

15

Following Jim, Alan and Igor suggestions made some changes to the code: rng.engine().seed() instead of gener.seed(), and called rng.distribution().reset() after the call to rng.engine().seed() and it worked like a charm.

Many thanks!

Sign up to request clarification or add additional context in comments.

1 Comment

Glad it worked out! By the way, you're allowed (and encouraged) to accept your own answer, especially if it took a combination of several people's ideas to solve your problem.
5

You should call normal.reset() after the call to gener.seed(). That is specified to ensure that the output of normal will not depend on any previous output from gener.

(The distribution is probably caching some state that you need to clear out.)

2 Comments

Yes it looks like a caching problem. I did as you suggested but I'm still getting the same results...
Normally distributed RNGs use the Box-Muller transform which generates random numbers in pairs (see: Numerical Recipes examples)
2

Great to see the problem resolved! But I guess I just figured out why Alan's method wouldn't work...

When writing boost::variate_generator<boost::mt19937&,boost::normal_distribution<> > rng(gener, normal), you didn't create another copy of gener because it's a call by reference, but you did create another copy of normal with the variate_generate.

So instead of normal.reset, which only resets the original normal, you should use rng.distribution().reset(). But you can just keep gener.seed(), which I suspect will have the same effect as rng.engine().seed().

I tested it in my code, and it worked as expected.

Well, just in case anybody would care :)

Comments

1

I believe boost::variate_generator<> makes a copy of your boost::mt19937 gener object. So when you reseed your copy of gener, it has no effect on the rng object that's already been constructed. Constructing a new rng object each time you reseed should give you the behavior you want (disclaimer: not tested!)

2 Comments

I believe that reseeding is having some effect on rng, because I'm getting repeated values -0.5887503675 and 0.2504171986. But then unfortunately not at all what I would expect.
Great to see the problem resolved, but may I ask why boost::variate_generator<> makes a copy of gener in this case? I think the OP passed reference when writing boost::variate_generator<boost::mt19937&,boost::normal_distribution<> >, am I missing anything?...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.