В C ++, почему я не могу генерировать независимые случайные целочисленные выборки, используя два случайных механизма по умолчанию - PullRequest
5 голосов
/ 26 марта 2019

Я хочу иметь независимые случайные распределения целых чисел в настраиваемом диапазоне. То, что у меня было изначально, иллюстрируется следующей программой:

#include <random>
#include <cstdio>
#include <cstdlib>
using namespace std;

int main(int argc, char* argv[])
{
    default_random_engine generator1;
    default_random_engine generator2;
    uniform_int_distribution<int> dist1(0,atoi(argv[1]));
    uniform_int_distribution<int> dist2(0,atoi(argv[2]));

    generator1.seed(0);
    generator2.seed(1);
    for (int i = 0; i < 60; i++)
        printf("(%d, %d)\n", dist1(generator1), dist2(generator2));
    return 0;
}

Получается, что всегда генерируются равные значения, когда argv [1] и argv [2] равны, и имеет менее очевидные зависимости, когда они также различны. Потому что на случай, если я использовал разные экземпляры движка и даже посеял их по-разному.

Что здесь происходит? Я заметил, что проблема исчезнет, ​​если я заменю default_random_engine на mt19937, но об этом я бы никогда не догадался. Кроме того, должен ли другой движок производить независимые сэмплы?

РЕДАКТИРОВАТЬ Я работаю над Ubuntu 16.04.2, с g ++ 7.3.0 из стандартных репозиториев.

РЕДАКТИРОВАТЬ 2 Как предположил Франсуа Андрие в комментариях, это, похоже, является особенностью конкретного генератора случайных чисел по умолчанию в моем окружении: семена 0 и 1, кажется, генерируют одинаковую последовательность случайных чисел. Все остальные комбинации генерируют кажущиеся независимыми выборки.

Ответы [ 2 ]

2 голосов
/ 26 марта 2019

libstdc ++, кажется, использует minstd_rand0 для default_random_engine.

В visual studio (и предположительно других реализациях) начальное число 0 явно преобразуется в начальное число 1.

Либо используйте другое начальное значение, либо явно выберите движок, который вы хотите использовать. Вы не можете контролировать то, что создает default_random_engine, и разные стандартные библиотеки будут выбирать генераторы с разными свойствами. Например, Visual Studio использует mt19937.

2 голосов
/ 26 марта 2019

Некоторые механизмы псевдослучайных чисел могут иметь несколько начальных чисел с коррелирующей или даже идентичной последовательностью.Это особенно верно для линейных конгруэнтных генераторов.

Чтобы избежать корреляции двигателей с различным начальным числом:

  1. Используйте более качественный двигатель, например Mersenne Twister.
  2. Избегайтеиспользование идентичных элементов в качестве начального числа (0, 1, пустая последовательность, generator.modulus, ...) для всех двигателей.
  3. Вместо использования единственного начального числа используйте начальную последовательность:

-

template< class Sseq >
void seed( Sseq& seq );
...