mardi 21 février 2017

Why do I have to reseed the random generator when using iterators?

My goal is to fill each element of each vector of a vector of vectors with a random value. Please consider to following code:

#include <algorithm>
#include <iostream>
#include <random>
#include <vector>


typedef std::vector<int> IntVect;
typedef std::vector<IntVect> Grid;


void fillRandom(Grid& grid, int lo, int hi);


int main(int argc, const char * argv[]) {

    Grid grid { Grid(5, IntVect (5)) };

    fillRandom(grid, 0, 10);

    for (auto& row : grid) {
        for (auto& i : row) {
            std::cout << i << " ";
        }
        std::cout << "\n";
    }
    return 0;
}
// fillRandom v1
void fillRandom(Grid& grid, int lo, int hi) {

    // Init Random engine
    std::random_device rnd_device;
    std::mt19937 generator { rnd_device() };
    std::uniform_int_distribution<int> distr(lo, hi);
    auto dice = std::bind(distr, generator);

    Grid::iterator i { grid.begin() };
    for (; i != grid.end(); ++i) {
        std::generate(i->begin(), i->end(), dice);
        generator.seed(rnd_device());              // reseed
        dice = std::bind(distr, generator);
    }
    return;
}

In fillRandom I have to reseed the generator for each element of grid. Otherwise the output will be the same for each element of grid, like:

7 5 8 1 9 
7 5 8 1 9 
7 5 8 1 9 
7 5 8 1 9 
7 5 8 1 9

. However, if I change fillRandom to:

// fillRandom v2
void fillRandom(Grid& grid, int lo, int hi) {

    // Init Random engine as above

    for (auto& row : grid)
        for (auto& i : row)
            i = dice();
    return;
}

I get the expected result without reseeding the generator for each vectorof grid.

In the second version of fillRandom dice() is called for each element of each vector, resulting in a grid filled with random values. However, the first version should do exactly the same. But it obviously does not. What's the difference here?

Why do I have to reseed the random generator for every vector when I use std::generate and an iterator? Could you please help me to understand this behaviour?




Aucun commentaire:

Enregistrer un commentaire