user1443778
user1443778

Reputation: 591

Avoid same random numbers with same generator <random> c++ 11

I have a class with a random engine generator object and functions that return functions representing different distributions but using the same generator.

foo.hpp:

class Foo {
private:
  default_random_engine generator;
  function<float()> sample_pdf1();

foo.cpp:

function<float()> Foo::sample_pdf1()  {
  float mean = 3.0f;
  float stddev = 1.0f;
  normal_distribution<float> dist(mean,stddev);
  return bind(dist,generator);
}

If I do:

Foo myFoo;
cout << myFoo.sample_pdf1()() << endl;
cout << myFoo.sample_pdf1()() << endl;

Both samples will be the same (always), which is not what I want. What is the problem here? Is generator getting copied in bind(dist,generator)?

Also note that this example is simplified, what I want to do is to give sample_pdf1() different paramters that gives rise to different mean and standard deviations (linear gaussian).

Upvotes: 2

Views: 564

Answers (1)

R. Martinho Fernandes
R. Martinho Fernandes

Reputation: 234474

The problem is that the code binds the generator by value. Each sampler returned by the function will have its own copy of the generator. All those copies have the same seed. Generators are deterministic: if you initialise one with the same seed you get the same sequence of numbers.

You could bind the generator by reference: bind(dist, std::ref(generator));. That way the two samplers will use the same generator instead of each one using its own copy.

Alternatively you could seed a different generator for each sampler, as follows.

function<float()> Foo::sample_pdf1()  {
  // a source of entropy to obtain seeds
  static std::random_device entropy;

  float mean = 3.0f;
  float stddev = 1.0f;
  normal_distribution<float> dist(mean,stddev);

  // seed a new generator for this sampler
  auto generator = default_random_engine(entropy());
  return bind(dist,generator);
}

Upvotes: 6

Related Questions