exponenta event banner

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

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

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

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

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

С помощью 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

Субпотоки полезны при последовательном вычислении. Субпотоки могут воссоздавать все или часть моделирования, возвращаясь к определенной контрольной точке в потоке. Например, можно вернуться к 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], имеет период 219937 1 и каждое значение U (0,1) создается с помощью двух 32-битных целых чисел. Возможные значения кратны 2 − 53 в интервале (0, 1). Этот генератор не поддерживает несколько потоков или субпотоков . randn алгоритм, используемый по умолчанию для mt19937ar потоки - это алгоритм зиггурата [7], но с mt19937ar генератор внизу.

Примечание

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

dsfmt19937

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

mcg16807

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

Примечание

Этот генератор идентичен генератору, используемому начиная с MATLAB версии 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-разрядного целого числа из генератора; все возможные значения кратны 2 − 64 строго в пределах интервала (0, 1). randn алгоритм, используемый по умолчанию для mlfg6331_64 потоки - это алгоритм зиггурата [7], но с mlfg6331_64 генератор внизу.

mrg32k3a

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

philox4x32_10

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

threefry4x64_20

Генератор 4x64 с 20 патронами, как описано в [15]. Этот генератор представляет собой не криптографическую адаптацию блочного шифра Threefish из хеш-функции Скейна. Имеет период 2514 (2256 потоков длиной 2258).

shr3cong

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

Примечание

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

swb2712

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

Примечание

Этот генератор идентичен генератору, используемому rand функция, начинающаяся в MATLAB версии 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

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

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] Девройе, L. Поколение неоднородных случайных вариаций, Springer-Verlag, 1986.

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

[3] Л'Эквадер, П. и С. Коте. «Реализация пакета случайных чисел с разделительными средствами», ACM Transactions on Mathematical Software, 17: 98-111. 1991.

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

[5] Л'Эквадер, П., Р. Симард, Э. Дж. Чен и У. Д. Келтон. «Объектно-ориентированный пакет случайных чисел с множеством длинных потоков и субпотоков». Исследование операций, 50 (6): 1073-1075. 2002.

[6] Марсалья, Г. «Случайные числа для C: The END?» Публикация 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] Марсалья, Г. и А. Заман. «Новый класс генераторов случайных чисел». Анналы прикладной вероятности 1 (3): 462-480. 1991.

[9] Марсалья, Г. и В. В. Цанг. «Быстрый, легко реализуемый метод выборки из убывающих или симметричных унимодальных функций плотности». SIAM J. Sci. Stat. Comput. 5(2):349–359. 1984.

[10] Масканьи, М. и А. Шринивасан. «Параметризация параллельных мультипликативных генераторов с отставанием Фибоначчи». Параллельные вычисления, 30: 899-916. 2004.

[11] Мацумото, М., и Т. Нисимура. «Mersenne Twister: A 623-Dimensionally Equiddisted Uniform Pseudorandom Number Generator». Транзакции ACM по моделированию и компьютерному моделированию, 8 (1): 3-30. 1998.

[12] Мацумото, М. и М. Сайто. «PRNG, специализированный на двойных точных числах с плавающей запятой с использованием аффинного перехода». Методы Монте-Карло и Квази-Монте-Карло 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] Лосось, Дж. К., М. А. Мораес, Р. О. Дрор и Д. Э. Шоу. «Параллельные случайные числа: так легко, как 1, 2, 3». В трудах Международной конференции по высокопроизводительным вычислениям, сетям, хранению и анализу (SC11). Нью-Йорк, Нью-Йорк: ACM, 2011.

См. также

|

Связанные темы