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; };
<chrono>&<random>this wrapper class may be of some help to you: stackoverflow.com/a/48115400/1757805voseconstructor, you aren't actually usingmtoruniformanywhere. Aremtanduniformsupposed to be members ofvose? 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 thevoseclass?