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

Матеріал з testwiki
Перейти до навігації Перейти до пошуку

Шаблон:Не плутати

Числова послідовність зациклюється, починаючи з деякого n. Цикл виглядає як грецька літера ρ.

ρ-алгоритм Полларда — алгоритм факторизації цілих чисел, що ґрунтується на пошуку циклу в послідовності і деяких наслідках із парадоксу днів народжень. Його запропонував Шаблон:Не перекладено (1975). Алгоритм найбільш ефективний для факторизації складених чисел із досить малими множниками в розкладі. Обчислювальна складність оцінюється як O(N1/4).

У всіх варіантах ρ-алгоритму Полларда будується числова послідовність, елементи якої, починаючи з деякого номера n, утворюють цикл, що можна проілюструвати розташуванням членів послідовності у вигляді грецької літери ρ. Це й послужило назвою для сімейства методів.

Історія алгоритму

Наприкінці 60-х років XX століття Дональд Кнут опублікував досить ефективний алгоритм пошуку циклу в послідовності, також відомий, як алгоритм «черепаха та заєць», який він пов'язував з ім'ям Флойда[1]. Шаблон:Не перекладено, Дональд Кнут та інші математики проаналізували поведінку цього алгоритму в середньому випадку. Було запропоновано кілька модифікацій та поліпшень алгоритму.

У 1975 році Поллард опублікував статтю, в якій він, ґрунтуючись на алгоритмі Флойда виявлення циклів, виклав ідею алгоритму факторизації чисел, який виконується за час, пропорційний N1/4Шаблон:Sfn. Автор назвав його методом факторизації Монте-Карло, тому, що в процесі обчислення генерується псевдовипадкова послідовність чисел. Проте пізніше метод все-таки назвали ρ-алгоритмом ПоллардаШаблон:Sfn.

У 1981 році Шаблон:Не перекладено і Джон Поллард за допомогою цього алгоритму знайшли менший дільник восьмого числа Ферма F8=228+1Шаблон:Sfn.

Так, F8=1238926361552897p62, де p62 — просте число, що складається з 62 десяткових цифр.

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

Опис алгоритму

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

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

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 раз. Наприклад, можна зупинити алгоритм при i=S=105. Якщо при цьому число не було до кінця факторизовано, можна вибрати, наприклад, інше початкове число x0.

Сучасна версія

Нехай N складене ціле додатне число, яке потрібно розкласти на множники. Алгоритм виглядає таким чином:Шаблон:Sfn

  1. Вибираємо невелике число x0 та будуємо послідовність {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) або F(x)=x2±a(modN)[2]. Однак не слід застосовувати функції x22 та x2Шаблон:Sfn.

Якщо відомо, що для дільника p числа N справедливо p1(modk) при деякому k>2, то має сенс застосувати F(x)=xk+bШаблон:Sfn.

Істотним недоліком алгоритму в такий реалізації є необхідність зберігати велику кількість попередніх значень 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Шаблон:Sfn.

Приклад факторизації числа

Нехай N=8051, F(x)=(x2+1)mod8051, x0=y0=2, yi+1=F(F(yi)).

i xi yi НСД (|xiyi|, 8051)
1 5 26 1
2 26 7474 1
3 677 871 97

Таким чином, 97 — нетривіальний дільник числа 8051. Використовуючи інші варіанти поліному F(x), можна також отримати дільник 83.

Обґрунтування ρ-методу Полларда

Алгоритм ґрунтується на відомому парадоксі днів народження.

Теорема (Парадокс днів народження)

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

Слід зазначити, що ймовірність 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, то з імовірністю, що перевищує 0,5, дільник N буде знайдено за 1.18×N1/4 ітераційШаблон:Sfn.

Складність алгоритму

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

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

Виконується така теорема. Нехай N — складене число. Тоді існує така стала C, що для будь-якого додатного числа λ ймовірність події, що полягає в тому, що ρ-метод Поларда не знайде нетривіального дільника N за час CλN(logN)2, не перевершує величини eλ. Ця теорема випливає з парадоксу днів народження.

Особливості реалізації

Обсяг пам'яті, використовуваний алгоритмом, можна значно зменшити.

 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, що вигідно відрізняє метод в такій реалізації від інших методів факторизації чиселШаблон:Sfn.

Розпаралелювання алгоритму

Алгоритм Полларда дозволяє розпаралелювання з використанням будь-якого стандарту паралельних обчислень (наприклад, OpenMP та ін.).

Існує декілька варіантів розпаралелювання, але їх спільна ідея полягає в тому, що кожний процесор виконує послідовний алгоритм, причому початкове число x0 та/або поліном F(x) мають бути різними для кожного процесора. Очікується, що на якомусь процесорі початкові параметри (випадково) виявляться більш вдалими і дільник буде знайдено швидше, однак цей випадок недетермінований (імовірнісний). Прискорення від такої паралельної реалізації значно менше лінійного.

Припустимо, що є P однакових процесорів. Якщо ми використовуємо P різних послідовностей (тобто, різних поліномів F(x)), то ймовірність того, що перші k чисел в цих послідовностях будуть різними за модулем p приблизно дорівнює exp(k2P/2p). Таким чином, прискорення можна оцінити як P1/2Шаблон:Sfn. Тобто, збільшення швидкості вдвічі можна очікувати, якщо процесорів буде вчетверо більше.

Річард Крандалл припустив, що можна досягти прискорення O(P/(logP)2), однак на 2000-й рік це твердження не було перевіреноШаблон:Sfn.

Див. також

Примітки

Шаблон:Примітки

Література

Шаблон:Алгоритми теорії чисел

  1. Перший опис алгоритму «черепахи та зайця» з'явився в другому томі Мистецтва програмування Дональда Кнута (Шаблон:Citation), у вправах 6 та 7 (стор. 7). На сторінці 4 Кнут приписує цей алгоритм Флойду, не посилаючись на джерела. Хоча Флойд і опублікував 1967 року статтю: Шаблон:Citation, однак у ній він описав алгоритми пошуку простих циклів в орієнтованому графі.
  2. Н. Ю. Золотих. Лекції по комп'ютерній алгебрі. Лекция 11. ρ-метод Полларда. Шаблон:Webarchive