Proper design of RNG helper in C++ - c++

In my project, I want to have some kind of helper functions/class to work with random number generator. Main topic of the project is Monte Carlo simulations so I will be using it very often and in many places. Hence, I'm looking for ideas of designing such wrapper on C++ random library so I can randomize e.g. probability by calling simple function generateProbability(). I've came with 2 ideas, one is just class with needed functions. This solution looks nice, however I would have to create separate RNG objects inside every file/place what it's needed. The other solution is just creating separate namespace with global variables of pseudo-random engine, distributions and helper functions. I've prepared example code for both cases:
#pragma once
#include <random>
namespace rng {
std::mt19937_64 rng_engine(std::random_device{}());
std::uniform_int_distribution<uint8_t> zeroToNineDistrib(0, 9);
inline auto generateNumber() { return zeroToNineDistrib(rng_engine); }
} // namespace rng
class RNG {
public:
RNG() : rng_engine(std::random_device{}()), zeroToNineDistrib(0, 9){};
~RNG() = default;
auto generateNumber() { return zeroToNineDistrib(rng_engine); }
private:
std::mt19937_64 rng_engine;
std::uniform_int_distribution<uint8_t> zeroToNineDistrib;
};
What do you think about these solutions? Which one is 'better' in a way that it's more professional and considered as 'cleaner'? Or maybe you have other ideas on how to do that better?
I encourage you to discussion because I can see both pros and cons of either solution and can't decide which one should I pick.

Related

pass C++ random number distribution to a function

I have looked for similar questions but haven't found them. I want to generate normally distributed random numbers. I used to code C and some C++98 but am now trying to go back and learn C++11.
I have a function to return a seeded RNG
auto seeded_rng () {
.... //do seeding.
std::default_random_engine Eng(/*seeds*/);
return Eng;
}
In my main function I bind the RNG to say a gaussian distribution
auto binded = std::bind(std::normal_distribution<double>{0,1.0},seeded_rng);
This function works fine. I can call "binded()" directly in main and it generates the numbers
I want to have a simulation object that needs random numbers to be created. My question related to how to pass in the "RNG_PART" below.
class sim
{
public:
sim( RNG_PART & rng, int_number_of sims ){ /* Do whatever */}
}
So if in main, I then want to create a simulation object
sim A(binded, 100);
it complains.
I tried declaring
sim::sim(std::default_random_engine &rng, int number_of_sims){}
but it is complaining. What type should I use to pass in the "binded" distribution to the constructor? Or am I going about this completely incorrectly. Should I just declare the RNG engine globally? I'd prefer not to do that.
Apologies if this is very basic!
The type of the argument to sim is not matching the type of binded. When you create binded, you avoid the issue by using auto instead of declaring the type, but you're going to need it later. How about the following in class sim instead of trying to figure out the type ahead of time. This also allows you to change the RNG or the random distribution without changing the sim class:
template<typename T>
class sim
{
public:
sim(T& rng, int_number_of sims ){ /* Do whatever */}
Note that the template definition must be visible to the place you use it, so you can't put it into a cpp file unless the only code that uses it is in that file. Typically, the template definition is in the same h file as where it was declared.
Then, you'd create sim as:
sim<decltype(binded)> A(binded,100);
the decltype(binded) is a way to tell the sim function template the type of binded.
Since binded can return different types depending upon the chosen random number distribution, obtaining the return type in the sim class template could be done with
using rnd_return_type = typename std::result_of<T()>::type; //in C++11, C++14
or
using rnd_return_type = std::invoke_result_t<T>; //C++17 and later
std::result_of is deprecated in C++17 and will be removed in C++20

Incorrectly seeding Mersenne Twister via constructor

What is wrong with my constructor? Every time I call a function (about once every five seconds) that is supposed to generate random numbers, it generates the same numbers. Each call instantiates one of these objects below. I thought I was seeding m_gen randomly with the output of m_rd's operator() call.
Could I pass in the result of m_rd() to the constructor? What would the signature be? Shuffler(std::random device& rd)? But then that would be more difficult for the user.
Edit:
Actually, if it's possible, I would prefer a solution where you don't need to pass anything into the constructor.
shuffler.h
#include <random>
class Shuffler
{
private:
std::random_device m_rd;
std::mt19937 m_gen;
public:
//! The default constructor.
Shuffler();
};
shuffler.cpp
#include "shuffler.h"
Shuffler::Shuffler() : m_gen(m_rd())
{
}
std::random_device is usually fine for this sort of thing, but it may not be on every platform. While most platforms' standard libraries implement it in terms of some underlying OS random functionality (i.e. /dev/urandom on Linux or CryptGenRandom on Windows), it is not required to do so by the C++ standard. On some platforms, high-quality random generators simply may not be available, and the standard allows std::random_device to be a simple, statically seeded PRNG. If it is, every std::random_device object will generate the same sequence of numbers.
For those reasons, you may want to go back to simple time-seeding. The standard
provides std::chrono::high_resolution_clock:
class Shuffler
{
private:
std::mt19937 m_gen;
public:
Shuffler()
: m_gen{static_cast<std::uint32_t>(
std::chrono::high_resolution_clock::now().time_since_epoch().count()
)}
{}
};
std::chrono::high_resolution_clock usually has a resolution of nanoseconds or hundreds of nanoseconds. This is high enough that two PRNGs seeded by calls to the high_resolution_clock are very unlikely to end up using the same seed. This is also not guaranteed though. For example, std::chrono::high_resolution_clock only has microsecond resolution on macOS, which may or may not be good enough for your purposes.
In the end, neither method is perfect. You may want to combine the two using std::seed_seq:
std::seed_seq make_seeds() {
thread_local std::random_device rd;
return {{
static_cast<std::uint32_t>(std::chrono::high_resolution_clock::now().time_since_epoch().count()),
rd()
}};
}
// Cast away rvalue-ness because the standard random generators need
// an lvalue reference to their seed_seq for some strange reason
template <typename T>
T& identity(T&& t) { return t; }
class Shuffler
{
private:
std::mt19937 m_gen;
public:
Shuffler()
: m_gen{identity(make_seeds())}
{}
};
As you can see, this is getting far from simple, and it's still not perfect. See these blog posts for more information about seeding and random number generators then you ever thought you wanted.
As in this example, you have to seed it and random_device doesn't seem to do the trick*:
// do this once somewhere
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
class Shuffler
{
private:
std::mt19937 m_gen;
public:
Shuffler() : m_gen(seed) {}
};
*As stated here, random_device is not a Seed Sequence!

Factory class driven by a map for determining the object type

I'm having a brain freeze and can't figure out how to best solve this issue. I'm creating objects from my factory class by calling
CreateEnvironment<T>(ARGS);
Now lets say that i want to save alot of class-types into a map and iterate through the map and call the method at runtime like this:
ITERATION:
CrateEnvironment<(*it)>(world);
(*it) should be the class type, which could be FOO or BAR for example. How do i achieve this instead of having alot of if statements?
Best regards
For each class you could have a function that would serve as generator and create a new object and return a pointer to it (or better, a shared_ptr).
In your container you could then store a the generator function pointers.
Step by step explanations:
Suppose you have these classes to populate your world:
struct GO { virtual void say_hello()=0; }; // Game Object
struct A:GO { void say_hello() { cout<<"I'm a werewolf\n";} };
struct B:GO { void say_hello() { cout<<"I'm a soldier\n";}};
You can then define a generic GO generator:
template <class T>
shared_ptr<GO> generator() {
return make_shared<T>();
};
This would serve as subsititue for your "type" container (for the simplicity of the example I've used a vector, but you could easily opt for a map):
typedef shared_ptr<GO> (*gen_fn)();
vector <gen_fn> generators{generator<A>, generator<B>};
You could then populate your universe like this, without any if:
vector<shared_ptr<GO>> universe;
default_random_engine generator;
uniform_int_distribution<int> distribution(0,generators.size()-1);
for (int i=0; i<10; i++) {
int mytype = distribution(generator);
universe.push_back(generators[mytype]());
}
for (auto x: universe)
x->say_hello();
And here an online demo.
Statistical remark: As the distribution is uniform, you will have a high probability of having the roughly the same proportion of each type of object. If you'd like to have different distribution, you could add several times generators of the same type. For example, with generators{generator<A>, generator<B>, generator<B>}; you'd have around 66% of soldiers and 33% of werewolves.

How to std::bind() to create a data member?

I'm generating random values with C++11 nice new generators and distributions. In a function it works like a charm and looks like this:
void foo() {
mt19937 generator;
uniform_int_distribution<unsigned> distribution;
auto dice = bind(distribution, generator);
// dice() will now give a random unsigned value
}
But how can I put all three objects in a class as data members? I can simply write generator and distribution as data members, but how do I make dice a data member without knowing (or wanting to know) its exact type? Suprisingly this
class X {
mt19937 generator;
uniform_int_distribution<unsigned> distribution;
decltype(bind(distribution, generator)) dice;
};
yields the error error C2660: 'bind' : function does not take 2 arguments in Visual Studio 2013.
You could always gasp write a function instead of using a lambda/bind/etc.:
class X {
mt19937 generator;
uniform_int_distribution<unsigned> distribution;
public:
auto dice() -> decltype(distribution(generator)) {
return distribution(generator);
}
// or alternatively
auto operator() () -> decltype(distribution(generator)) {
return distribution(generator);
}
};
Bonus points for parameterizing on the type of the generator and/or distribution, and for holding the generator with a std::shared_ptr so that you can make several objects with differing distributions that share the same engine. You'll eventually want a constructor to seed the generator as well - Ideally with something like std::random_device{}().
Or, the answer I think you are looking for:
class X {
mt19937 generator{std::random_device{}()};
uniform_int_distribution<unsigned> distribution{1,6};
public:
decltype(bind(std::ref(distribution), std::ref(generator))) dice{
bind(std::ref(distribution), std::ref(generator))
};
};
I'm sorry I mocked you for trying to use bind in the first place: it's actually kind of neat that you can write this class with "no code" in C++11. We need to get type-inference for class member declarations in C++17 so this could be:
class X {
auto generator = mt19937{std::random_device{}()};
auto distribution = uniform_int_distribution<unsigned>{1,6};
public:
auto dice = bind(std::ref(distribution), std::ref(generator));
};
Given that the latest Concepts Lite paper proposes using concept names anywhere in the language where auto can appear to mean "infer type, ill-formed if type doesn't model named concept," auto member declarations may not be out of the question.
It works on GCC. I’m pretty sure that’s just a compiler bug. Unfortunately this means that you have to bite the bitter pill and use one of the workarounds described in the other answers.
The result of std::bind is unspecified: this means that you cannot store its raw result without type inference. However, you can use std::function to encapsulate the result of bind:
#include <functional>
std::function<unsigned()> dice(std::bind(distribution, generator));
auto result = dice();
EDIT: As whoever said above, this is most clearly a Visual Studio issue. I can confirm that this compiles with VS2013:
#include <functional>
#include <random>
using namespace std;
class X {
mt19937 generator;
uniform_int_distribution<unsigned> distribution;
std::function<unsigned()> dice;
public:
X() : dice(bind(distribution, generator)) {}
unsigned roll() { return dice(); }
};
but changing the type of dice to decltype(bind(distribution, generator)) makes the whole thing fail with flying colors (even though it still works with clang).

Good practice for choosing an algorithm randomly with c++

Setting:
A pseudo-random pattern has to be generated. There are several ways / or algorithms availible to create different content. All algorithms will generate a list of chars (but could be anything else)... the important part is, that all of them return the same type of values, and need the same type of input arguments.
It has to be possible to call a method GetRandomPattern(), which will use a random one of the algorithms everytime it is called.
My first aproach was to put each algorithm in it's own function and select a random one of them each time GetRandompattern() is called. But I didn't come up with another way of choosing between them, than with a switch case statement which is unhandy, ugly and inflexible.
class PatternGenerator{
public:
list<char> GetRandomPattern();
private:
list<char>GeneratePatternA(foo bar);
list<char>GeneratePatternB(foo bar);
........
list<char>GeneratePatternX(foo bar);
}
What would be a good way to select a random GeneratePattern function every time the GetRandomPattern() method is called ?
Or should the whole class be designed differently ?
Thanks a lot
Create a single class for each algorithm, each one subclassing a generator class. Put instances of those objects into a list. Pick one randomly and use it!
More generically, if you start creating several alternative methods with the same signature, something's screaming "put us into sibling classes" at you :)
Update
Can't resist arguing a bit more for an object-oriented solution after the pointer-suggestion came
Imagine at some point you want to print which method created which random thing. With objects, it's easy, just add a "name" method or something. How do you want to achieve this if all you got is a pointer? (yea, create a dictionary from pointers to strings, hm...)
Imagine you find out that you got ten methods, five of which only differ by a parameter. So you write five functions "just to keep the code clean from OOP garbage"? Or won't you rather have a function which happens to be able to store some state with it (also known as an object?)
What I'm trying to say is that this is a textbook application for some OOP design. The above points are just trying to flesh that out a bit and argue that even if it works with pointers now, it's not the future-proof solution. And you shouldn't be afraid to produce code that talks to the reader (ie your future you, in four weeks or so) telling that person what it's doing
You can make an array of function pointers. This avoids having to create a whole bunch of different classes, although you still have to assign the function pointers to the elements of the array. Any way you do this, there are going to be a lot of repetitive-looking lines. In your example, it's in the GetRandomPattern method. In mine, it's in the PatternGenerator constructor.
#define FUNCTION_COUNT 24
typedef list<char>(*generatorFunc)(foo);
class PatternGenerator{
public:
PatternGenerator() {
functions[0] = &GeneratePatternA;
functions[1] = &GeneratePatternB;
...
functions[24] = &GeneratePatternX;
}
list<char> GetRandomPattern() {
foo bar = value;
int funcToUse = rand()%FUNCTION_COUNT;
functions[funcToUse](bar);
}
private:
generatorFunc functions[FUNCTION_COUNT];
}
One way to avoid switch-like coding is using Strategy design pattern. As example:
class IRandomPatternGenerator
{
public:
virtual list<int> makePattern(foo bar);
};
class ARandomPatternGenerator : public IRandomPatternGenerator
{
public:
virtual list<int> makePattern(foo bar)
{
...
}
};
class BRandomPatternGenerator : public IRandomPatternGenerator
{
public:
virtual list<int> makePattern(foo bar)
{
...
}
};
Then you can choose particular algorithm depending on runtime type of your RandomPatternGenerator instance. (As example creating list like nicolas78 suggested)
Thank you for all your great input.
I decided to go with function pointers, mainly because I didn't know them before and they seem to be very powerfull and it was a good chance to get to know them, but also because it saves me lot of lines of code.
If I'd be using Ruby / Java / C# I'd have decided for the suggested Strategy Design pattern ;-)
class PatternGenerator{
typedef list<char>(PatternGenerator::*createPatternFunctionPtr);
public:
PatternGenerator(){
Initialize();
}
GetRandomPattern(){
int randomMethod = (rand()%functionPointerVector.size());
createPatternFunctionPtr randomFunction = functionPointerVector.at( randomMethod );
list<char> pattern = (this->*randomFunction)();
return pattern;
}
private:
void Initialize(){
createPatternFunctionPtr methodA = &PatternGenerator::GeneratePatternA;
createPatternFunctionPtr methodB = &PatternGenerator::GeneratePatternB;
...
functionPointerVector.push_back( methodA );
functionPointerVector.push_back( methodB );
}
list<char>GeneratePatternA(){
...}
list<char>GeneratePatternB(){
...}
vector< createPattern > functionPointerVector;
The readability is not much worse as it would have been with the Design Pattern Solution, it's easy to add new algorithms, the pointer arithmetics are capsuled within a class, it prevents memory leaks and it's very fast and effective...