Создание и управление потоком случайных чисел

RandStream класс позволяет вам создавать поток случайных чисел. Это полезно по нескольким причинам:

  • Можно сгенерировать случайные значения, не влияя на состояние глобального потока.

  • Можно разделить источники случайности в симуляции.

  • Можно использовать генератор, который сконфигурирован по-другому, чем одно использование MATLAB при запуске.

С a RandStream объект, можно создать собственный поток, установить перезаписываемые свойства и использовать поток, чтобы сгенерировать случайные числа. Можно управлять потоком, вы создаете тот же способ, которым вы управляете глобальным потоком. Можно даже заменить глобальный поток на поток, который вы создаете.

Чтобы создать поток, используйте RandStream функция.

myStream = RandStream('mlfg6331_64');
rand(myStream,1,5)
ans =
    0.6986    0.7413    0.4239    0.6914    0.7255

Случайный поток myStream действия отдельно от глобального потока. Если вы вызываете rand, randn, randi, и randperm функции с myStream в качестве первого аргумента они чертят от потока, который вы создали. Если вы вызываете rand, randn, randi, и randperm без myStream, они чертят от глобального потока.

Можно сделать myStream глобальный поток с помощью RandStream.setGlobalStream метод.

RandStream.setGlobalStream(myStream)
RandStream.getGlobalStream
ans = 

mlfg6331_64 random stream (current global stream)
             Seed: 0
  NormalTransform: Ziggurat
RandStream.getGlobalStream == myStream
ans =
     1

Подпотоки

Можно использовать подпотоки, чтобы получить различные результаты, которые статистически независимы от потока. В отличие от seed, где местоположения вдоль последовательности случайных чисел не точно известны, известен интервал между подпотоками, таким образом, любой шанс перекрытия может быть устранен. Короче говоря, подпотоки являются более управляемым способом сделать многое из того же самого, для которого традиционно использовались seed. Подпотоки являются также более легким решением, чем параллельные потоки.

Подпотоки обеспечивают быстрый и простой способ гарантировать, что вы получаете различные результаты того же кода в разное время. Использовать Substream свойство RandStream возразите, создайте поток с помощью генератора, который поддерживает подпотоки. Для списка алгоритмов генератора, которые поддерживают подпотоки и их свойства, см. таблицу в следующем разделе. Например, сгенерируйте несколько случайных чисел в цикле.

myStream = RandStream('mlfg6331_64');
RandStream.setGlobalStream(myStream)
for i = 1:5
    myStream.Substream = i;
    z = rand(1,i)
end
z =
    0.6986

z =
    0.9230    0.2489

z =
    0.0261    0.2530    0.0737

z =
    0.3220    0.7405    0.1983    0.1052

z =
    0.2067    0.2417    0.9777    0.5970    0.4187

В другом цикле можно сгенерировать случайные значения, которые независимы от первого набора 5 итераций.

for i = 6:10
    myStream.Substream = i;
    z = rand(1,11-i)
end
z =
    0.2650    0.8229    0.2479    0.0247    0.4581

z =
    0.3963    0.7445    0.7734    0.9113

z =
    0.2758    0.3662    0.7979

z =
    0.6814    0.5150

z =
    0.5247

Подпотоки полезны в последовательном расчете. Подпотоки могут воссоздать все или часть симуляции путем возврата к конкретной контрольной точке в потоке. Например, можно возвратиться к 6-му подпотоку в цикле. Результат содержит те же значения как 6-й выход выше.

myStream.Substream = 6;
z = rand(1,5)
z =
    0.2650    0.8229    0.2479    0.0247    0.4581

Выбор генератора случайных чисел

MATLAB предлагает несколько опций алгоритма генератора. Таблица суммирует ключевые свойства доступных алгоритмов генератора, и ключевые слова раньше создавали их. Чтобы возвратить список всех доступных алгоритмов генератора, используйте RandStream.list метод.

Ключевое словоГенераторНесколько передают потоком и подпотоковая поддержкаАппроксимированный период в полной точности
mt19937arВихрь Мерсенна (используемый потоком по умолчанию при запуске MATLAB)Нет219937-1
dsfmt19937SIMD-ориентированный быстрый Вихрь Мерсенна Нет219937-1
mcg16807Мультипликативный congruential генераторНет231-2
mlfg6331_64Мультипликативный изолированный генератор ФибоначчиДа2124 (251 поток длины 272)
mrg32k3aОбъединенный несколько рекурсивный генераторДа2191 (263 потока длины 2127)
philox4x32_10Philox 4x32 генератор с 10 раундамиДа2193 (264 потока длины 2129)
threefry4x64_20Threefry 4x64 генератор с 20 раундамиДа2514 (2 256 потоков длины 2258)
shr3congГенератор сдвигового регистра суммирован с линейным congruential генераторомНет264
swb2712Измененный вычитают с, одалживают генераторНет21492

Генераторы mcg16807, shr3cong, и swb2712 предусмотрите назад совместимость с более ранними версиями MATLAB. mt19937ar и dsfmt19937 спроектированы, в основном, для последовательных приложений. Остающиеся генераторы оказывают явную поддержку для параллельной генерации случайных чисел.

В зависимости от приложения некоторые генераторы могут быть более быстрыми или возвращаемыми значениями с большей точностью. Все генераторы псевдослучайного числа основаны на детерминированных алгоритмах, и все генераторы проходят достаточно определенный статистический тест для случайности. Один способ проверять результаты симуляции Монте-Карло состоит в том, чтобы повторно выполнить симуляцию с двумя или больше различными алгоритмами генератора, и выбор генераторов в MATLAB предоставляет вам средние значения, чтобы сделать это. Несмотря на то, что маловероятно, что ваши результаты будут отличаться больше, чем Монте-Карло, производящий ошибку при использовании различных генераторов, существуют примеры в литературе, где этот вид валидации поднял дефекты в конкретном алгоритме генератора. (См. [13] для примера.)

Алгоритмы генератора

mt19937ar

У Вихря Мерсенна, как описано в [11], есть период 2199371 и каждый U (0,1) значение создается с помощью двух 32-битных целых чисел. Возможные значения являются множителями 253 в интервале (0, 1). Этот генератор не поддерживает несколько потоков или подпотоков. randn алгоритм, используемый по умолчанию для mt19937ar потоки являются алгоритмом зиггурата [7], но с mt19937ar генератор внизу.

Примечание

Этот генератор идентичен тому, используемому rand функция, начинающаяся в MATLAB Version 7, активированном rand('twister',s).

dsfmt19937

Двойная точность, SIMD-ориентированная на Быстрый Вихрь Мерсенна, как описано в [12], является быстрым внедрением Алгоритма Вихря Мерсенна. Период 2199371 и возможные значения являются множителями 252 в интервале (0, 1). Генератор производит значения двойной точности в [1, 2), исходно, которые преобразовываются, чтобы создать U (0,1) значения. Этот генератор не поддерживает несколько потоков или подпотоков.

mcg16807

32-битный мультипликативный congruential генератор, как описано в [14], со множителем a=75, по модулю m=2311. Этот генератор имеет период 2312 и не поддерживает несколько потоков или подпотоков. Каждый U (0,1) значение создается с помощью одного 32-битного целого числа из генератора; возможные значения являются всеми множителями (2311)1 строго в интервале (0, 1). Для mcg16807 потоки, алгоритм по умолчанию, используемый randn полярный алгоритм (описанный в [1]).

Примечание

Этот генератор идентичен тому, используемому, начинаясь в MATLAB Version 4 обоими rand и randn функции, активированное использование rand('seed',s) или randn('seed',s).

mlfg6331_64

64-битный мультипликативный изолированный генератор Фибоначчи, как описано в [10], с задержками l=63, k=31. Этот генератор похож на MLFG, реализованный в пакете SPRNG. Это имеет период приблизительно 2124. Это поддерживает до 261 параллельные потоки, через параметризацию, и 251 подпотоки каждая длина 272. Каждый U (0,1) значение создается с помощью одного 64-битного целого числа из генератора; возможные значения являются всеми множителями 264 строго в интервале (0, 1). randn алгоритм, используемый по умолчанию для mlfg6331_64 потоки являются алгоритмом зиггурата [7], но с mlfg6331_64 генератор внизу.

mrg32k3a

32-битное объединило несколько рекурсивный генератор, как описано в [2]. Этот генератор похож на CMRG, реализованный в пакете RngStreams в C. Это имеет период 2191 и поддержки до 263 параллельные потоки посредством разделения последовательности, каждой длины 2127. Это также поддерживает 251 подпотоки, каждая длина 276. Каждый U (0,1) значение создается с помощью двух 32-битных целых чисел из генератора; возможные значения являются множителями 253 строго в интервале (0, 1). randn алгоритм, используемый по умолчанию для mrg32k3a потоки являются алгоритмом зиггурата [7], но с mrg32k3a генератор внизу.

philox4x32_10

4x32 генератор с 10 раундами как описано в [15]. Этот генератор использует сеть Feistel и целочисленное умножение. Генератор специально предназначен для высокой производительности в очень параллельных системах, таких как графические процессоры. Это имеет период 2 193 (264 потока длины 2129).

threefry4x64_20

4x64 генератор с 20 раундами как описано в [15]. Этот генератор является некриптографической адаптацией блочного шифра Threefish от Хеш-функции Мотка пряжи. Это имеет период 2 514 (2 256 потоков длины 2258).

shr3cong

Генератор сдвигового регистра Марсэглии SHR3 суммирован с линейным congruential генератором со множителем a=69069, слагаемое b=1234567, и модуль 232. SHR3 является генератором с 3 сдвиговыми регистрами, заданным как u=u(I+L13)(I+R17)(I+L5), где I единичный оператор, L левый оператор смещения, и R является оператором сдвига вправо. Объединенный генератор (часть SHR3 описана в [7]) имеет период приблизительно 264. Этот генератор не поддерживает несколько потоков или подпотоков. Каждый U (0,1) значение создается с помощью одного 32-битного целого числа из генератора; возможные значения являются всеми множителями 232 строго в интервале (0, 1). randn алгоритм, используемый по умолчанию для shr3cong потоки являются более ранней формой алгоритма зиггурата [9], но с shr3cong генератор внизу. Этот генератор идентичен тому, используемому randn функция, начинающаяся в MATLAB Version 5, активированное использование randn('state',s).

Примечание

Генератор SHR3, используемый в [6] (1999), отличается от того, используемого в [7] (2000). MATLAB использует новую версию генератора, представленного в [7].

swb2712

Модифицированный генератор Subtract-Borrow, как описано в [8]. Этот генератор похож на изолированный генератор Фибоначчи дополнения с задержками 27 и 12, но он изменяется, чтобы иметь намного более длинный период приблизительно 21492. Генератор работает исходно в двойной точности, чтобы создать U (0,1) значения, и все значения в открытом интервале (0, 1) возможны. randn алгоритм, используемый по умолчанию для swb2712 потоки являются алгоритмом зиггурата [7], но с swb2712 генератор внизу.

Примечание

Этот генератор идентичен тому, используемому rand функция, начинающаяся в MATLAB Version 5, активированное использование rand('state',s).

Алгоритмы преобразования

Inversion

Вычисляет нормальную случайную варьируемую величину путем применения стандартной нормальной обратной кумулятивной функции распределения к универсальной случайной варьируемой величине. Точно одно универсальное значение используется на нормальное значение.

Polar

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

Ziggurat

Алгоритм зиггурата, как описано в [7]. Приблизительно 2,02 универсальных значения используются на нормальное значение в среднем.

Конфигурирование потока

Поток случайных чисел s имеет свойства, которые управляют его поведением. Чтобы получить доступ или изменить свойство, используйте синтаксис p = s.Property и s.Property = p.

Например, можно сконфигурировать алгоритм преобразования, чтобы сгенерировать нормально распределенные псевдослучайные значения при использовании randn. Сгенерируйте нормально распределенные псевдослучайные значения с помощью Ziggurat по умолчанию алгоритм преобразования.

s1 = RandStream('mt19937ar');
s1.NormalTransform
ans = 'Ziggurat'
r1 = randn(s1,1,10);

Сконфигурируйте поток, чтобы использовать Polar алгоритм преобразования, чтобы сгенерировать нормально распределенные псевдослучайные значения.

s1.NormalTransform = 'Polar'
s1 =
mt19937ar random stream
             Seed: 0
  NormalTransform: Polar
r2 = randn(s1,1,10);

При генерации случайных чисел с использованием равномерного распределения rand, можно также сконфигурировать поток, чтобы сгенерировать прямо противоположные псевдослучайные значения, то есть, обычные значения, вычтенные от 1 для универсальных значений.

Создайте 6 случайных чисел с равномерным распределением от потока s.

s2 = RandStream('mt19937ar');
r1 = rand(s2,1,6)
r1 =
    0.8147    0.9058    0.1270    0.9134    0.6324    0.0975

Восстановите начальное состояние потока. Создайте еще 6 случайных чисел с Antithetic набор свойств к истине. Проверяйте, что эти 6 случайных чисел равны ранее сгенерированным случайным числам, вычтенным от 1.

reset(s2)
s2.Antithetic = true;
r2 = rand(s2,1,6)
r2 =
    0.1853    0.0942    0.8730    0.0866    0.3676    0.9025
isequal(r1,1 - r2)
ans =
   1

Вместо того, чтобы установить свойства потока один за другим, можно сохранить и восстановить все свойства потока s при помощи A = get(s) и set(s,A), соответственно. Например, сконфигурируйте все свойства потока s2 совпадать с потоком s1.

A = get(s1)
A =
               Type: 'mt19937ar'
         NumStreams: 1
        StreamIndex: 1
          Substream: 1
               Seed: 0
              State: [625x1 uint32]
    NormalTransform: 'Polar'
         Antithetic: 0
      FullPrecision: 1
set(s2,A)
               Type: 'mt19937ar'
         NumStreams: 1
        StreamIndex: 1
          Substream: 1
               Seed: 0
              State: [625x1 uint32]
    NormalTransform: 'Polar'
         Antithetic: 0
      FullPrecision: 1

get и set функции позволяют вам сохранить и восстановить целую настройку потока так, чтобы результаты были точно восстанавливаемы позже.

Восстановите состояние генератора случайных чисел, чтобы воспроизвести Выход

State свойство является внутренним состоянием генератора случайных чисел. Можно сохранить состояние глобального потока в определенный момент в симуляции при генерации случайных чисел, чтобы воспроизвести результаты позже.

Используйте RandStream.getGlobalStream возвратить указатель на глобальный поток, то есть, текущий глобальный поток что rand генерирует случайные числа от. Сохраните состояние глобального потока.

globalStream = RandStream.getGlobalStream;
myState = globalStream.State;

Используя myState, можно восстановить состояние globalStream и воспроизведите предыдущие результаты.

A = rand(1,100);
globalStream.State = myState;
B = rand(1,100);
isequal(A,B)
ans = logical
   1

randrandirandn, и randperm получите доступ к глобальному потоку. Поскольку все эти функции получают доступ к тому же базовому потоку, вызову, каждый влияет на значения, произведенные другими в последующих вызовах.

globalStream.State = myState;
A = rand(1,100);
globalStream.State = myState;
C = randi(100);
B = rand(1,100);
isequal(A,B)
ans = logical
   0

Можно также сбросить поток к его начальным установкам с помощью reset функция.

reset(globalStream)
A = rand(1,100);
reset(globalStream)
B = rand(1,100);
isequal(A,B)
ans = logical
   1

Ссылки

[1] Devroye, L. Неоднородная генерация случайных переменных, Springer-Verlag, 1986.

[2] L’Ecuyer, P. “Хорошие наборы параметров для объединенного несколько рекурсивных генераторов случайных чисел”, исследование операций, 47 (1): 159–164. 1999.

[3] L'Ecuyer, P. и С. Куте. “Реализовывая пакет случайных чисел с разделяющими средствами”, транзакции ACM на математическом программном обеспечении, 17: 98–111. 1991.

[4] L'Ecuyer, P. и Р. Симард. “TestU01: библиотека C для эмпирического тестирования генераторов случайных чисел”, транзакции ACM на математическом программном обеспечении, 33 (4): статья 22. 2007.

[5] L'Ecuyer, P., Р. Симард, Э. Дж. Чен и В. Д. Келтон. “Возраженный - ориентированный пакет случайных чисел со многими длинными потоками и подпотоками”. Исследование операций, 50 (6):1073–1075. 2002.

[6] Marsaglia, G. “Случайные числа для C: ЗАКАНЧИВАНИЕ?” Регистрация Usenet к sci.stat.math. 1999. Доступный онлайн в https://groups.google.com/group/sci.crypt/browse_thread/
thread/ca8682a4658a124d/
.

[7] Марсэглия Г. и В. В. Цанг. “Метод зиггурата для генерации случайных переменных”. Журнал Статистического программного обеспечения, 5:1–7. 2000. Доступный онлайн в https://www.jstatsoft.org/v05/i08.

[8] Marsaglia, G. и A. Заман. “Новый класс генераторов случайных чисел”. Летопись Прикладной Вероятности 1 (3):462–480. 1991.

[9] Marsaglia, G. и В. В. Цанг. “Быстрый, легко реализованный метод для выборки от уменьшения или симметричных одномодовых функций плотности”. SIAM J. Научный Закон Comput. 5 (2):349–359. 1984.

[10] Масканьи, M. и А. Сринивасан. “Параметрируя параллельные мультипликативные изолированные-Fibonacci генераторы”. Параллельные вычисления, 30: 899–916. 2004.

[11] Мацумото, M. и Т. Нисимура. “Вихрь Мерсенна: 623 - размерностно универсальный генератор псевдослучайного числа Equidistributed”. Транзакции ACM при моделировании и компьютерном моделировании, 8 (1):3–30. 1998.

[12] Мацумото, M. и М. Саито. “PRNG, специализированный в числах двойной точности с плавающей точкой Используя аффинный переход”. Методы Монте-Карло и квазиметоды Монте-Карло 2008, 10.1007/978-3-642-04107-5_38. 2009.

[13] Moler, К.Б. Нумерикэл Компьютинг с MATLAB. SIAM, 2004. Доступный онлайн в https://www.mathworks.com/moler

[14] Припаркуйтесь, S.K., и К.В. Миллер. “Генераторы случайных чисел: хорошие единицы трудно найти”. Коммуникации ACM, 31 (10):1192–1201. 1998.

[15] Лосось, J. K. М. А. Мораес, Р. О. Дрор и Д. Э. Шоу. "Параллельные случайные числа: столь же легкий как 1, 2, 3". В продолжениях международной конференции для высокоэффективного вычисления, организации сети, устройства хранения данных и анализа (SC11). Нью-Йорк, Нью-Йорк: ACM, 2011.

Смотрите также

|

Похожие темы