Default_random_engine passed into a function gives repeatable results - c++

I have a class Permutation that inherits from std::vector<int>. I created a constructor that makes the object filled with non-repeating numbers. Randomness is meant to be guaranteed by <random> stuff, so the declaration goes like this:
/* Creates a random permutation of a given length
* Input: n - length of permutation
* generator - engine that does the randomizing work */
Permutation(int n, default_random_engine generator);
Function itself looks like this (irrevelant details skipped):
Permutation::Permutation(int n, default_random_engine generator):
vector<int>(n, 0)
{
vector<int> someIntermediateStep(n, 0);
iota(someIntermediateStep.begin(), someIntermediateStep.end(), 0); //0, 1, 2...
shuffle(someIntermediateStep.begin(), someIntermediateStep.end(),
generator);
// etc.
}
And is called in the following context:
auto seed = std::chrono::system_clock::now().time_since_epoch().count();
static std::default_random_engine generator(seed);
for (int i = 0; i < n; i++)
Permutation test(length, generator);
Code compiles perfectly fine, but all instances of Permutation are the same. How to force regular generation of random numbers? I know that default_random_engine should be binded to a distribution object, but hey, I don't have any – I use the engine only in shuffle() (at least at the moment).
Is there any solution or a workaround that still uses the goodness of <random>?

Your Permutation constructor takes the engine in by value. So, in this loop:
for (int i = 0; i < n; i++)
Permutation test(length, generator);
You are passing a copy of the same engine, in the same state, over and over. So you are of course getting the same results. Pass the engine by reference instead
Permutation::Permutation(int n, default_random_engine& generator)
That way its state will be modified by the call to std::shuffle.

So a childish mistake, just as I supposed – I mixed various solutions to similar problems in a wrong way.
As Benjamin pointed out, I mustn't copy the same engine over and over again, because it remains, well, the same. But this alone doesn't solve the issue, since the engine is pointlessly declared static (thanks, Zereges).
For the sake of clarity, corrected code looks like this:
Permutation(int n, default_random_engine &generator);
// [...]
Permutation::Permutation(int n, default_random_engine generator):
vector<int>(n, 0)
{
vector<int> someIntermediateStep(n, 0);
iota(someIntermediateStep.begin(), someIntermediateStep.end(), 0); //0, 1, 2...
shuffle(someIntermediateStep.begin(), someIntermediateStep.end(),
generator);
// etc.
}
// [...]
// some function
auto seed = chrono::system_clock::now().time_since_epoch().count();
default_random_engine generator(seed);
for (int i = 0; i < n; i++)
Permutation test(length, generator);

Related

When is it preferable to use rand() vs a generator + a distribution? (e.g. mt19937 + uniform_real_distribution)

After going through the rabbit hole that is learning about rand() and how it's not very good at generating uniform pseudorandom data based on what I've dug into based on this post:
Random float number generation. I am stuck trying to figure out which strategy would yield better balance of performance and accuracy when iterated a significant number of times, 128*10^6 for an example of my use case.
This link is what led me to make this post, otherwise I would have just used rand(): rand() considered harmful
Anyway, my main goal is to understand whether rand() is ever preferable to use over the generator + distribution method. There doesn't seem to be very good info even on cppreference.com or cplusplus.com for performance or time complexity for either of the two strategies.
For example, between the following two random number generation strategies is it always preferable to use the 2nd approach?
rand()
std::mt19937 and uniform_real_distribution
Here is an example of what my code would be doing:
int main(){
int numIterations = 128E6;
std::vector<float> randomData;
randomData.resize(numIterations);
for(int i = 0; i < numIterations; i++){
randomData[i] = float(rand())/float(RAND_MAX);
}
}
vs.
#include<random>
int main(){
std::mt19937 mt(1729);
std::uniform_real_distribution<float> dist(0.0, 1.0);
int numIterations = 128E6;
std::vector<float> randomData;
randomData.resize(numIterations);
for(int i = 0; i < numIterations; i++){
randomData[i] = dist(mt);
}
}

Random function generator C++

I want to generate a random number in C++ based on known distribution.
Here is the problem. I rolled a dice (say) 6 times, and I record a four for 3 times, and an one for 1 times, and a two for 2 times.
So four=3/6, one=1/6, two=2/6
Is there a library function that I could use which generates a random number based on the above distribution?
If not, do you think it is valid for me to simply do
int i= ran()%5;
if (i is in the range of 0 to 2)
{
//PICK FOUR
}
else if (i is in the range of 3 to 4)
{
// PICK ONE
}
else
{
// PICK TWO
}
int pick()
{
static const int val[6] = { 4,4,4,1,2,2 };
return val[ran()%6]; // <---- note %6 not %5
}
Edit Note ran() % 6 may or may not be uniformly distributed, even if ran() is. You probably want something that is guaranteed to be uniformly distributed, e.g.
std::random_device device;
std::default_random_engine engine(device());
std::uniform_int_distribution<int> dist(0, 5);
Now dist(engine) is a good replacement for ran()%6.
Edit2 From a suggestion in the comments, here's a version based on std::discrete_distribution:
std::random_device device;
std::default_random_engine engine(device());
std::discrete_distribution<> dist ({1, 2, 0, 3, 0, 0});
int pick()
{
return dist(engine) + 1;
}

Adding Gaussian noise

I have a .arff file which contains a list of float numbers. I need to add to every number a gaussian noise, which in MATLAB would be:
m = m+k*randn(size(m)
where m is one of the numbers in the list and k is a standard deviation and has value 0.1. What is the C++ equivalent to randn()?
Could you please provide an example?
Use std::normal_distribution with an appropriate generator (std::default_random_engine will usually work). See http://en.cppreference.com/w/cpp/numeric/random for details on all of the random number generation facilities of the C++ standard library.
(live example)
#include <iostream>
#include <iterator>
#include <random>
int main() {
// Example data
std::vector<double> data = {1., 2., 3., 4., 5., 6.};
// Define random generator with Gaussian distribution
const double mean = 0.0;
const double stddev = 0.1;
std::default_random_engine generator;
std::normal_distribution<double> dist(mean, stddev);
// Add Gaussian noise
for (auto& x : data) {
x = x + dist(generator);
}
// Output the result, for demonstration purposes
std::copy(begin(data), end(data), std::ostream_iterator<double>(std::cout, " "));
std::cout << "\n";
return 0;
}
Output:
0.987803 1.89132 3.06843 3.89248 5.00333 6.07448
Further considerations
For decent statistical properties, you'll probably want to choose the std::mersenne_twister_engine generator (or, for convenience, the std::mt19937 predefined version), and seed it using std::random_device:
std::mt19937 generator(std::random_device{}());
[Note: Seeding from std::random_device is a good practice to get into; if you use the current time as a seed, you can end up with the same seed value across multiple generators (e.g. when initialising several generators in a very short period of time). std::random_device will obtain entropy from the system, if available.]
In order to avoid passing the generator to the distribution every time, you can do something like:
auto dist = std::bind(std::normal_distribution<double>{mean, stddev},
std::mt19937(std::random_device{}()));
which you can then use as follows:
double val = dist();
(Live example with these modifications)
The c++ standard now includes several distributions for random numbers.
You are looking for std::normal_distribution.
In the documentation you can also find a code sample
// construct a trivial random generator engine from a time-based seed:
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::default_random_engine generator (seed);
std::normal_distribution<double> distribution (0.0,1.0);
std::cout << "some Normal-distributed(0.0,1.0) results:" << std::endl;
for (int i=0; i<10; ++i)
std::cout << distribution(generator) << std::endl;
The parameters given to the constructor, std::normal_distribution, are first mean (0.0) and standard-deviation (1.0).

C++ with OpenMP thread safe random numbers

I am trying to draw some random points, and then calculate smth with them. I am using few threads, but my random is not so random as it supposed to be... I mean when I am using rand() I gets correct answer, but very slow(because of static rand), so I am using rand_r with seed, but the answer of my program is always wird.
double randomNumber(unsigned int seed, double a, double b) {
return a + ((float)rand_r(&seed))/(float)(RAND_MAX) * (b-a);
}
my program:
#pragma omp parallel
for(int i = 0; i < points; i++){
seedX = (i+1) * time(NULL);
seedY = (points - i) * time(NULL);
punkt.x = randomNumber(seedX, minX, maxX);
punkt.y = randomNumber(seedY, minY, maxY);
...
}
I found some solution in other topics(some mt19937 generators etc), but i cant compile anything.
I am using g++ -fopenmp for compiling.(g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2)
edit:
seed = rand();
#pragma omp parallel
for(int i = 0; i < points; i++){
punkt.x = randomNumber(seed, minX, maxX);
punkt.y = randomNumber(seed, minY, maxY);
...
}
Re-seeding your generators within each iteration of the for loop is going to ruin their statistical properties.
Also, it's likely that you'll introduce correlation between your x and y values if you extract them using two linear congruential generators.
Keep it simple; use one generator, and one seed.
Going forward, I'd recommend you use mt19937 as it will have better properties still. Linear congruential generators can fail a chi squared test for autocorrelation which is particularly important if you are using it for an x, y plot.
I believe that others are trying to say is, seed one in constructor with srand(some number), then do not seed anymore.
class someRandomNumber
{
}

Why are the results of RNG same every time?

I have a problem about RNG class. I want to get different point randomly from a given image, so I use the RNG class which is recommended in the OpenCV documentation. The code is:
struct SingleAnt
{
int row;
int col;
};
void initializeAnts( SingleAnt *ants, Mat *sourceImage )
{
RNG rng( 0xFFFFFFFF );
int imgWidth = sourceImage->cols;
int imgHight = sourceImage->rows;
for( int index = 0; index < ANTSNUMBER; index++ ) {
ants[ index ].col = rng.uniform( 0, imgWidth );
ants[ index ].row = rng.uniform( 0, imgHight );
}
}
However, when I run this code, I get the same result every time. Are there any mistakes in the code?
RNG rng( 0xFFFFFFFF );
Here you are (presumably) providing the PRNG with a seed value - specifically the same seed value (0xFFFFFFFF) every time the code runs. Because of this, the PRNG (being a completely deterministic algorithm) is going to provide the same sequence of output values every time.
Instead, you should provide it with a pseudo-random seed value. Typically, the system time() value is used to seed a PRNG. Many times, calling a parameter-less constructor for a PRNG actually does this for you.
As B... points out, The cv::RNG class does have a parameterless constructor: cv::RNG::RNG(), but it does not seed the generator. From the documentation, RNG::RNG() only
sets the state to some pre-defined value, equal to 2**32-1 in the current implementation
So as I previously suggested, you should seed it yourself.