I'm trying to figure out how to generate a random Gaussian vector in c++. Would it be sufficient to generate random gaussian numbers and putting them in a vector?
EDIT: I just realized you were, probably, talking about multivariate Gaussian distribution. In this case, I think, you'd need N normal distributions, each corresponding to an univariate distribution along one of the coordinates. Then, you generate random vector's coordinates by sampling each of the distributions. Effectively, the edited code below represents coordinates of 10 two-dimensional random vectors, using C++11 pseudo-random number generation (code on ideone.com). Note, in the example given there will be correlation between the two coordinates, since there is correlation between consecutive pseudo-random numbers. One can try using two seeds with two generators with more sophisticated algorithms provided by the Standard library. However, I feel, there still might be a correlation, even using two different generators - one would have to investigate this issue to give a definite answer.
#include <iostream>
#include <vector>
#include <random>
#include <iomanip>
int main()
{
std::random_device device_random_;
std::default_random_engine generator_(device_random_());
std::normal_distribution<> distribution_x_(1.0, 0.5);
std::normal_distribution<> distribution_y_(10.0, 1.0);
std::vector<double> vector_x_, vector_y_;
for (int counter_(0); counter_ < 10; ++counter_)
{
vector_x_.push_back(distribution_x_(generator_));
vector_y_.push_back(distribution_y_(generator_));
std::cout << std::fixed << std::setprecision(4) << "(" << vector_x_[counter_]
<< ", " << vector_y_[counter_] << ")\n";
}
return (0);
}
Program output:
(0.2390, 10.3887)
(1.1087, 9.5847)
(1.0920, 9.3468)
(1.1982, 11.6633)
(0.8840, 11.0903)
(0.5573, 8.5121)
(0.6709, 11.4706)
(1.1477, 9.4374)
(0.8778, 11.0323)
(0.8255, 9.7704)
Boost.Random includes a normal distribution generator. You should be able to use this to populate a vector. Complete tested example code:
#include <boost/random/random_device.hpp>
#include <boost/random/normal_distribution.hpp>
#include <vector>
int main()
{
boost::random::random_device rng;
boost::random::normal_distribution<> generator(0, 100);
std::vector<int> vec;
vec.reserve(100);
std::generate_n(
std::back_inserter(vec),
100,
[&] () { return generator(rng); });
for (auto i : vec)
std::cout << i << ',';
return 0;
}
Related
This question already has answers here:
Random numbers based on a probability
(3 answers)
Closed last month.
I wonder how one would go about coding weighted random in C++—having a random outcome but where you can control the outcome percentage of each result. I have searched the web but have yet to find anything but the Javascript version.
I want to program a question game, which I have programmed in python previously without being able to controll the percentages. Still, I want to transfer the program to C++ as there is more controllability. The program would have a list of questions; currently, the python version has just multiplication table questions, but I would like to have other genres of questions once I get this weighted random figured out. So far, I have been able to get the python code to stop asking a question that was correctly answered. Still, I would like it to slightly lessen the chance of it appearing as a question instead of it just not appearing after correctly answered once. If someone can explain how to get a weighted random in C++, I can transfer the rest of the code to C++ without issue.
Have a look at std::discrete_distribution:
#include <iostream>
#include <iomanip>
#include <map>
#include <random>
int main()
{
std::random_device rd;
std::mt19937 gen(rd());
std::discrete_distribution<> d({40, 10, 10, 40});
std::map<int, int> map;
for(int n=0; n<10000; ++n) {
++map[d(gen)];
}
for(const auto& [num, count] : map) {
std::cout << num << " generated " << std::setw(4) << count << " times\n";
}
}
Besides correct and simple other answer I can suggest my own version which explicitly does all math computation from scratch. For educational purpose only.
Try it online!
#include <cstdint>
#include <vector>
#include <random>
#include <iostream>
#include <iomanip>
int main() {
std::vector<double> const weights = {9.0, 7.8, 1.2, 3.4, 5.6};
std::vector<double> sum = {0};
for (auto w: weights)
sum.push_back(sum.back() + w);
for (auto & s: sum)
s /= sum.back();
std::mt19937_64 rng{std::random_device{}()};
auto Gen = [&]{
auto x = double(rng()) / double(uint64_t(-1));
for (size_t i = 0; i < sum.size() - 1; ++i)
if (x < sum[i + 1])
return i;
return sum.size() - 2;
};
std::vector<size_t> counts(weights.size());
for (size_t i = 0; i < (1 << 12); ++i)
++counts[Gen()];
for (size_t i = 0; i < counts.size(); ++i)
std::cout << std::setw(2) << i << " was generated "
<< std::setw(4) << counts[i] << " times" << std::endl;
}
Console output:
0 was generated 1404 times
1 was generated 1165 times
2 was generated 166 times
3 was generated 524 times
4 was generated 837 times
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.
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;
}
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.
here is my problem: I have a 2D matrix of doubles containing data. The data is gaussian and and i need to find out which datapoints are the extrem ones. As a first estimation, values > (µ + 3 sigma) should be okay. Just to be sure whether i'm corret with doing the following:
I can add the data to the accumulator, i'm able to calculate the µ, but how can i get the f** sigma?
you can get mean and moment from accumulator:
#include <iostream>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/mean.hpp>
#include <boost/accumulators/statistics/moment.hpp>
using namespace boost::accumulators;
int main()
{
// Define an accumulator set for calculating the mean and the
// 2nd moment ...
accumulator_set<double, stats<tag::mean, tag::moment<2> > > acc;
// push in some data ...
acc(1.2);
acc(2.3);
acc(3.4);
acc(4.5);
// Display the results ...
std::cout << "Mean: " << mean(acc) << std::endl;
std::cout << "Moment: " << accumulators::moment<2>(acc) << std::endl;
return 0;
}
However in the boost docs we read that this is raw moment (not central):
Calculates the N-th moment of the samples, which is defined as the sum
of the N-th power of the samples over the count of samples.
so you need to adjust this and here is how to do it (you need sqrt of second central moment, mi_2).
http://en.wikipedia.org/wiki/Moment_(mathematics)