1

I'm writing code for initializing particle positions in a phase space using a density function. I would like to randomly sample their locations according to an arbitrary distribution, and the easiest way to do this that I found was to make a small class with everything needed to sample according to an array of probabilities that I give it. However, I've found that I get the same sequence of numbers every time I run the code.

vose *sampler = new vose(density, init_grid_count); for (unsigned int i=0; i<20; i++) { unsigned int index = sampler->alias_method(); cout << index << '\t'; } 

This is the definition of the function I use

unsigned int vose::alias_method() { double x = uniform(mt); unsigned int i = floor(array_size*x)+1; double y = array_size*x+1-i; if (y<distribution[i]) return i; else return alias[i]; } 

I found that if I do the same loop in the constructor for the class so that it runs when I initialize the vose object, it behaves as expected. This means that it generates a different random sequence each time. So why is it that when I do this in the constructor it works right, but when I use it in a member function it outputs the same sequence every time?

The problem is not that my compiler doesn't support the seed generation. I'm using the <chrono> library and when I print out the seed in the constructor, it is different every time. In case you think there could be something off in the constructor, here it is.

vose::vose(double *array, unsigned int size) { //Initialize auto seed = chrono::high_resolution_clock::now().time_since_epoch().count(); mt19937 mt(seed); // Seeds Mersenne Twister with Device RNG uniform_real_distribution<double> uniform(0, 1); distribution = array; array_size = size; alias = new unsigned int[size]; for (unsigned int i = 0; i<size; i++) { alias[i] = i+1; } } 

Edit: To be perfectly clear, everything works right when I run the method in the constructor. However, that's obviously not where I mean ultimately to run it so I need to figure out how to have a method run in the main section of code.

Edit: In response to the possibility that I hid the generator or something, here is the class declaration in the header file.

class vose { public: vose(double*, unsigned int); void demo(); unsigned int alias_method(); private: std::mt19937 mt; // I struggled with this for a while, you don't give it args // until you use it since it's not a function, it's a strange class std::uniform_real_distribution<double> uniform; double *distribution; unsigned int array_size; unsigned int *alias; }; 
7
  • This is not the same as that question you linked to. I do seed the RNG only once, and that was the mistake on that post. The critical and novel (I think) problem here is that it works in the constructor but not in a method of the class. Commented Jan 18, 2018 at 17:57
  • I have shown this answer to similar questions regarding <chrono> & <random> this wrapper class may be of some help to you: stackoverflow.com/a/48115400/1757805 Commented Jan 18, 2018 at 17:58
  • 1
    That won't work for my purposes because it isn't amenable to using an array to define a distribution. It does seem convenient though and I'll use it in future. Commented Jan 18, 2018 at 18:04
  • Your example doesn't make sense to me; inside the vose constructor, you aren't actually using mt or uniform anywhere. Are mt and uniform supposed to be members of vose? If so, you are hiding those members inside the constructor by declaring local variables with the same names, which means your seed is not being applied. If that's not the issue, can you post the definition of the vose class? Commented Jan 18, 2018 at 19:54
  • You might be onto something. I wasn't sure how to initialize the stuff so I might have done something stupid. Commented Jan 18, 2018 at 20:51

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.