2011-01-24 3 views
8

Я хотел бы сбросить случайные последовательности, используя разные семенные числа. При выполнении этого тестового кода:Установка начального толчка :: random

boost::mt19937 gener(1); 
boost::normal_distribution<> normal(0,1); 
boost::variate_generator<boost::mt19937&,boost::normal_distribution<> > rng(gener, normal); 
cout << rng() << endl; 
cout << rng() << endl; 
cout << rng() << endl; 
gener.seed(2); 
cout << rng() << endl; 
cout << rng() << endl; 
gener.seed(1); 
cout << rng() << endl; 
gener.seed(2); 
cout << rng() << endl; 
gener.seed(3); 
cout << rng() << endl; 

Я получаю следующий вывод:

# seed(1) via constructor 
-2.971829031 
1.706951063 
-0.430498971 
# seed(2) 
-2.282022417 
-0.5887503675 
# seed(1) 
0.2504171986 
# seed(2) 
-0.5887503675 
# seed(3) 
0.2504171986 

Очевидно, что я делаю что-то очень неправильно. Как я могу решить эту проблему?

ответ

14

После Джим, Алан и Игорь предложения внесли некоторые изменения в коде: rng.engine().seed() вместо gener.seed() и называется rng.distribution().reset() после вызова rng.engine().seed() и он работал как шарм.

Большое спасибо!

+3

Рад, что все получилось! Кстати, вам разрешено (и поощряется) принять ваш собственный ответ, особенно если для решения вашей проблемы потребовалось сочетание нескольких идей. –

1

Я считаю, что boost::variate_generator<> делает копию вашего объекта boost::mt19937 gener. Итак, когда вы перегружаете свою копию gener, она не влияет на объект rng, который уже создан . Построение нового объекта rng при каждом повторном подаче должно дать вам поведение, которое вы хотите (отказ от ответственности: не проверен!)

+0

Я считаю, что пересев оказывает некоторое влияние на ГСЧ, потому что я получаю повторяющиеся значения -0.5887503675 и 0.2504171986. Но, к сожалению, совсем не то, чего я ожидал бы. –

+0

Замечательно, что проблема решена, но могу ли я спросить, почему 'boost :: variate_generator <>' делает копию 'gener' в этом случае? Я думаю, что OP передал ссылку при написании 'boost :: variate_generator >', я ничего не пропустил? ... – Vokram

5

Вызвать normal.reset() после вызова функции gener.seed(). Это указано для обеспечения того, что выход нормали не будет зависеть от любого предыдущего выхода из генератора.

(распределение, вероятно, кэширование какое-то состояние, что вам нужно очистить.)

+0

Да, это похоже на проблему кэширования. Я сделал так, как вы предлагали, но я все равно получаю те же результаты ... –

+2

Обычно распределенные RNG используют [Преобразование Box-Muller] (http://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform) который генерирует случайные числа в парах (см. [Примеры числовых рецептов] (http://dimacs.rutgers.edu/~graham/code.html)) – Mike

1

Отлично, что проблема решена! Но я думаю, я просто понял, почему метод Алана не будет работать ...

При написании boost::variate_generator<boost::mt19937&,boost::normal_distribution<> > rng(gener, normal), вы не создали еще одну копию gener, потому что это вызов по ссылке, но сделал создать еще одну копию normal с variate_generate.

Таким образом, вместо normal.reset, который только сбрасывает оригинал normal, вы должны использовать rng.distribution().reset(). Но вы можете просто оставить gener.seed(), который, как я подозреваю, будет иметь такой же эффект, как rng.engine().seed().

Я тестировал его в своем коде, и он работал, как ожидалось.

Ну, на всякий случай кто-то будет все равно :)

Смежные вопросы