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

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

Подпотоки

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

Субпотоки обеспечивают быстрый и легкий способ гарантировать, что вы получаете различные результаты от одного и того же кода в разное время. Как использовать 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

Субпотоки полезны при последовательных расчетах. Substreams может воссоздать все или часть симуляции, вернувшись к определенной контрольной точке в потоке. Для примера можно вернуться к 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Мультипликативный конгруенциальный генераторНет231-2
mlfg6331_64Мультипликативный отставший генератор ФибоначчиДа2124 (251 потоки длиной 272)
mrg32k3aОбъединенный множественный рекурсивный генераторДа2191 (263 потоки длиной 2127)
philox4x32_10Генератор Philox 4x32 с 10 патронамиДа2193 (264 потоки длиной 2129)
threefry4x64_20Трехфазный генератор 4x64 с 20 патронамиДа2514 (2256 потоки длиной 2258)
shr3congГенератор сдвигового регистра, суммированный линейным конгруэнтным генераторомНет264
swb2712Измененное вычитание с генератором заимствованийНет21492

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

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

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

mt19937ar

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

Примечание

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

dsfmt19937

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

mcg16807

32-битный мультипликативный конгруенциальный генератор, как описано в [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 потоки - это алгоритм ziggurat [7], но со mlfg6331_64 ниже генератора.

mrg32k3a

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

philox4x32_10

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

threefry4x64_20

Генератор 4x64 с 20 патронами, как описано в [15]. Этот генератор является некриптографической адаптацией блочного шифра Threefish от Skein Hash Function. Он имеет период 2514 (2256 потоки длиной 2258).

shr3cong

Генератор SHR3 сдвигового регистра Марсальи суммирован линейным конгруенциальным генератором с умножителем a=69069, addend 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 потоки являются более ранней формой алгоритма ziggurat [9], но со shr3cong ниже генератора. Этот генератор идентичен тому, который используется randn функция, начиная с MATLAB Version 5, активируется с помощью randn('state',s).

Примечание

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

swb2712

Модифицированный генератор вычитания с заимствованием, как описано в [8]. Этот генератор похож на аддитивный отставший генератор Фибоначчи с лагами 27 и 12, но он модифицирован, чтобы иметь намного более длительный период приблизительно 21492. Генератор работает нативно с двойной точностью, чтобы создать значения U (0,1), и все значения в открытом интервале (0, 1) возможны. randn алгоритм, используемый по умолчанию для swb2712 потоки - это алгоритм ziggurat [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 значение свойства установлено равным true. Проверяйте, что эти 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

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

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

The 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

rand, randi, randn, и 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. Non-Uniform Random Variate Generation, Springer-Verlag, 1986.

[2] L'Ecuyer, P «. Хорошие наборы параметров для комбинированных нескольких рекурсивных генераторов случайных чисел», Operations Research, 47 (1): 159-164. 1999.

[3] L'Ecuyer, P. and S. Cи. «Реализация пакета случайных чисел с разделительными устройствами», Транзакции ACM на математическом программном обеспечении, 17: 98-111. 1991.

[4] L'Ecuyer, P. and R. Simard. «TestU01: Библиотека C для эмпирической проверки генераторов случайных чисел», ACM Transactions on Mathematical Software, 33 (4): Article 22. 2007.

[5] L'Ecuyer, P., R. Simard, E. J. Chen, and W. D. Kelton. «Объектно-ориентированный пакет случайных чисел с многими длинными потоками и субпотоками». Операции Исследования, 50 (6): 1073-1075. 2002.

[6] Марсалья, Г. «Случайные числа для C: The END?» Сообщение пользователя в sci.stat.math. 1999. Доступно онлайн в https://groups.google.com/group/sci.crypt/browse_thread/
thread/ca8682a4658a124d/
.

[7] Marsaglia G., and W. W. Tsang. Метод зиггурата для генерации случайных переменных. Журнал статистического программного обеспечения, 5: 1-7. 2000. Доступно онлайн в https://www.jstatsoft.org/v05/i08.

[8] Марсалья, Г. и А. Заман. «Новый класс генераторов случайных чисел». Анналы прикладных 1 вероятностей (3): 462-480. 1991.

[9] Marsaglia, G., and W. W. Tsang. Быстрый, легко реализованный метод дискретизации из уменьшающихся или симметричных функций унимодальной плотности. SIAM J. Sci. Stat. Comput. 5(2):349–359. 1984.

[10] Mascagni, M., and A. Srinivasan. Параметризация параллельных мультипликативных генераторов Lagged-Fibonacci. Параллельные вычисления, 30: 899-916. 2004.

[11] Matsumoto, M. and T. Nishimura. «Вихрь Мерсенна: A 623-Dimensionally Equidistributed Pseudorandom Number Generator». Транзакции ACM по моделированию и компьютерной симуляции, 8 (1): 3-30. 1998.

[12] Matsumoto, M. and M. Saito. «A PRNG Specialized in Double Precision Floating Point Numbers Using a Affine Transition». Методы Монте-Карло и Квази-Монте-Карло 2008, 10.1007/978-3-642-04107-5_38. 2009.

[13] Молер, К.Б. Числовые вычисления с MATLAB. СИАМ, 2004. Доступно онлайн в https://www.mathworks.com/moler

[14] Парк, С.К. и К.В. Миллер. Генераторы случайных чисел: хорошие Таковые трудно найти. Коммуникации ACM, 31 (10): 1192-1201. 1998.

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

См. также

|

Похожие темы