I would like to use built-in distribution, but add some constraints to it. I tried something like this, but i get same number when using function. How can i avoid this? Can i use distribution as a argument to the function?
double Cauchy(double Fm){
std::default_random_engine generator;
std::cauchy_distribution<double> distribution(Fm, 0.1);
double number=distribution(generator);
while(number<0)
number=distribution(generator);
if (number>1)
number = 1;
return number;
}
Now i changed function and it looks like this
double Cauchy_1(double Fm, std::random_device &rd){
std::default_random_engine generator(rd());
std::cauchy_distribution<double> distribution(Fm, 0.1);
double number=distribution(generator);
while(number<0)
number=distribution(generator);
if (number>1)
number =1;
return number;
}
std::random_device rd;
int i=15;
double Crm=0.1, num;
while (i>0){
num=Cauchy_1(0.1, rd);
cout<<num<<endl;
i--;
}
It gives me different values, but values are the same on new run.
You initialize std::default_random_engine generator; with the same default seed. You need to seed it to get different outputs if you instantiate it anew. There is std::random_device class you can use to get a new random seed.
Also, std::default_random_engine is slow class to instantiate/create so you are using it wrong.
Functions in the standard library like std::shuffle take a random number generator by a forwarding reference, not a distribution. You can do the same:
template<class URBG>
double cauchy_1(double fm, URBG&& gen) {
std::cauchy_distribution<double> distribution(fm, 0.1);
double number;
do
number = distribution(gen);
while (number < 0);
return std::min(number, 1.0);
}
int main() {
std::random_device rd;
std::default_random_engine gen(rd());
for (int i = 0; i < 10; ++i) {
auto num = cauchy_1(0.1, gen);
std::cout << num << std::endl;
}
}
It still has same set of numbers if i rerun this code.
This is not the problem of this code, but the problem of std::random_device. As explained here, std::random_device may be implemented in terms of a pseudo-random number engine. Possible solutions can be found here.
For example:
std::default_random_engine gen(
std::chrono::system_clock::now().time_since_epoch().count());
Related
I find a method of generating uniform random number in range(aa,bb) as below:
#include <random>
double randnum (double aa, double bb) //defining a function to create random numbers
{
static std::default_random_engine generator;
std::uniform_real_distribution<double> distribution (aa,bb);
return distribution(generator);
}
int main (){
for (i=1;i<50;i++){
cout<< randnum(0,1);
}
}
For example, randnum(0,1); creates a random number between 0 and 1. The problem is that, during different runs, the random sequence which I create in for loop is exactly the same. How can I create different random numbers during different runs?
Use a non-deterministic random number engine to seed a more performant, deterministic one, like the mersenne twister:
#include <iostream>
#include <random>
double randnum (double aa, double bb) { //defining a function to create random numbers
static std::random_device rd; // non-deterministic, but may be slow
static std::mt19937 engine{ rd() };
std::uniform_real_distribution<double> distribution (aa,bb);
return distribution(engine);
}
int main() {
for(int i=1; i<50; i++) {
std::cout<< randnum(0,1);
}
}
https://ideone.com/dgvarY
I've a function to generate random characters from a set of alphabets. This function would be called multiple times and thus I'm trying to make it use same set of variables, ie have same seed so that strings don't repeat as long as possible.
#include <iostream>
#include <random>
#include <string>
std::string generateRandomChar(const unsigned int _len)
{
std::string result;
result.reserve(_len);
static constexpr char alphanum[] = "0123456789"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 61);
for (int i = 0; i < _len;
result += (alphanum[dis(gen)]);
}
return result;
}
int main(){
for(int i = 0; i < 10; ++i){
std::cout << generateRandomChar(10) << std::endl;
}
}
Unfortunately I don't have any expertise with c++11 functions and I was only using srand and friends earlier, so I might be making lots of mistakes here. Currently it works and generates tons of strings without repeating, but I'm sure I could make either of -
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 61);
static variable too, so that it isn't calculated each time the function is called because that would be waste right?
So which one should be static here? Are there any mistakes/improvements that you see here?
Thankyou :D
edit - here's an ideone link - http://ideone.com/e7ssXo
So which one should be static here?
Either std::mt19937 gen or none of them.
std::random_device generates uniformly-distributed random integers using non-deterministic entropy source, if available. Your code uses std::random_device output as a seed for std::mt19937 pseudo-random generator. So you are very likely to have good, non-deterministic seeds for std::mt19937 if you run on a PC, and thus there is no need to make any of them static. I suppose that std::random_device is implemented as a pure-procedural PRNG only on low-end controllers.
On the other hand, one-time seeding is more idiomatic, so you may declare std::mt19937 as static. std::mt19937 itself implements a high-quality PRNG algorithm with 19937 bits of state, so it's period probably exceeds the Universe lifetime (or at least the stelliferous era), if the generator is running on a modern PC.
There is no need to make std::uniform_int_distribution static, as it's only a wrapper which modifies actual generator's output according to desired distribution properties. So it's up to you to decide whether make it static or not.
To allow unit test, I suggest to move the generator outside of the function, something like
std::string generateRandomChar(const unsigned int len, std::mt19937& gen)
{
std::string result;
result.reserve(len);
static constexpr char alphanum[] = "0123456789"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
std::uniform_int_distribution<> dis(0, 61);
for (int i = 0; i < len; ++i) {
result += (alphanum[dis(gen)]);
}
return result;
}
int main() {
std::random_device rd;
std::mt19937 gen(rd());
for (int i = 0; i < 10; ++i) {
std::cout << generateRandomChar(10, gen) << std::endl;
}
}
or create a class
class RandomCharGenerator
{
public:
RandomCharGenerator() : RandomCharGenerator(std::random_device{}()) {}
template <typename T>
RandomCharGenerator(T&& seed) : gen(std::forward<T>(seed)) {}
std::string operator() (const unsigned int len)
{
std::string result;
result.reserve(len);
for (int i = 0; i < len; ++i) {
result += (alphanum[dis(gen)]);
}
return result;
}
private:
std::mt19937 gen;
std::uniform_int_distribution<> dis{0, 61};
static constexpr char alphanum[] = "0123456789"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
};
int main() {
RandomCharGenerator charGenerator{};
for (int i = 0; i < 10; ++i) {
std::cout << charGenerator(10) << std::endl;
}
}
You can eventually templated things to allow other rand generator.
You can make your random_device and mt19937 static. Currently you are constructing one everytime the function is called (IIRC, mt19937 is expensive to construct. Someone corect me). Also, your uniform_int_distribution can be moved out of the loop. This question is better suited for codereview as it already works and you are looking for improvements.
TL;DR: You can make all of them static.
For my program, I needed so far to draw one random value in [0..k[ from time to time, and using C++11 <random> features works really well. My current code is something like
class Random
{
public:
Random() : rng( rd() ) { }
inline int getRandNum( int limit ) { return ( numbers(rng) % limit ); }
private:
std::random_device rd;
std::mt19937 rng;
std::uniform_int_distribution<int> numbers;
};
Now, I need to draw in a row n different values in [0..k[. I was looking for something in <random> allowing that, but either I am not able to find it, or such a thing does not exist yet. Is there a clever, more elegant way to proceed than calling my getRandNum function and repeat until I get n different values?
EDIT: to give an idea, in my program k is some thousands and n some tens.
This solution is not C++ specific but can be easily implemented in any language.
What you want is essentially shuffle numbers 0 to k and pick the first n numbers, where n <= k.
This can be done using a reservoir sampling algorithm. See this wikipedia link for the pseudocode.
Note that it is possible to get the n numbers without storing all k numbers and shuffling them. That is, it is possible to just use O(n) space, where n is the number of random numbers you wish to obtain, instead of O(k). The time complexity for this algorithm is O(k), if we assume generating the random number takes O(1) time.
If k is several thousands and n is tens, then a permutation generation is really not the best choise. But calling getRandNum is not what you want too, because it can return the same value several times.
One option is to generate random sequence all at once, checking that the numbers don't repeat. The easiest (and may be even the most efficient) way to achieve this is to use a set.
Like so:
#include <vector>
#include <set>
#include <iostream>
#include <random>
class Random
{
public:
Random() : rng( rd() ) { }
inline int getRandNum( int limit ) { return ( numbers(rng) % limit ); }
std::set<int> getRandSequence(int limit, int n);
private:
std::random_device rd;
std::mt19937 rng;
std::uniform_int_distribution<int> numbers;
};
std::set<int> Random::getRandSequence(int limit, int n)
{
std::set<int> generatedSequence;
while (generatedSequence.size() < n) //size() for set is O(1) if I'm not mistaken
generatedSequence.insert(getRandNum(limit));
return generatedSequence;
}
int main()
{
Random r;
auto sequence = r.getRandSequence(1000, 10);
std::cout << "Seq;uence: " << std::endl;
for (int number : sequence)
std::cout << number << std::endl;
std::cout << "End" << std::endl;
return 0;
}
Ideone demo.
By the way, random_device creation is expensive, but uniform_int_distribution creation, as far as I remember, is not. So this might be even more efficient:
std::set<int> Random::getRandSequence(int limit, int n)
{
std::uniform_int_distribution<int> uiniformDistribution(0, limit);
std::set<int> generatedSequence;
while (generatedSequence.size() < n)
generatedSequence.insert(uiniformDistribution(rng));
return generatedSequence;
}
Besides, when you get a uniform distribution and then apply % limit to it, you don't get a uniform distribution anymore.
std::random_device rd; // obtain a random number from hardware
std::mt19937 eng(rd()); // seed the generator
std::uniform_int_distribution<> distr(0, 1500); // define the range
for(int a=0; a<limit; a++){
cout << distr(eng); //draw random nubmer
I just played around with Eigen a bit and noticed that MatrixXf::Random(3,3) always returns the same matrices, first one is always this for example:
0.680375 0.59688 -0.329554
-0.211234 0.823295 0.536459
0.566198 -0.604897 -0.444451
Is that intended behaviour or am i just overseeing something really simple? (My experience with mathematic libraries is close to zero)
Code i used:
for(int i = 0; i < 5; i++) {
MatrixXf A = MatrixXf::Random(3, 3);
cout << A <<endl;
}
Instead of srand you can also use a nullary expression together with modern C++11 random number generation:
//see https://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution
std::random_device rd;
std::mt19937 gen(rd()); //here you could set the seed, but std::random_device already does that
std::uniform_real_distribution<float> dis(-1.0, 1.0);
Eigen::MatrixXf A = Eigen::MatrixXf::NullaryExpr(3,3,[&](){return dis(gen);});
This also allows to use more complex distributions such as a normal distribution.
Yes, that's the intended behaviour. Matrix::Random uses the random number generator of the standard library, so you can initialize the random number sequence with srand(unsigned int seed), for instance:
srand((unsigned int) time(0));
#orian:
std::srand(unsigned seed) is not an Eigen function. The complete code should work like that:
std::srand((unsigned int) time(0));
for(int i = 0; i < 5; i++) {
MatrixXf A = MatrixXf::Random(3, 3);
cout << A <<endl;
}
How about this way?
#include<iostream>
#include<random>
#include <Eigen/Dense>
int main(){
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<float> dis(0, 1);
Eigen::MatrixXf m = Eigen::MatrixXf::Zero(10,10).unaryExpr([&](float dummy){return dis(gen);});
cout<<"Uniform random matrix:\n"<<m<<endl;
cout<<"Mean: "<<m.mean()<<endl;
return 0;
}
I need to generate a random number between 1 and n where n is unsigned int.
If n were int I would simply write 1 + rand()% n. But unfortunately n is unsigned int. What do you suggest?
rand() should be avoided whenever possible*.
Use http://en.cppreference.com/w/cpp/numeric/random
#include <random>
#include <iostream>
int main()
{
std::random_device rd;
std::mt19937 engine(rd());
std::uniform_int_distribution<unsigned> dist(1, 77);
for (int i = 0; i != 5; ++i)
std::cout << dist(engine) << '\n';
}
* Because it shares a global state, gets often implemented as a linear congruential engine which has a few drawbacks and it's range is often only 0-2^16. Also, % n where n is not an exact multiple of the range does not produce an uniform distribution.
Edit: This might seem like overkill, but technically one would want something like this, since mt19937 needs a bit of "warm up":
std::mt19937 create_seeded_rng()
{
std::random_device rd;
std::array<std::mt19937::result_type, std::mt19937::state_size> seed_data;
std::generate(seed_data.begin(), seed_data.end(), std::ref(rd));
std::seed_seq seq(seed_data.begin(), seed_data.end());
return std::mt19937(seq);
}
int main()
{
std::mt19937 rng = create_seeded_rng();
std::uniform_int_distribution<int> dist(0, 100);
for (unsigned i = 0; i != 100; ++i)
std::cout << dist(rng) << '\n';
}