I have a function that should simulate a new random exponential variable every time it is called:
#include <boost/random.hpp>
//Simulates a single exponential random variable
double generateExponential(double lambda) {
boost::mt19937 rng; //Mersenne Twister Generator
rng.seed(time(0));
boost::variate_generator< boost::mt19937&, boost::exponential_distribution<> > rndm(rng, boost::exponenti\
al_distribution<>(lambda));
return rndm();
}
for example,
double newExp = generateExponential(10);
However, each time I call the function, it generates the same random number. I want it to generate a different random number each time the function is called. I thought "rng.seed(time(0))" might fix it but it hasn't. How could I get it to do this?
If you can't change the signature of your function, then you could use a static instance of your generator. No need to re-seed.
#include <boost/random.hpp>
typedef boost::mt19937 G;
typedef boost::exponential_distribution D;
double generateExponential(double lambda)
{
static G rng(std::time(0)); // initialized and seeded once
boost::variate_generator<G &, D<> > rndm(rng, D<>(lambda));
return rndm();
}
Generally speaking, a source of random numbers should be a resource whose lifespan is that of your entire program, not that of an individual function call.
Consequently, you need the object representing said source of random numbers to have an appropriate lifespan. Making it a variable local to your function is a Bad Idea. It should be an object passed into your function, or maybe a global object.
(also, frequently reseeding a random number generator is another well known Bad Idea)
Related
I want to generate random numbers outside the main function but even when using the library and seeding the random number generator, the output is not random. Any help is appreciated.
#include <iostream>
#include <random>
#include <time.h>
int foo(std::mt19937 rng)
{
std::uniform_int_distribution<int> distr(0, 9);
return distr(rng);
}
int main()
{
std::random_device rd;
std::mt19937 rng(rd());
for (int j=0; j<10; j++)
{
std::cout << foo(rng) << " ";
}
return 0;
}
With output
5 5 5 5 5 5 5 5 5 5
int foo(std::mt19937 rng)
You are passing the std::mt19937 generator by value, so when you pass your generator to the function, it isn't getting the numbers from the one in main, therefore creating a copy of that generator, which is modified inside that function only, and doesn't affect the one in main.
You should pass it by reference, so it modifies the one in main, and in each call the generator will create different numbers:
int foo(std::mt19937& rng)
Short version: Change foo to take a reference.
int foo(std::mt19937& rng);
When a function parameter is an object type, not a reference, that parameter is a different object from the argument object passed to it. Here since the argument type and parameter type are the same, you're using the copy constructor.
When an entropy source like mt19937 is passed to a distribution like uniform_int_distribution, the operator() of the distribution calls the operator() of the entropy source. The operator() of the entropy source both returns a pseudo-random value and also modifies the entropy source so that its next call will be different.
But back in your main, the original object rng has not been used with a distribution. It has only been copied, and then that copy was used. So next time through the loop, another copy of rng is made. But since this fresh object is essentially identical to the unused rng object, using it once is just going to produce the same results again.
A reference parameter will fix all this, since then the reference is just another name for the original mt19937 object, so then every call to foo is actually using and changing that original object.
int helper( mt19937& generator ){
do stuff;
return 0;
}
#include "helper.h"
// helper function defined in separate source file and included in header
mt19937 generator(time(NULL));
int main( ) {
help(generator);
}
Is it correct to create and seed the mt19937 random number generator, then pass it by reference to a function for use?
I am doing this because I know I am suppose to only seed mt19937 once. But I have a lot of helper functions in separate source files that need to use a random number generator. E.g. with the shuffle function.
Yes it is correct to pass the generator around by reference. The mt19937 has internal state that needs to be modified to get the next random number. If you were to pass the generator by value then you would make a copy of that state and then multiple functions would wind up getting the same random number. This is also why you cannot pass it by const& since it would not be able to modify that internal state if it was const.
I am given to believe that random number generators (RNGs) should only be seeded once to ensure that the distribution of results is as intended.
I am writing a Monte Carlo simulation in C++ which consists of a main function ("A") calling another function ("B") several times, where a large quantity of random numbers is generated in B.
Currently, I am doing the following in B:
void B(){
std::array<int, std::mt19937::state_size> seed_data;
std::random_device r;
std::generate(seed_data.begin(), seed_data.end(), std::ref(r));
std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); //perform warmup
std::mt19937 eng(seq);
std::uniform_real_distribution<> randU(0,1);
double myRandNum = randU(eng);
//do stuff with my random number
}
As you can see, I am creating a new random number generator each time I call the function B. This, as far as I can see, is a waste of time - the RNG can still generate a lot more random numbers!
I have experimented with making "eng" extern but this generates an error using g++:
error: ‘eng’ has both ‘extern’ and initializer extern std::mt19937 eng(seq);
How can I make the random number generator "global" so that I can use it many times?
Be careful with one-size-fits-all rules. 'Globals are evil' is one of them. A RNG should be a global object. (Caveat: each thread should get its own RNG!) I tend to wrap mine in a singleton map, but simply seeding and warming one up at the beginning of main() suffices:
std::mt19937 rng;
int main()
{
// (seed global object 'rng' here)
rng.dispose(10000); // warm it up
For your usage scenario (generating multiple RNs per call), you shouldn't have any problem creating a local distribution for each function call.
One other thing: std::random_device is not your friend -- it can throw at any time for all kinds of stupid reasons. Make sure to wrap it up in a try..catch block. Or, and I recommend this, use a platform specific way to get a true random number. (On Windows, use the Crypto API. On everything else, use /dev/urandom/.)
Hope this helps.
You shouldn't need to pass anything or declare anything, as the interaction between mt19937 and uniform_real_distribution is through globals.
std::array<int, std::mt19937::state_size> seed_data;
std::random_device r;
std::generate(seed_data.begin(), seed_data.end(), std::ref(r));
std::seed_seq seq(std::begin(seed_data), std::end(seed_data)); //perform warmup
std::mt19937 eng(seq);
B()
...
void B()
{
std::uniform_real_distribution<> randU(0,1);
...
There are two random integer generators in boost, boost::uniform_int<> and boost::random::uniform_int_distribution<>, the latter being add only after boost 1.47.
I would like to know if there is any difference in their performance (i.e. the quality of the random numbers they generate)?
Also, with boost::uniform_int<> you need to couple it with a random engine through variate_generate, but seems on boost's official website that you can use
boost::random::mt19937 rng;
boost::random::uniform_int_distribution<> six(1,6);
int x = six(rng);
wihout the variate generate.
Can these two usage be used interchangeably?
boost::uniform_int<> inherits from boost::random::uniform_int_distribution<> and if you look at the header for uniform_int<>, you can see that it basically just calls the base class functions.
Since uniform_int<> just calls uniform_int_distribution<>'s functions, there is no difference in the numbers generated. Boost does explicitly state, however, that uniform_int<> is deprecated, and that uniform_int_distribution<> should be used for all new code.
To answer your second question, neither uniform_int<> nor uniform_int_distribution<> require a boost::random::variate_generator<> to function. The variate_generator<> simply associates a random number generator (like boost::random::mt19937) with a random number distribution (like uniform_int_distribution<>) as a convenience. If you don't use variate_generator<>, then you need to pass a random number generator each time you wish to generate a random number. Here's an example:
#include <boost/random/uniform_int.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/variate_generator.hpp>
#include <iostream>
#include <ctime>
int main()
{
boost::mt19937 rand_generator(std::time(NULL));
boost::random::uniform_int_distribution<> int_distribution(0, 100);
//Need to pass generator
std::cout << int_distribution(rand_generator) << std::endl;
//Associate generator with distribution
boost::random::variate_generator<boost::mt19937&,
boost::random::uniform_int_distribution<>
> int_variate_generator(rand_generator, int_distribution);
//No longer need to pass generator
std::cout << int_variate_generator() << std::endl;
}
Note that the first call is to uniform_int_distribution<> operator() whereas the second call is to variate_generator<> operator(). Associating a generator with a distribution does not change the original generator or distribution objects.
Please let me know if anything is unclear.
I have the following code:
Class B {
void generator()
{
// creating random number generator
boost::mt19937 randgen(static_cast<unsigned int>(std::time(0)));
boost::normal_distribution<float> noise(0,1);
boost::variate_generator<boost::mt19937,
boost::normal_distribution<float> > nD(randgen, noise);
for (int i = 0; i < 100; i++)
{
value = nD();
// graph each value
}
}
};
Class A {
void someFunction()
{
for(int i = 1; i <=3; i++)
{
std::shared_ptr<B> b;
b.reset(new B());
b->generator();
}
}
};
I wish to execute the above code multiple times in rapid succession to produce multiple graphs. I have also reviewed this stackoverflow question which is similar but the caveat states that when time(0) is used and the member function is called in rapid succession then you will still likely get the same sequence of numbers.
How might I overcome this problem?
EDIT: I've tried making randgen static in Class B, also tried making it a global variable in Class A, but each time the 3 graphs are still the same. I've also tried seeding from the GetSystemTime milliseconds. I must be missing something.
One way would be to not reseed the random number generator every time you execute your code.
Create the generator and seed it once, then just continue to use it.
That's assuming you're calling that code multiple times within the same run. If you're doing multiple runs (but still within the same second), you can use another differing property such as the process ID to change the seed.
Alternatively, you can go platform-dependent, using either the Windows GetSystemTime() returning a SYSTEMTIME structure with one of its elements being milliseconds, or the Linux getTimeOfDay returning number of microseconds since the epoch.
Windows:
#include <windows.h>
SYSTEMTIME st;
GetSystemTime (&st);
// Use st.wSecond * 100 + st.wMillisecs to seed (0 thru 59999).
Linux:
#include <sys/time.h>
struct timeval tv;
gettimeofday (&tv, NULL);
// Use tv.tv_sec * 100 + (tv.tv_usec / 1000) to seed (0 thru 59999).
With Boost.Random you can save the state of the random number generator--for example, you can save it to a text file. This is done with streams.
For example, using your code, after you seed the generator and have run it once, you can save the state with an output stream, like so:
std::ofstream generator_state_file("rng.saved");
generator_state_file << randgen;
Then later, when you've created a new generator, you can load the state back from that file using the opposite stream:
std::ifstream generator_state_file("rng.saved");
generator_state_file >> randgen;
And then use the state to generate some more random numbers, and then re-save the state, and so on and so on.
It may also be possible to save the state to a std::string using std::stringstream, if you don't want to use a file, but I haven't personally tried this.
Only create a single random number generator so it's only seeded once:
static boost::mt19937 randgen(static_cast<unsigned int>(std::time(0)));
First Thoughts
On unix you could try reading some bytes from /dev/random or /dev/urandom for the seed. You could also try using a combination of time(0) + pid + static counter (or pseudo-random sequence).
I believe on windows, you can use QueryPerformanceCounter to get the value of the high performance timer register.
Another thought:
You could declare your mt19937 prng as a static or global so you never lose its state.
A third thought:
You wish to "execute the above code multiple times in rapid succession to produce multiple graphs" pass in a graph index. (e.g. genGraph(int graphIndex) and combine this (add, xor, etc) with the output of time(0). boost::mt19937 randgen(static_cast<unsigned int>(std::time(0) + graphIndex));
A late answer: two random-number generator functions for comparing boost with standard method.
boost
#include <boost/random.hpp>
//the code that uses boost is massively non-intuitive, complex and obfuscated
bool _boost_seeded_=false;
/*--------------------*/int
boostrand(int High, int Low)
{
static boost::mt19937 random;
if (!_boost_seeded_)
{
random = boost::mt19937(time(0));
_boost_seeded_=true;
}
boost::uniform_int<> range(Low,High);
boost::variate_generator<boost::mt19937&, boost::uniform_int<> >
getrandom(random, range);
return getrandom();
}
standard
#include <cstdlib>
#include <time.h>
//standard code is straight-forward and quite understandable
bool _stdrand_seeded_=false;
/*--------------------*/int
stdrand(int High, int Low)
{
if (!_stdrand_seeded_)
{
srand(time(0));
_stdrand_seeded_=true;
}
return ((rand() % (High - Low + 1)) + Low);
}
The results from both functions are comparably of the same "randomness". I would apply the KISS-principle.
If you do not want to use only one generator you could create one generator with seed(time(0)) and then use that generator as seed into the other generators.
time(0) has the resolution of 1 second. Using it multiple times as seed within a short time span will create the same generator.