简体   繁体   中英

Random engine state and multiple deterministic independent random sequences

The C++ TR1 random number generation scheme has improved the old C runtime library in terms of keeping a separate state for random engines in different threads, or for independent random sequences. The old library has a global state machine, and this is usually bad.

However, when implementing an algorithm that requires deterministic random sequences, I find it annoying to have to pass the engine down to any method that should be drawing numbers from such a sequence. From a design perspective, the code that initializes the random seed doesn't need to know which methods down the stack are using random numbers. Yet those inner methods cannot initialize their own random engines, because:

  1. they lack the knowledge to create a unique reproducible seed
  2. memory requirements prevent keeping a separate state for the many downstream clients

To clarify, the downstream methods do not need to draw numbers from the same sequence as the main method, but they do need to be independent and reproducible in different runs.

Any idea on how to solve this conundrum elegantly?

EDIT

Some code to clarify the situation

typedef std::mt19937 RandEng;

class PossibleRandomConsumer;

class RandomProvider {
public:
    void foo() {
        std::uniform_int<> uni;
        uni(eng, 17); // using the random engine myself
        std::for_each(children.begin(), children.end(), [](PossibleRandomConsumer& child) { 
            // may or may not need a random number. if it does, it has to be different than from other children, and from other providers
            child.DoSomething(eng); 
        });
    }
private:
    RandEng eng; // unique seed per RandomProvider
    std::array<PossibleRandomConsumer,10000> children; // lots of these...
};

Not an easy question without knowing some detail about your architecture. So this is just a try:
How about passing down references to an interface that knows how to provide random numbers. This interface may just have one function that returns an amount of random numbers if asked. In this way you can hide the implementation details from the downstream functions (methods) and passing constant references around is nearly for free. You can even decide at top level where those random numbers come from (file, random number generator, your room temperature, ...).

class RandomNumberProvider {
    public:  
        typedef std::vector<int> RandomArray;  
        virtual RandomArray Generate(unsigned numNumbers) = 0;
};  

void Consumer(const RandomNumberProvider& rndProvider) {  
    RandomNumberProvider::RandomArray rndNumber;   
    rndNumber = rndProvider(10); // get a sequence of 10 random numbers  
    ...
}  

something like this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM