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?

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
anton skvorts
  • 441
  • 1
  • 4
  • 11

4 Answers4

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!

Alan Stokes
  • 18,815
  • 3
  • 45
  • 64
anton skvorts
  • 441
  • 1
  • 4
  • 11
  • 3
    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. – Jim Lewis Jan 25 '11 at 04:15
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.)

Alan Stokes
  • 18,815
  • 3
  • 45
  • 64
  • Yes it looks like a caching problem. I did as you suggested but I'm still getting the same results... – anton skvorts Jan 24 '11 at 20:03
  • 2
    Normally distributed RNGs use the [Box-Muller transform](http://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform) which generates random numbers in pairs (see: [Numerical Recipes examples](http://dimacs.rutgers.edu/~graham/code.html)) – Mike Jun 20 '12 at 18:54
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 :)

Vokram
  • 2,097
  • 4
  • 19
  • 27
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!)

Jim Lewis
  • 43,505
  • 7
  • 82
  • 96
  • 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. – anton skvorts Jan 24 '11 at 14:00
  • 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 >`, am I missing anything?... – Vokram Aug 17 '12 at 06:49