Mersenne twister seed as - c++

I would like to maintain the random number generator state as a member variable, so every object generated from this class will have its one. It is necessary, that everytime an object is generated the seed gets changed too.
I did the following thing, namely changing the seed through the object's constructer. The seeding I did with time(NULL) but this is not accurate enough, since the the objects get created way faster than within a second, haha.
#include <iostream>
#include <cmath>
#include<random>
#include<chrono>
#include <ctime>
class Test{
public:
Test();
std::mt19937 rng;
double randomNumber(double min, double max);
};
Test::Test(){
rng.seed(time(NULL));
}
double Test::randomNumber(double min, double max){
std::uniform_real_distribution<double> uniformDistribution(min, max);
return uniformDistribution(rng);
}
int main(){
Test a;
Sleep(1000*1);
Test b;
for (int i = 0; i < 10; i++){
std::cout << "Random number a: " << a.randomNumber(0, 10) << "\tRandom number b: " << b.randomNumber(0, 10) << std::endl;
}
}
I am struggling with the method described in [Seeding rand() for a C++ class by bames53.
Including this piece
std::mt19937 eng{ std::chrono::high_resolution_clock::now().time_since_epoch().count() };
into the class declarations yields the following error:
Error: no instance of constructor "std::merseene_twister_engine<_Ty,_Wx, many more things> argument types are (std::chrono::system_clock::rep)
Now I do not exactly know where the error comes from and how to achieve my problem. Please keep in mind I am more or less an c++ newby.
Thank you!

Given your description you could initialize the RNG once then pass it as a reference to the Test class:
class Test{
public:
Test(std::mt19937& rng): m_rng(rng){
}
std::mt19937& m_rng;
double randomNumber(double min, double max){
std::uniform_real_distribution<double> uniformDistribution(min, max);
return uniformDistribution(m_rng);
}
};
std::mt19937 rng{std::chrono::high_resolution_clock::now().time_since_epoch().count()};
Test a(rng);
Because this particular RNG has a very long period you can instantiate it once then draw values from it across all your classes that need the random number generation.
Sample usage:
std::mt19937 rng{std::chrono::high_resolution_clock::now().time_since_epoch().count()};
Test a(rng);
Test b(rng);
for(int i=0; i<10; ++i){
std::cout<< "a: " << a.randomNumber(0.0,1.0) << "b: " << b.randomNumber(5.0,6.0) << std::endl;
}
Here's this code in action: http://ideone.com/Lzyp22

Related

How to avoid same sequences of random numbers

I would like to generate different sequences of uniformly distributed samples. To this end, I initialize the default random engine with different seeds, but the same sequences are produced:
#include <iostream>
#include <random>
void fun(double seed)
{
std::cout << "given seed: " << seed << std::endl;
std::default_random_engine gen_2(seed);
std::uniform_real_distribution<double> dis_2(0.0,1.0);
std::cout << dis_2(gen_2) << std::endl;
std::cout << dis_2(gen_2) << std::endl;
}
int main()
{
double seed = 1.0;
std::default_random_engine gen_1(seed);
std::uniform_real_distribution<double> dis_1(0.0,1.0);
for(size_t i=0; i<3; ++i)
{
fun(dis_1(gen_1));
}
}
The output reads:
given seed: 0.0850324
0.0850324
0.891611
given seed: 0.891611
0.0850324
0.891611
given seed: 0.18969
0.0850324
0.891611
How can I produce different sequences in the function fun?
The seed of the generator is an integer.
The problem is that all numbers generated by your dis_1 are less than 1, and greater than or equal to 0. Therefore they implicitly convert to the same value 0 when converted to an integer.
The solution is to use a different seed, rather than 0 always.

random_shuffle and srand() give me the same result every time

I'm trying to produce do some processing on a random permutation of the alphabet, however each permutation produces the same result despite using srand(myseed)
I have included the <algorithm> header.
string create_permutation(unsigned seed)
{
srand(seed);
string permutation = ALPHABET;
random_shuffle(permutation.begin(), permutation.end());
return permutation;
}
cout << create_permutation(2) << endl; // or 3, 4, 5 etc
// continuously returns 'XQACKHSLOJ,TRBZNGV.W FIUEYDMP
Any help would be greatly appreciated.
EDIT: Minimal, Complete, and Verifiable example
EDIT 2: adjustment to mcve
#include <iostream>
#include <algorithm>
using namespace std;
const string ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.,' ";
string create_permutation(unsigned seed)
{
srand(seed);
string permutation = ALPHABET;
random_shuffle(permutation.begin(), permutation.end());
return permutation;
}
int main(){
cout << create_permutation(2) << endl; // or 3, 4, 5 etc
// continuously returns 'XQACKHSLOJ,TRBZNGV.W FIUEYDMP
return 0;
}
The problem
The shuffles aren't random because shuffle_random is using the same seed for the random number generator each time it is called.
srand does not seed the random_shuffle function, it seeds rand and random_shuffle usually calls rand, but does not have to.
random_shuffle has two forms:
One that takes 2 arguments (begin/end iterators)
One that takes 3 (begin/end iterator and a random generator).
You have demonstrated that you know how to use the first form, but the problem with the first form is that it is implemented differently on different platforms and with different compilers. It may not use rand() at all, which is the function that srand seeds.
You should use the 3 argument form and provide the random number generator as a parameter to the function.
You can follow this detailed answer to learn how to make your own random number generator, or you can provide rand() to the random_shuffle function as the random number generator.
When you seed the random number generator, you set the starting point for an algorithm that will provide a sequence of psuedorandom numbers. If you always use the same seed, the algorithm will always have the same starting point and always generate the same sequence of numbers.
Every time you call srand, you reset the seed and reset the starting point for the algorithm.
A common bug here is to repeatedly call srand. Unless you have a very good reason not to (and if you do, you probably shouldn't use rand and srand at all. Look to the <random> library) you should call srand once at the beginning of the program to seed the generator once and ever after use that seed.
srand is also quite expensive. From a performance standpoint, you don't want to call it often.
So: since every call to create_permutation calls srand with the seed parameter and create_permutation is always called with the same seed value, for a given implementation of the random number generator, create_permutation will always use the same random number sequence and thus generate the same permutation.
A quick example that will generate different permutations, so long as the program is not run more often than once per second is
#include <iostream>
#include <string>
#include <algorithm>
#include <ctime>
const std::string ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.,' ";
std::string create_permutation()
{
std::string permutation = ALPHABET;
std::random_shuffle(permutation.begin(), permutation.end());
return permutation;
}
int main(){
srand(time(NULL)); // caveat: time's minimum resolution is 1 second.
// multiple executions of this program within 1
// second will get the same time and use the same seed.
std::cout << create_permutation() << std::endl;
std::cout << create_permutation() << std::endl;
std::cout << create_permutation() << std::endl;
std::cout << create_permutation() << std::endl;
std::cout << create_permutation() << std::endl;
return 0;
}
A more modern approach:
#include <random>
#include <algorithm>
#include <iostream>
#include<string>
const std::string ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ.,' ";
std::random_device rd; // Warning: implementation of this is allowed to be stupid and
// return the same value every time. Does not work in mingw 4.8
// Can't speak for 4.9 or greater
std::mt19937 randomizer(rd());
std::string create_permutation()
{
std::string permutation = ALPHABET;
std::shuffle(permutation.begin(), permutation.end(), randomizer);
return permutation;
}
int main()
{
std::cout << create_permutation() << std::endl;
std::cout << create_permutation() << std::endl;
std::cout << create_permutation() << std::endl;
std::cout << create_permutation() << std::endl;
std::cout << create_permutation() << std::endl;
}

C++ - How to correctly bind a default_random_engine to two different uniform_int_distributions

I am trying to use two different objects of std::uniform_int_distribution bound (using std::bind) with the same object std::default_random_engine as argument (as described here http://www.cplusplus.com/reference/random/), but binding them together results in different behavior than using them unbound:
#include <iostream>
#include <functional>
#include <random>
using namespace std;
int main()
{
default_random_engine generator;
int dist1Max = 10, dist2Max = 10;
uniform_int_distribution<int> dist1(1, dist1Max);
uniform_int_distribution<int> dist2(1, dist2Max);
function<int()> boundDist1 = std::bind(dist1, generator);
function<int()> boundDist2 = std::bind(dist2, generator);
for (int i=0; i<10; ++i)
{
cout << boundDist1() << " " << boundDist2() << endl;
}
cout << endl;
for (int i=0; i<10; ++i)
{
cout << dist1(generator) << " " << dist2(generator) << endl;
}
}
The second loop produces random numbers as I want them, while in the first one boundDist1() and boundDist2() always produce the same number in each cycle of the loop.
So my question is:
How does std::bind change the behavior of the function call and how can I avoid this problem?
The problem is that by default, bind will copy its argument to the closure, rather than create a reference to them. Random engines being copyable, you get two distinct engines that create the same numbers.
You need to wrap the generators in bind with std::ref. This tells bind that you want to keep a reference to the engine, not make a copy of it.
function<int()> boundDist1 = std::bind(dist1, std::ref(generator));
function<int()> boundDist2 = std::bind(dist2, std::ref(generator));
Here's an ideone run with it.

How to generate 64 bit random numbers?

I'm implementing universal hashing and using the following universal hash function :
h(k)=((A*k)mod 2^64) rsh 64-r
where A is a random number between
2^61 and 2^62.
The rand() function in C++ has return type integer and it can't generate that big numbers. So how can i generate random numbers in this range? (numbers should be very random i.e. every number should have equal probability to be selected)
Note:
long long int random=rand();
doesn't work as the number returned by rand is int.
In C++11 you can use the random header and std::uniform_int_distribution along with a 64-bit instance of std::mersenne_twister_engine this should do what you want (see it live):
#include <iostream>
#include <random>
#include <cmath>
int main()
{
std::random_device rd;
std::mt19937_64 e2(rd());
std::uniform_int_distribution<long long int> dist(std::llround(std::pow(2,61)), std::llround(std::pow(2,62)));
std::cout << std::llround(std::pow(2,61)) << std::endl;
std::cout << std::llround(std::pow(2,62)) << std::endl;
for (int n = 0; n < 10; ++n) {
std::cout << dist(e2)<< ", " ;
}
std::cout << std::endl ;
}
If C++11 is not an option then it seems there is source code available for several 64-bit Mersenne Twister implementations.
((long long)rand() << 32) | rand()
EDIT: that's assuming that rand() produces 32 random bits, which it might not.

Program is generating same random numbers on each run? [duplicate]

This question already has answers here:
Why does rand() yield the same sequence of numbers on every run?
(7 answers)
Closed 5 years ago.
I just finished coding a Minesweeper type game, and everything's good except for that each time I run the application, it generates the same number (I ran it 3 different times, saved the output to 3 text files and used the diff command in Linux, it didn't find any differences). It's seeded by time(NULL) so it should change every time, right?
Here's my code:
main.cpp
#include <iostream>
#include <cstdlib>
#include <time.h>
#include <string>
#include "Minesweeper/box.h"
#include <cstdio>
int main(int argc, char** argv){
using namespace std;
bool gameOver = false;
int x, y, score = 0;
const int HEIGHT = 10;
const int WIDTH = 10;
unsigned int Time = time(0);
cout << "Welcome to Minesweeper. " << endl;
//setup grid
Box grid[10][10];
for(int i = 0; i < WIDTH; i++)
for(int n = 0; n < HEIGHT; n++){
unsigned int value = rand() %100 + 1;
cout << value << endl;
if(value <= 38){
grid[i][n].setFill(MINE);
//cout << i << "," << n << " is mined." << endl;
}
else
grid[i][n].setFill(EMPTY);
}
for(int r = 0; r < WIDTH; r++)
for(int l = 0; l < HEIGHT; l++)
if(grid[r][l].getFill() == EMPTY)
cout << r << "," << l << " - EMPTY." << endl;
else if (grid[r][l].getFill() == MINE)
cout << r << "," << l << " - MINE." << endl;
while(!gameOver){
cout << "Enter coordinates (x,y): ";
scanf("%i,%i",&x,&y);
if(grid[x][y].getFill() == MINE)
gameOver = true;
else{
cout << "Good job! (You chose " << x << "," << y << ")" << endl;
score++;
}
}
cout << "You hit a mine! Game over!" << endl;
cout << "Final score: " << score << endl;
getchar();
return EXIT_SUCCESS;
}
It's seeded by time(NULL)
If it is, I can't see it. In fact, a search for it in your code returns nothing. The default behaviour, if you don't explicitly seed, is the same as if you had seeded it with the value 1.
You need to explicitly state something like:
srand (time (NULL));
at the start of main somewhere (and make sure you do this once and once only).
Though keep in mind this makes it dependent on the current time - if you start multiple jobs in the same second (or whatever your time resolution is), they'll start with the same seed.
From the C standard (on which C++ is based for these compatibility features):
The srand function uses the argument as a seed for a new sequence of pseudo-random numbers to be returned by subsequent calls to rand. If srand is then called with the same seed value, the sequence of pseudo-random numbers shall be repeated. If rand is called before any calls to srand have been made, the same sequence shall be generated as when srand is first called with a seed value of 1.
You need to seed randomizer. Call srand() at the beginning.
To add to the answers by others, you can use the Mersenne Twister Algorithm, which is a part of the C++11 library. Its fast becoming a standard in many common softwares to generate random numbers.
For example, this is the function I wrote, which I use often to generate random numbers in my other codes:
std::vector<double> mersennetwister(const int& My,const int& Mz,
const int& Ny,const int& Nz)
{
int ysize = (My + 2*Ny + 1);
int zsize = (Mz + 2*Nz + 1);
int matsize = ysize*zsize;
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
// Seeding the generator with the system time
std::mt19937_64 generator (seed);
// Calling the Mersenne-Twister Generator in C++11
std::uniform_real_distribution<double> distribution(0,1);
// Specifying the type of distribution you want
std::vector<double> randarray(matsize,0);
// Saving random numbers to an array
for (int i=0;i<matsize;++i)
{
randarray[i] = distribution(generator); // Generates random numbers fitting the
// Distribution specified earlier
}
return(randarray);
}
Bottomline: C++11 has some excellent features for numerical operations and it would be a good idea to look into them. As for the Mersenne Twister, http://en.wikipedia.org/wiki/Mersenne_twister