On C++, I am using random_device to seed my 64-bit mersenne twister as follows:
random_device rand_dev;
mt19937_64 mersenne_generator(rand_dev());
And then calling the distribution function inside the loop:
double rand_no = uniform_real_distribution<double>(0.0,1.0)(mersenne_generator);
In other words, the standard way of using mt19937_64, as far as I'm aware. I am using this for a Monte Carlo simulation, and so far it has worked quite well.
However, I for future simulations I would like the simulation results to be fully reproducible based on a stored seed. Such that running:
mt19937_64 mersenne_generator(stored_rand_dev);
For the same parameter set and a given stored_rand_dev will result in the same outputs.
My first thought was to store the results of the random_device as some kind of integer or string. However, naive typecasting random_device to a integer does not work, nor does using to_string. I was wondering if there was an alternative method of storing random_device? Preferably in a form that can occupy a single cell in a tsv file.
Alternatively, I thought of using random device to choose an unsigned integer from 0 to INT_MAX and using this as a seed for mt19937. However, I was unsure if this would affect the quality of random numbers generated by mt19937 versus using random_device. Could anyone advise on this as well?
Related
I have a bash script that starts many client processes. These are AI game players that I'm using to test a game with many players, on the order of 400 connections.
The problem I'm having is that the AI player uses
srand( time(nullptr) );
But if all the players start at approximately the same time, they will frequently receive the same time() value, which will mean that they are all on the same rand() sequence.
Part of the testing process is to ensure that if lots of clients try to connect at approximately the same time, the server can handle it.
I had considered using something like
srand( (int) this );
Or similar, banking on the idea that each instance has a unique memory address.
Is there another better way?
Use a random seed to a pseudorandom generator.
std::random_device is expensive random data. (expensive as in slow)
You use that to seed a prng algorithm. mt19937 is the last prng algorithm you will ever need.
You can optionally follow that up by feeding it through a distribution if your needs require it. i.e. if you need values in a certain range other than what the generator provides.
std::random_device rd;
std::mt19937 generator(rd());
These days rand() and srand() are obsolete.
The generally accepted method is to seed a pseudo random number generator from the std::random_device. On platforms that provide non-deterministic random sources the std::random_device is required to use them to provide high quality random numbers.
However it can be slow or even block while gathering enough entropy. For this reason it is generally only used to provide the seed.
A high quality but efficient random engine is the mersenne twister provided by the standard library:
inline
std::mt19937& random_generator()
{
thread_local static std::mt19937 mt{std::random_device{}()};
return mt;
}
template<typename Number>
Number random_number(Number from, Number to)
{
static_assert(std::is_integral<Number>::value||std::is_floating_point<Number>::value,
"Parameters must be integer or floating point numbers");
using Distribution = typename std::conditional
<
std::is_integral<Number>::value,
std::uniform_int_distribution<Number>,
std::uniform_real_distribution<Number>
>::type;
thread_local static Distribution dist;
return dist(random_generator(), typename Distribution::param_type{from, to});
}
You use a random number seed if and only if you want reproducible results. This can be handy for things like map generation where you want the map to be randomized, but you want it to be predictably random based on the seed.
For most cases you don't want that, you want actually random numbers, and the best way to do that is through the Standard Library generator functions:
#include <random>
std::random_device rd;
std::map<int, int> hist;
std::uniform_int_distribution<int> dist(0, 5);
int random_die_roll = dist(rd);
No seed is required nor recommended in this case. The "random device" goes about seeding the PRNG (pseudo random number generator) properly to ensure unpredictable results.
Again, DO NOT use srand(time(NULL)) because it's a very old, very bad method for initializing random numbers and it's highly predictable. Spinning through a million possible seeds to find matching output is trivial on modern computers.
I'm trying so seed the random function with errno :
#include <stddef.h>
#include <string.h>
int main(void){
srand(&errno);
srand(strerror(0));
return rand();
}
This question already has answers here:
Why do I get the same sequence for every run with std::random_device with mingw gcc4.8.1?
(5 answers)
Closed 5 years ago.
//My trial program
#include<iostream>
#include<random>
using namespace std;
int main(){
//USed to initialize (seed) the random number generator
random_device sd{};
// The random number generator
mt19937 engine {sd()};
//Uniformly distribute random numbers in [1...10]
uniform_int_distribution <> dis{1, 50};
//Generate a random integer
int x {dis(engine)};
//Print it
cout<<x<<"\n";
return 0;
}
I have used the code above to a generate random number between 1 to 50. But whenever I run the program, the random number generated is the same. An online course that I am taking has this code and it works perfectly fine on the instructor's clang compiler. I am using gcc compiler. Can anyone tell me what needs to be done please? thank you!!
From std::random_device :
std::random_device may be implemented in terms of an implementation-defined pseudo-random number engine if a non-deterministic source (e.g. a hardware device) is not available to the implementation. In this case each std::random_device object may generate the same number sequence.
Although it's not ideal for it's users, an implementation is allowed to have the behavior you described.
The issue here is that std::random_device does not have to really be a random device. It can be a wrapper around an unseeded rand which would give you the same value every time you use it. This means your seed for engine would be the same which means the pseudo-random sequence it generates would be the same as well.
One way you could get around this is to use the current as a seed like
auto seed = std::chrono::system_clock::now().time_since_epoch().count();
mt19937 engine {seed};
But this can be manipulated via external processes and isn't very fined grained so multiple instances seeded at the same time could all make the same sequence.
I have been learning recently how to program games in c++ from a beginner book, and i reached a lesson where i have to make a game in where i have to guess the computer's random picked number, and i have to use this line of code:
srand(static_cast<unsigned int>(time(0)));
variable=rand();
I obviously use iostream cstdlib and ctime.I don't really understand how this works.How is it picking the time and date, and by what rules is it converting into an unsigned int. Basically, how those functions work.
Thank you!
1. About time()
time (or better std::time in C++) is a function that returns some integer or floating point number that represents the current time in some way.
Which arithmetic type it actually returns and how it represents the current time is unspecified, however, most commonly you will get some integer type that holds the seconds since begin of the Unix epoch.
2. About srand()
srand is a function that uses its argument (which is of type unsigned int), the so called seed, to set the internal state of the pseudo number generator rand. When I write random in the rest of this answer, read pseudo random.
Using a different seed will in general result in a different sequence of random numbers produced by subsequent calls to rand, while using the same seed again will result in the exactly same sequence of random numbers.
3. Using time() to seed rand()
If we do not want to get the same random numbers every time we run the program, we need some seed that is different on each run. The current time is a widely used source for such a seed as it changes constantly.
This integer (or whatever else time returned) representing the current time is now converted to unsigned int with a static_cast. This explicit cast is not actually needed as all arithmetic types convert to unsigned int implicitly, but the cast may silence some warnings. As time goes by, we can expect the resulting unsigned int and thus the sequence of random numbers produced by rand to change.
4. Pitfalls
If, as is common, time returns the number of seconds since the beginning of the Unix epoch, there are three important things to note:
The sequence you produce will be different only if at least a second has passed between two invocations.
Depending on the actual implementation, the resulting sequences may start of kind of similar if the time points used to seed rand are close to each other (compared to time since Epoch). Afaik, this is the case in MSVC's implementation. If that is problematic, just discard the first couple of hundred or thousand values of the sequence. (As I have learned by now, this does not really help much for poor RNGs as commonly used for rand. So if that is problematic, use <random> as described below.)
Your numbers are not very random in the end: If someone knows when your call to srand occurred, they can derive the entire sequence of random numbers from that. This has actually led to a decryption tool for a ransom ware that used srand(time(0)) to generate its "random" encryption key.
Also, the sequence generated by rand tends to have poor statistical properties even if the seed was good. For a toy program like yours, that is probably fine, however, for real world use, one should be aware of that.
5. The new <random>
C++11 introduced new random number facilities that are in many ways superior to the old rand based stuff. They provided in the standard header <random>. It includes std::random_device which provides a way to get actually random seeds, powerful pseudo random number generators like std::mt19937 and facilities to map the resulting random sequences to integer or float ranges without introducing unnecessary bias.
Here is an example how to randomly roll a die in C++11:
#include <random>
#include <iostream>
int main()
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(1, 6);
for (int n=0; n<10; ++n)
std::cout << dis(gen) << ' ';
std::cout << '\n';
}
(Code from cppr) Note: std::random_device does not work properly with MinGW, at least in the version (Nuwen MinGW5.3) I tested!
It should also be noted that the state space of a mt19937 is much larger than the 32 bit we (commonly) get out of a single call to random_device. Again, this will most likely not matter for toy programs and homework, but for reference: Here is my attempt to properly seed the entire state space, plus some helpful suggestions in the answers.
If you are interested in more details about rand vs <random>, this is an interesting watch.
First line:
srand() is a pseudo-random number generator. In your case it is initialized with the current time (execution time) on your system.
Second line:
After the pseudo-random number generator is configured, you can retrieve random numbers by calling rand().
I'm trying to find a random number generator that will give me a single random number each time I run it. I have spent a week trying dozens of different ones, both from this site and others. Every time I run it, it gives me the same number! The only time it changes is if I change the range, and then it just gives me the new number over and over.
I am running Code::Blocks ver. 16.01 on Windows 7. Can anyone help?? I'm at my wits' end!
This code gives me a decently ramdom string of numbers, but still the same string each time!
#include <iostream>
#include <random>
int main()
{
std::random_device rd;
std::mt19937 eng(rd()); std::uniform_int_distribution<> distr(0, 10);
for(int n=0; n<100; ++n)
std::cout << distr(eng) << '\t';
}
I have tried the code on my compiler app on my phone as well.
Every pseudo random number generator will return the same sequence of numbers for the same initial seed value.
What you want to do is to use a different seed every time you run the program. Otherwise you'll just be using the same default seed every time and get the same values.
Picking good seeds is not as easy as you might think. Using the output from time(nullptr) for example still gives the same results if two copies of the program run within the same second. Using the value of getpid() is also bad since pid values wrap and thus sometimes you'll get the same value for different runs. Luckily you have other options. std::seed_seq lets you combine multiple bad sources and returns a good (or rather, pretty good) seed value you can use. There is also std::random_device which (on all sane implementations) returns raw entropy - perfect for seeding a pseudo random generator (or you can just use it directly if it is fast enough for your purpose) or you can combine it with std::seed_seq and the bad sources to seed a generator if you are worried it might be implemented as a prng on your implementation.
I would advice you to read this page: http://en.cppreference.com/w/cpp/numeric/random for an overview of how to deal with random number generation in modern C++.
The standard allows std::random_device to be implemented in terms of a pseudo-random number generator if there is no real random source on the system.
You may need to find a different entropy source, such as the time, or user touch co-ordinates.
I can use:
boost::mt19937 gen(43);
this works just fine, but what if I want more than 32-bits of seed before using the random number generator? Is there an easy way to put 64-bits or 128-bits of seed into the Mersenne Twister?
I found a few examples of loading multiple values before generating results, but none of the code works.
There are a couple of problems with this code:
std::vector<unsigned int> seedv(1000, 11);
std::vector<unsigned int>::iterator i=seedv.begin();
boost::mt19937 gen2(i, seedv.end());
First, calling gen2() always returns the same value. I don't know how I screwed that up.
Second, I don't want 1,000 seeds, but when I lower it to 600 it "throws an instance of std::invalid_argument with note enough elements in call to seed"
Can this method be shortened to a handful of seeds?
Here is another code example that looks easy:
std::string seedv("thisistheseed");
std::seed_seq q(seedv.begin(),seedv.end());
boost::mt19937 gen2(q);
but it won't compile. I finally figured out that std::seed_seq is only available in c++11. I am stuck with gcc 4.7 until the libraries I depend on are stable.
I suppose I can just stick with a 32-bit seed, but I wanted a little bit more.
I did read this article:
Boost Mersenne Twister: how to seed with more than one value?
I like the idea of initializing the whole vector from:
mersenne_twister(seed1) ^ mersenne_twister(seed2)
but I don't see a way to do that without modifying Mersenne_Twister.hpp
Any suggestions?
UPDATE: one more way not to do it!
unsigned long seedv[4];
seedv[0]=1;
seedv[1]=2;
seedv[2]=3;
seedv[3]=4;
boost::mt19937 gen2(seedv,4);
With the right casting, this should work, but every cast I have tried still won't get past the compiler. I can cast anything in C, but C++ still stumps me at times...
Use boost::seed_seq instead of std::seed_seq.
Update: Use
boost::random_device rd;
boost::mt19937 eng(rd);
boost::mt19937 allows you to seed it with either a single value up to 32 bits in width (the w parameter of the underlying boost::mersenne_twister_engine), or with a sequence of 624 values (the n parameter of the underlying template). 624 is the number of elements in mt19937's internal state.
If you read the documentation you'll see that these two mechanisms seed the state of the engine differently.
seeding with a single value sets every element of the engine's state using a complicated function of that single value.
seeding with a sequence of 624 values sets each element of the engine state to exactly the corresponding seed value.
The point is that boost::mt19937 does not itself include a mechanism to map an arbitrary number of seed values to the fixed number of elements in its internal state. It allows you to set the state directly (using 624 values), and for convenience it offers a built-in mapping from single 32-bit values to complete, 624 element states.
If you want to use an arbitrary number of input seed values then you will need to implement a mapping from arbitrarily sized sequences to 624 element states.
Keep in mind that the mapping should be designed such that the resulting internal state is a 'good' state for the mersenne twister algorithm. This algorithm is shift-register based and can be subject to internal states which produce relatively predictable output. The built-in mapping for single values was designed to minimize this issue and whatever you implement should be as well.
Probably the best way to implement such a mapping, rather than doing the mathematical analysis yourself, is to simply use the standard mersenne twister warmup algorithm. According to a comment on this answer the C++11 std::seed_seq is specified to perform such a warmup. Boost includes boost::seed_seq, which presumably does the same thing.
Update: Instead of using some arbitrary number of values to compute a sequence of 624 values you can simply use exactly 624 random values. If the values are unbiased and evenly distributed over the range of 32-bit values then you won't need any warm-up (well, unless you're astronomically unlucky).
The boost <random> library supports this very directly:
boost::random_device rd;
boost::mt19937 eng(rd);
Note that the C++11 <random> library does not support seeding this way.
A seed-sequence generator helper exists for this reason:
The class seed_seq stores a sequence of 32-bit words for seeding a pseudo-random number generator . These words will be combined to fill the entire state of the generator. http://www.boost.org/doc/libs/1_57_0/doc/html/boost/random/seed_seq.html
#include <boost/random.hpp>
#include <boost/random/seed_seq.hpp>
int main()
{
boost::random::seed_seq ss({1ul, 2ul, 3ul, 4ul});
boost::mt19937 gen2(ss);
}
You can also pass a pair of iterators to an existing range.
Live On Coliru
The standard Mersenne Twister is the following typedef:
typedef mersenne_twister_engine<uint32_t,32,624,397,31,0x9908b0df,
11,0xffffffff,7,0x9d2c5680,15,0xefc60000,18,1812433253> mt19937;
The first template type is called UintType and is used as the argument for the seed method:
void seed(UIntType value);
You could therefore use the pre-defined boost::mt19937_64 to have a 64-bit seed. You can also create your own mersenne_twister_engine if you want to customize it more.
It's not pretty, but it should be possible to do:
std::vector<unsigned int> seedv(1000);
seedv[0] = 1;
seedv[1] = 2;
seedv[2] = 3;
seedv[3] = 4;
// etc.
boost::mt19937 gen2(seedv.begin(), seedv.end());
That is, still pass in 1000 seeds, even though most of them are 0's. However, as #bames53 mentions in a comment, this isn't a good idea. It's legal, and compiles, but doesn't make for a good seed.
By the way, the array approach should work (at least, it should compile):
unsigned long seedv[4];
seedv[0]=1;
seedv[1]=2;
seedv[2]=3;
seedv[3]=4;
boost::mt19937 gen2(seedv, seedv + 4);
This is an example of using pointers as iterators. 4 isn't an iterator (generally), but seedv + 4 is (it's the address of the element just after the end of seedv)..