Ро-алгоритм Полларда

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

Шаблон:About

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

Ро-алгоритм (ρ-алгоритм) — предложенный Шаблон:Нп5 в 1975 году алгоритм, служащий для факторизации (разложения на множители) целых чисел. Данный алгоритм основывается на алгоритме Флойда поиска длины цикла в последовательности и некоторых следствиях из парадокса дней рождения. Алгоритм наиболее эффективен при факторизации составных чисел с достаточно малыми множителями в разложении. Сложность алгоритма оценивается как O(N1/4)Шаблон:Sfn.

ρ-алгоритм Полларда строит числовую последовательность, элементы которой образуют цикл, начиная с некоторого номера n, что может быть проиллюстрировано, расположением чисел в виде греческой буквы ρ, что послужило названием семейству алгоритмовШаблон:SfnШаблон:Sfn.

История алгоритма

В конце 60-х годов XX века Роберт Флойд придумал достаточно эффективный метод решения задачи нахождения цикла, также известный, как алгоритм «черепаха и заяц»Шаблон:Sfn. Джон Поллард, Дональд Кнут и другие математики проанализировали поведение этого алгоритма в среднем случае. Было предложено несколько модификаций и улучшений алгоритмаШаблон:Sfn.

В 1975 году Поллард опубликовал статьюШаблон:Sfn, в которой он, основываясь на алгоритме Флойда обнаружения циклов, изложил идею алгоритма факторизации чисел, работающего за время, пропорциональное N1/4[1][2]. Автор алгоритма назвал его методом факторизации Монте-Карло, отражая кажущуюся случайность чисел, генерируемых в процессе вычисления. Однако позже метод всё-таки получил своё современное название — ρ-aлгоритм ПоллардаШаблон:Sfn.

В 1981 году Ричард Брент и Джон Поллард с помощью алгоритма нашли наименьшие делители чисел Ферма Fn=22n+1 при 5n13Шаблон:Sfn. Скорость алгоритма сильно зависит лишь от величины наименьшего делителя исходного числа, но не от самого числа. Так, поиск наименьшего делителя седьмого числа Ферма — F7=340282366920938463463374607431768211457=596495891274972175704689200685129054721;, занимает гораздо больше времени, чем поиск делителя двенадцатого числа Ферма (т.к. его делитель 114689 значительно меньше, хотя само число состоит более чем из 1200 десятичных цифр).

В рамках проекта «Шаблон:Нп5» алгоритм Полларда помог найти делитель длиной 19 цифр числа 22386+1. Большие делители также могли бы быть найдены, однако открытие метода факторизации с помощью эллиптических кривых сделало алгоритм Полларда неконкурентоспособнымШаблон:Sfn.

Описание алгоритма

Оригинальная версия

Рассматривается последовательность целых чисел xn, такая что x0=2 и xi+1=(xi21)(modN), где N — число, которое нужно факторизовать. Оригинальный алгоритм выглядит следующим образомШаблон:Sfn[1]:

1. Вычисляются тройки чисел
(xi,x2i,Qi),i=1,2,..., где Qij=1i(x2jxj)(modN).
Причём каждая такая тройка получается из предыдущей.
2. Каждый раз, когда число i кратно числу m (скажем, m=100), вычисляется наибольший общий делитель di=GCD(Qi,N) любым известным методом.
3. Если 1<di<N, то частичное разложение числа N найдено, причём N=di×(N/di).
Найденный делитель di может быть составным, поэтому его также необходимо факторизовать. Если число N/di составное, то продолжаем алгоритм с модулем N=N/di.
4. Вычисления повторяются S раз. Если при этом число не было до конца факторизовано, выбирается, например, другое начальное число x0.

Современная версия

Пусть N составное целое положительное число, которое требуется разложить на множители. Алгоритм выглядит следующим образом[3]:

  1. Случайным образом выбирается небольшое число x0Шаблон:Sfn и строится последовательность {xn},n=0,1,2,..., определяя каждое следующее как xn+1=F(xn)(modN).
  2. Одновременно на каждом i-ом шаге вычисляется d=GCD(N,|xixj|) для каких-либо i, j таких, что j<i, например, i=2j.
  3. Если d>1, то вычисление заканчивается, и найденное на предыдущем шаге число d является делителем N. Если N/d не является простым числом, то процедуру поиска делителей продолжается, взяв в качестве N число N=N/d.

На практике функция F(x) выбирается не слишком сложной для вычисления (но в то же время не линейным многочленом), при условии того, что она не должна порождать взаимно однозначное отображение. Обычно в качестве F(x) выбираются функции F(x)=x2±1(modN)[4] или F(x)=x2±a(modN)[5]. Однако функции x22 и x2 не подходят[6].

Если известно, что для делителя p числа N справедливо p1(modk) при некотором k>2, то имеет смысл использовать F(x)=xk+b[6].

Существенным недостатком алгоритма в такой реализации является необходимость хранить большое число предыдущих значений xj.

Улучшения алгоритма

Изначальная версия алгоритма обладает рядом недостатков. В настоящий момент существует несколько подходов к улучшению оригинального алгоритма.

Пусть F(x)=(x21)modN. Тогда, если (xjxi)0(modp), то (F(xj)F(xi))0(modp), поэтому, если пара (xi,xj) даёт решение, то решение даст любая пара (xi+k,xj+k).

Поэтому нет необходимости проверять все пары (xi,xj), а можно ограничиться парами вида (xi,xj), где j=2k, и k пробегает набор последовательных значений 1, 2, 3, …, а i принимает значения из интервала [2k+1;2k+1]. Например, k=3, j=23=8, а i[9;16]Шаблон:Sfn.

Эта идея была предложена Ричардом Брентом в 1980 годуШаблон:Sfn и позволяет уменьшить количество выполняемых операций приблизительно на 25 %Шаблон:Sfn.

Ещё одна вариация ρ-алгоритма Полларда была разработана Флойдом. Согласно Флойду, значение y обновляется на каждом шаге по формуле y=F2(y)=F(F(y)), поэтому на шаге i будут получены значения xi=Fi(x0), yi=x2i=F2i(x0), и НОД на этом шаге вычисляется для N и yx[3].

Пример факторизации числа

Данный пример наглядно демонстрирует ρ-алгоритм факторизации (версия алгоритма, с улучшением Флойда), для числа N = 8051:

Таблица: факторизация числа 8051
n = 8051, F(x) = (x2 + 1) mod n , x0 = y0 = 2
i xi=F(xi-1) yi=F(F(yi-1)) НОД(|xiyi|, 8051)
1 5 26 1
2 26 7474 1
3 677 871 97

Используя другие варианты полинома F(x), можно также получить делитель 83:

Таблица: факторизация числа 8051
n = 8051, F(x) = (x2 + 3) mod n , x0 = y0 = 2
i xi=F(xi-1) yi=F(F(yi-1)) НОД(|xiyi|, 8051)
1 7 52 1
2 52 1442 1
3 2707 778 1
4 1442 3932 83

Таким образом, d1 = 97, d2 = 83 — нетривиальные делители числа 8051.

После нахождения делителя числа, в ρ-алгоритме предлагается продолжать вычисления и искать делители числа N/d, если N/d не является простым. В этом простом примере данного шага совершать не потребовалось[3].

Обоснование ρ-алгоритма Полларда

Алгоритм основывается на известном парадоксе дней рождения.

Шаблон:Теорема

Следует отметить, что вероятность p=0.5 в парадоксе дней рождения достигается при λ0.69.

Пусть последовательность {un} состоит из разностей xixj, проверяемых в ходе работы алгоритма. Определяется новая последовательность {zn}, где zn=unmodq, q — меньший из делителей числа N.

Все члены последовательности {zn} меньше N. Если рассматривать её как случайную последовательность целых чисел, меньших q, то, согласно парадоксу дней рождения, вероятность того, что среди l+1 её членов попадутся два одинаковых, превысит 1/2 при λ0.69, тогда l должно быть не меньше 2λq1.4q1.18q.

Если zi=zj, тогда xixj0modq, то есть, xixj=kq для некоторого целого k. Если xixj, что выполняется с большой вероятностью, то искомый делитель q числа N будет найден как GCD(N,|xixj|). Поскольку qn1/4, то с вероятностью, превышающей 1/2 , делитель N будет найден за 1.18×N1/4 итераций[3].

Сложность алгоритма

Чтобы оценить сложность алгоритма, рассматривается последовательность, строящаяся в процессе вычислений, как случайная (разумеется, ни о какой строгости при этом говорить нельзя). Чтобы полностью факторизовать число N длиной β бит, достаточно найти все его делители, не превосходящие N, что требует максимум порядка N арифметических операций, или N1/4β2=2β/4β2 битовых операций.

Поэтому сложность алгоритма оценивается, как O(N1/4)Шаблон:Sfn. Однако в этой оценке не учитываются накладные расходы по вычислению наибольшего общего делителя. Полученная сложность алгоритма, хотя и не является точной, достаточно хорошо согласуется с практикой.

Справедливо следующее утверждение: пусть N — составное число. Тогда существует такая константа C, что для любого положительного числа λ вероятность события, состоящего в том, что ρ-алгоритм Полларда не найдет нетривиального делителя N за время CλN(logN)2, не превосходит величины eλ. Данное утверждение следует из парадокса дней рожденияШаблон:Sfn.

Особенности реализации

Объём памяти, используемый алгоритмом, можно значительно уменьшить.

 int Rho-Поллард (int N)
 { 
   int x = random(1, N-2);
   int y = 1; int i = 0; int stage = 2;
   while (Н.О.Д.(N, abs(x - y)) == 1)
   {
     if (i == stage){
       y = x;
       stage = stage*2; 
     }
     x = (x*x + 1) (mod N);
     i = i + 1;
   }
   return Н.О.Д(N, abs(x-y));
 }

В этом варианте вычисление требует хранить в памяти всего три переменные N, x, и y, что выгодно отличает алгоритм в такой реализации от других методов факторизации чисел[3].

Распараллеливание алгоритма

Алгоритм Полларда допускает распараллеливание с использованием как систем с разделяемой памятью, так и систем с распределенной памятью (передача сообщений), однако второй случай является наиболее интересным с практической точки зренияШаблон:Sfn.

Система с распределенной памятью

Существующий метод распараллеливания заключается в том, что каждый вычислительный узел исполняет один и тот же последовательный алгоритм, однако, исходное число x0 и/или полином F(x) берутся различными. Для упрощения распараллеливания, предлагается получать их из генератора случайных чисел. Однако такая параллельная реализация не даёт линейного ускоренияШаблон:Sfn.

Предположим что есть P одинаковых исполнителей. Если мы используем P различных последовательностей (то есть различных полиномов F(x)), то вероятность того, что первые k чисел в этих последовательностях будут различными по модулю p, будет примерно равна exp(k2P/2p). Таким образом, максимальное ускорение можно оценить как P1/2[7].

Ричард Крэндалл предположил, что достижимо ускорение O(P/(logP)2), однако данное утверждение пока не провереноШаблон:Sfn.

Система с общей памятью

Предыдущий метод, очевидно, можно использовать и на системах с общей памятью, однако, гораздо разумнее использовать единый генератор F(x)Шаблон:Sfn.

Примечания

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

Литература

Шаблон:Refbegin

Шаблон:Refend

Шаблон:Теоретико-числовые алгоритмы Шаблон:Добротная статья

  1. 1,0 1,1 Ошибка цитирования Неверный тег <ref>; для сносок Pollard_bit не указан текст
  2. Ошибка цитирования Неверный тег <ref>; для сносок Pollard_article не указан текст
  3. 3,0 3,1 3,2 3,3 3,4 Ошибка цитирования Неверный тег <ref>; для сносок Ishmuhammetov не указан текст
  4. Ошибка цитирования Неверный тег <ref>; для сносок Mollin_default_function не указан текст
  5. Золотых Н. Ю. Лекции по компьютерной алгебре. Лекция 11. ρ-метод Полларда. Шаблон:Wayback
  6. 6,0 6,1 Ошибка цитирования Неверный тег <ref>; для сносок Pollard не указан текст
  7. Ошибка цитирования Неверный тег <ref>; для сносок BrentParallel не указан текст