Регистр сдвига с обобщённой обратной связью

Материал из testwiki
Перейти к навигации Перейти к поиску

Регистр сдвига с обобщённой обратной связью (Шаблон:Lang-en) — вариант генератора псевдослучайных чисел (ГПСЧ) Таусворта, предложенный Теодором Льюисом и Шаблон:Нп5 в 1973 году.

Cхема регистра сдвига с обобщённой обратной связью

Идея алгоритма GFSR состоит в том, что основная последовательность регистра сдвига с линейной обратной связью {ak}, основанная на примитивном трёхчлене xp+xpq+1, записывается в w колонок, w<p, с разумно выбранными циклическими сдвигами. p и q — произвольные натуральные числа, такие что q<p, причём q примерно равных (p+1)/2 и p, нужно избегать из-за плохих свойств результирующей последовательности.[1]

Таким образом все слова на выходе GFSR можно рассматривать как вектора длины w, с коэффициентами из множества {0,1}, которые подчиняются рекурсии

Wk=Wkp+qWkp

где  — XOR, или побитовое сложение по модулю 2, а k=p,p+1,...[2]

Сравнение с аналогичными алгоритмами

Результат работы линейного конгруэнтного генератора

Линейный конгруэнтный генератор показывает плохую n-пространственную однородность. На рисунке предвиден пример результата работы для Xi=17Xi11mod512 для 384 точек (a) и 512 (b).[1]

Результат работы GFSR

Как альтернатива, регистр сдвига с линейной обратной связью (FSR) даёт равномерное распределение в n-мерном пространстве, если длина регистра делится на n. Возможно FSR последовательности дают больше возможностей для улучшения n-мерного пространства, но период ограничен машинным словом. Кроме того, прореживание, с целью получить однородность n-мерном пространстве далее сокращает длину цикла.[1]

Из-за этого был создан регистр сдвига с обобщённой обратной связью, способный генерировать сколь угодно большие последовательности, независимо от размера машинного слова, также обладающий хорошим n-мерным распределением и большой скоростью.[1]

На рисунке предвиден пример результата работы GFSR c полиномом X31+X13+1, 9-битным машинным словом и циклическим сдвигом на 93[1]

История исследования GFSR

Льюисом и Пейном были представлены различные типы генераторов называемые регистры сдвига с обобщённой обратной связью. Этот быстрый метод и может генерировать одинаковые последовательности на компьютерах с разной длиной машинного слова, но он имеет недостаток с инициализацией.[3]

Во-первых, невырожденная битовая начальная матрица размером p×wдолжна быть сформирована. Льюис и Пейн показали, что если относительный сдвиг между соседними колонками постоянен, то матрица не вырожденная. Постоянный сдвиг был произвольно выбран равным 100p.[3]

Во-вторых, Льюис и Пейн предложили, с целью подавить эффект неслучайности начальной матрицы, отбрасывать первые 5000p чисел перед использованием генератора. Так, если нужна длинная последовательность и p большое, то процесс инициализации занимает много времени.

Другой недостаток который может быть более существенным, нет теоретического обоснования того, что последовательность будет обладать свойством k-распределения. Термин k-распределение означает, что каждый k-кортеж из w-бит чисел появляется 2pwk раз на полном периоде, за исключением нулевого кортежа. Они показали что последовательность может быть k-распределённая, для 1kp/w, но это необходимое, а не достаточное условие.[3]

Брайт (Bright) и Энисон (Enison) провели тесты на равнораспределение в пространствах большой размерности небольшой части последовательности с большим периодом. Оказалось что в тестах статистические свойства не повторяют свойства всей последовательности.[3]

Арвилиас (Arvillias) и Маритсас (Maritsas) предложили генератор типа GFSR, в которых pq есть степень 2. Они показали что pq элементов последовательности, почти равномерно распределённых вдоль периода, можно получить за один такт, используя переключатель и регистры сдвига. При этом относительный сдвиг аналитически определён. Это значит, что процесс инициализации становится столь же быстрым как и генерация случайных чисел. Но снова нет гарантий в k-распределении.[3]

Алгоритм GFSR

Входные значения:

  • p,q — задают характеристический полином регистра сдвига
  • a0,...,ap1 — начальная битовая последовательность

Алгоритм:

1. Создаем массив битовых векторов W0,...,Wp1, по которому будем перемещаться с индексом k и вспомогательным индексом j.
2. Инициализируем массив, используя начальную битовую последовательность. Устанавливаем k равное 0.
3. Вычисляем следующий вектор, но так как массив длины p, то индексы вычисляются по модулю p, из-за чего
kp+qk+q
kpk
Таким образом
j=k+qmodp
Wk=WkWj
4. Увеличиваем k на единицу и переходим к вычислению следующего вектора, до тех пор пока последовательность не начнет повторяться (длина последовательности 2p1)[1]

Алгоритм инициализации

  1. Сначала генерируется последовательность согласно алгоритму регистра сдвига с линейной обратной связью.
  2. После чего полученная последовательность циклически сдвигается. Величина сдвига должна быть меньше периода 2p1, тогда гарантируется что стартовые вектора будут линейно независимы (если величина сдвига взаимно просто с 2p1, то сдвиг может превышать полный период).
  3. Используя эту процедуру, получаем j последовательностей, которые можно записать друг под другом. Первые p бит последовательностей образуют матрицу, столбцы которой являются векторами W0,...,Wp1[1]

Пример

Пусть дан полином x5+x3+1, и a0=a1=a2=a3=a4=1.

Элементы последовательности удовлетворяют равенству ak=akp+qakp при k=p,p+1,.... Согласно полиному p=5,q=2, так мы можем узнать элементы последовательности

a5=a2a0=0

a6=a3a1=0

a7=a4a2=0

a8=a5a3=1

и так далее.

Таким образом получаем последовательность a030=1111100011011101010000100101100

Для того чтобы создать хорошую случайную последовательность воспользуемся алгоритмом Кендола (Kendall). Хотя есть несколько вариантов этого алгоритма мы возьмем тот, который сдвигает начальную последовательность 1111100011011101010000100|101100 вперед на 6 бит. То есть 1011001111100011011101010|000100 и так ещё 3 раза. Таким образом получим

Номер последовательность
0 1111100011011101010000100101100
1 1011001111100011011101010000100
2 0001001011001111100011011101010
3 1010100001001011001111100011011
4 0110111010100001001011001111100

W0 образуется из первых бит последовательностей, W1 — из вторых, для W2,W3,W4 аналогично.

W0=11010,W1=10001,W2=11011,W3=11100,W4=10011

Последующие Wk вычисляем согласно правилу Wk=Wk3Wk5.

W0: 11010 W10: 01001 W20: 00111
W1: 10001 W11: 10000 W21: 01111
W2: 11011 W12: 10110 W22: 10010
W3: 11100 W13: 10100 W23: 01100
W4: 10011 W14: 01110 W24: 00101
W5: 00001 W15: 11111 W25: 10101
W6: 01101 W16: 00100 W26: 00011
W7: 01000 W17: 11000 W27: 10111
W8: 11101 W18: 01011 W28: 11001
W9: 11110 W19: 01010 W29: 00110

Преимущества и недостатки

Преимущества

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

Недостатки

Согласно исследованиям количество 0 и 1 в выходной последовательности заметно разнится, а что противоречит постулатам Голомба. Также, если взять целое N, и разделить последовательность на кортежи по N слов, то для случайной последовательности распределение единиц в этих кортежах должно подчиняться биномиальному распределению Bin(N, 1/2). Но оказалось, что при Nn это условие не выполняется. Это из-за того, что каждое слово зависит только от двух предыдущих, и по этому преобладание единиц или нулей не «сглаживается» сумматором по модулю 2.[2]

Вихрь Мерсенна — пример улучшения GFSR

Широко известна модификация регистра сдвига с обобщённой обратной связью под названием «Вихрь Мерсенна», предложенный Макото Мацумото и Такудзи Нисимурой в 1997 году. Период этого генератора огромен, и равен числу Мерсенна 2199371. Вихрь Мерсенна относят к классу витковых генераторов на регистрах сдвига с обобщёнными обратными связями. Его упрощённая схема приведена на рисунке

Упрощённая схема вихря Мерсенна

Рассмотрим наиболее распространённый вариант этого алгоритма — MT19937. Он использует 624 ячейки памяти, в каждой из которых содержится целое 32 битное число. При этом рекуррентное правило формирования последовательности выходных слов записывается таким образом:

Wk=Wk397((Wk623 & 0x80000000) | (Wk622 & 0x7fffffff))×A, (i = 0, 1 , 2, …)

То есть, на каждом k-том шаге берётся старший бит слова Wk623, и 31 бит из слова Wk622, а затем полученные части конкатенируют с последующим умножением полученного результата на матрицу

A=(0100000100...............00001aw1aw2......a0)

где a=(aw1aw2...a0) = 0x9908B0DF в шестнадцатеричном исчислении.

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

См. также

Литература

Примечания

Шаблон:Примечания

Ссылки