Русская Википедия:Метод Фибоначчи с запаздываниями

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

Запаздывающие генераторы Фибоначчи (Шаблон:Lang-en) — генераторы псевдослучайных чисел, также называемые аддитивными генераторами.

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

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

История

Последовательность, в которой <math>X_{n+1}</math> зависит более, чем от одного из предшествующих значений, и которая определяется следующей формулой:

<math>X_{n+1}=(X_n+X_{n-1}) \mod (2^m),</math>

носит название последовательность Фибоначчи.

В начале 50-х годов изучался данный алгоритм, однако, исследования показали, что этот генератор, как источник случайных чисел, был неэффективен. Грин (Green), Смит (Smith) и Клем (Klem) предложили доработанную формулу последовательности Фибоначчи в виде:

<math>X_{n+1}=(X_n+X_{n-k}) \mod (2^m).</math>

Однако, положительный результат получался лишь при <math>k\geq16</math>.

В 1958 году Митчел Дж. Ж. (Mitchell G. J.) и Мур Д. Ф. (Moore D. P.) вывели последовательность[1]:

<math>X_{n}=(X_{n-24}+X_{n-55}) \mod(2^m),</math> <math>(1)</math>

где <math>n\geq55</math>, <math>m</math> — чётное число, <math>X_0, X_1,...,X_{54}</math> — произвольные целые не все чётные числа. Числа 24 и 55 выбраны так, чтобы определялась последовательность, младшие значащие двоичные разряды <math>(X_n \mod(2))</math> которой имеют длину периода <math>2^{55}-1</math>.

Очевидными преимуществами данного алгоритма являются его быстрота, поскольку он не требует умножения чисел, а также, длина периода, однако, случайность, полученных с помощью него чисел, мало исследована.

Числа 24 и 55 обычно называют запаздыванием, а числа <math>X_n</math>, определённые в (1) — последовательностью Фибоначчи с запаздыванием[2].

Впоследствии, на основе этих работ было подобрано множество запаздываний, которые приводят к длинным периодам по модулю 2.

Формула

Аддитивные генераторы генерируют вместо случайных битов случайные слова.

Для работы аддитивному генератору требуется некое начальное состояние, которое является ключом — набор n-битовых слов: 16-битовых, 32-битовых, 64-битовых слов и т. д. — <math>X_1, X_2,...,X_k</math>.

Зная начальное состояние, можно вычислить i-е слово генератора по формуле[3]:

<math>X_{i}=(X_{i-a}+X_{i-b}+...+X_{i-k}) \mod (2^m),</math>

причём период генератора должен быть более или равен <math>2^m-1</math>.

Примеры алгоритмов, на основе аддитивных генераторов

Шаблон:Mainref

1) Один из широко распространённых фибоначчиевых генераторов основан на следующей итеративной формуле:

<math>X_k = \begin{cases} X_{k-a}-X_{k-b}, & \text{if } X_{k-a}\geq X_{k-b}; \\

X_{k-a}-X_{k-b}+1, & \text{if } X_{k-a} < X_{k-b};\end{cases}</math>

где <math>X_k</math> — вещественные числа из диапазона <math>[0, 1)</math>, <math>a, b</math> — целые положительные числа, называемые лагами. При реализации через целые числа достаточно формулы <math>X_k = X_{k-a}-X_{k-b}</math> (при этом будут происходить арифметические переполнения). Для работы фибоначчиеву генератору требуется знать <math>\max\{a, b\}</math> предыдущих сгенерированных случайных чисел. При программной реализации для хранения сгенерированных случайных чисел используется конечная циклическая очередь на базе массива. Для старта фибоначчиевому генератору требуется <math>\max\{a, b\}</math> случайных чисел, которые могут быть сгенерированы простым конгруэнтным методом.

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

<math>T = (2^{\max\{a,b\}}-1) \cdot 2^{\ell},</math>

где <math>\ell</math> — число битов в мантиссе вещественного числа.

Выбор параметров

Лаги a и b — «магические» и их не следует выбирать произвольно. Рекомендуются следующие значения лагов: <math>(a,b) = (55,24)</math>, <math>(17,5)</math> или <math>(97,33)</math>. Качество получаемых случайных чисел зависит от значения константы, a чем оно больше, тем выше размерность пространства, в котором сохраняется равномерность случайных векторов, образованных из полученных случайных чисел. В то же время, с увеличением величины константы a увеличивается объём используемой алгоритмом памяти.

Значения <math>(a,b) = (17,5)</math> можно рекомендовать для простых приложений, не использующих векторы высокой размерности со случайными компонентами. Значения <math>(a,b) = (55,24)</math> позволяют получать числа, удовлетворительные для большинства алгоритмов, требовательных к качеству случайных чисел. Значения <math>(a,b) = (97,33)</math> позволяют получать очень качественные случайные числа и используются в алгоритмах, работающих со случайными векторами высокой размерности. Описанный фибоначчиев генератор случайных чисел (с лагами 20 и 5) используется в широко известной системе Matlab (автором первой версии этой системы был Д. Каханер).

В настоящее время подобрано достаточно много пар чисел a и b, приведём некоторые из них:

<math>(24,55),(38,89),(37,100),(30,127),(83,258),(107,378),(273,607),(1029,2281),(576,3217),(4178,9689),...</math>

2) Брюс Шнайер в своей работе «Прикладная криптография» приводит примеры 3-х алгоритмов на основе аддитивных генераторов[4]:

Алгоритм Fish

«Fish — это аддитивный генератор, основанный на методах, используемых в прореживаемом генераторе. Он выдает поток 32-битовых слов, которые могут быть использованы (с помощью XOR) с потоком открытого текста для получения шифротекста или с потоком шифротекста для получения открытого текста. Название алгоритма представляет собой сокращение от Fibonacci shrinking generator — прореживаемый генератор Фиббоначи.

Во-первых, используйте два следующих аддитивных генератора. Ключом является начальные состояния этих генераторов.

<math>A_i=(A_{i-55}+A_{i-24}) \mod (2^{32})

</math>

<math>B_i=(B_{i-52}+B_{i-19}) \mod (2^{32})

</math>

Эти последовательности прореживаются попарно в зависимости от младшего значащего бита <math>B_i </math>: если его значение равно 1, то пара используется, если 0 — игнорируется. <math>C_j </math> — это последовательность используемых слов <math>A_i </math>, a <math>D_j </math> — это последовательность используемых слов <math>B_i </math>. Для генерации двух 32-битовых слов-результатов <math>K_{2j} </math> и <math>K_{2j+1} </math> эти слова используются парами — <math>C_{2j},C_{2j+1},D_{2j},D_{2j+1} </math>.

<math>E_{2j}=C_{2j}\oplus(D_{2j}\land D_{2j+1})

</math>

<math>F_{2j}=D_{2j+1}\oplus(E_{2j}\land C_{2j+1})

</math>

<math>K_{2j}=E_{2j}\oplus F_{2j}

</math>

<math>K_{2j+1}=C_{2j+1}\oplus F_{2j}

</math>

Этот алгоритм быстр, на процессоре i486/33 реализация Fish на языке С шифрует данные со скоростью 15-Мбит/с. К сожалению он также не безопасен, порядок вскрытия составляет около 240

Алгоритм Pike

«Pike — это обедненная и урезанная версия Fish, предложенная Россом Андерсоном, тем, кто взломал Fish . Он использует три аддитивных генератора. Например:

<math>A_i=(A_{i-55}+A_{i-24}) \mod (2^{32})

</math>

<math>B_i=(B_{i-57}+B_{i-7}) \mod (2^{32})

</math>

<math>C_i=(C_{i-58}+C_{i-19}) \mod (2^{32})

</math>

Для генерации слова потока ключей взгляните на биты переноса при сложении. Если все три одинаковы (все нули или все единицы), то тактируются все три генератора. Если нет, то тактируются только два совпадающих генератора. Сохраните биты переноса для следующего раза. Окончательным выходом является XOR выходов трех генераторов.

Pike быстрее Fish, так как в среднем для получения результата нужно 2.75 действия, а не 3. Он также слишком нов, чтобы ему доверять, но выглядит очень неплохо».

Алгоритм Mush

«Mush представляет собой взаимно прореживающий генератор. Его работу объяснить легко. Возьмем два аддитивных генератора: А и В. Если бит переноса А установлен, тактируется В. Если бит переноса В установлен, тактируется А.Тактируем А и при переполнении устанавливаем бит переноса. Тактируем В и при переполнении устанавливаем бит переноса. Окончательным выходом является XOR выходов А и В. Проще всего использовать те же генераторы, что и в Fish:

<math>A_i=(A_{i-55}+A_{i-24}) \mod (2^{32})

</math>

<math>B_i=(B_{i-52}+B_{i-19}) \mod (2^{32})

</math>

В среднем для генерации одного выходного слова нужно три итерации генератора. И если коэффициенты аддитивного генератора выбраны правильно и являются взаимно простыми, длина выходной последовательности будет максимальна.»

Примечания

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

Литература

Ссылки

Шаблон:Rq

  1. Кнут Д. Искусство программирования. — том 2. — 3-е издание. — 2001 г. — гл.3.2.2.
  2. Кнут Д. Искусство программирования. — том 2. — 3-е издание — 2001 г. — C.39.
  3. Шнайер Б. Прикладная криптография. Протоколы, алгоритмы и исходные тексты на языке C. — 2002 г. — С. 291.
  4. Шнайер Б. Прикладная криптография. Протоколы, алгоритмы и исходные тексты на языке C. — 2002 г. — гл.16.9.