2

I want to change the weights of a discrete distribution every time I sample from the distribution without having to initialize an object every time I draw a new random sample.

The reason for changing weights is that this is part of the particle filter algorithm I am implementing. The reason I don't want to instantiate a new object each time is that I want to set the random seed once externally to the whole program in a controlled manner for repeatable results.

Similar queries are asked here but don't quite answer my specific question:

Boost random::discrete_distribution How to change weights once constructed? - advises to initialize on each draw

Why is boost's random number generation (on a normal distribution) always giving the same values? - doesn't change the parameters

The problem is that currently each time in one higher level program I call the function that contains the random number generation, I get the same sequence of random numbers. The numbers should be different.

Here is simplified sample of what I am trying to do.

typedef boost::mt19937 RNGType;
RNGType rng;
nParticles = 10;

int main()
{      
  std::vector<int> indices(nParticles);
  int nIterations(5);
  for (int i=0; i<nIterations; ++i)
  {
    // Pseudo code. In the final version the weights will change on each loop
    std::vector<double> weights = { 0.1, 0.4, ..., 0.3 }; // Vector length 10
    indices = filter(weights);
    std::cout << indices << std::endl;
  }
  return 0;
}

std::vector filter(std::vector<double> weights)
{
  std::vector<int> indices(nParticles);
  boost::random::discrete_distribution<int,double> weightdist(weights);
  boost::variate_generator< RNGType, 
      boost::random::discrete_distribution<int,double> >
      weightsampler(rng, weightdist);
  for (int i=0; i<nParticles ; ++i)
  {
    indices[i] = weightsampler();
  }
  return indices;
}

This returns, e.g.

1,8,9,2,3,5,1,9,9,9 // Good: each number is "random"
1,8,9,2,3,5,1,9,9,9 // Bad: This is the same as the previous line
1,8,9,2,3,5,1,9,9,9
1,8,9,2,3,5,1,9,9,9
1,8,9,2,3,5,1,9,9,9

Any ideas on how to get different numbers for each filter function output?

Community
  • 1
  • 1

1 Answers1

1

You're already changing the weights every time because you pass in a new set of weights to the filter() function on each call. The reason your example produces the same output for each call is because boost::variate_generator's constructor takes both arguments by value. So you end up making a copy of the RNG on each call, and the changes to the copy's internal state are never seen by the original RNG object.

Change the variate generator's template argument to a reference type

boost::variate_generator<RNGType&, boost::random::discrete_distribution<int,double>>
//                             ^^^
//               doesn't copy RNG anymore

You may also want to change your filter() function signature to

std::vector filter(std::vector<double> const& weights)

This will avoid unnecessary copying of the input argument on each call.

Live demo

Praetorian
  • 106,671
  • 19
  • 240
  • 328