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

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку
Числова послідовність зациклюється, починаючи з деякого n. Цикл виглядає як грецька літера ρ.

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

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

Історія алгоритму[ред. | ред. код]

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

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

У 1981 році Річард Брент[ru] і Джон Поллард за допомогою цього алгоритму знайшли менший дільник восьмого числа Ферма [4].

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

У межах проекту «Cunningham project[en]» алгоритм Полларда допоміг знайти дільник числа довжиною 19 цифр. Більші дільники також можна б знайти, але відкриття методу факторизації за допомогою еліптичних кривих[ru] зробило алгоритм Полларда неконкурентоспроможним[5].

Опис алгоритму[ред. | ред. код]

Оригінальна версія[ред. | ред. код]

Розглянемо послідовність цілих чисел , таку що та , де  — число, яке потрібно факторизувати. Оригінальний алгоритм виглядає таким чином[6].

1. Будемо обчислювати трійки чисел
, де .
Причому кожна така трійка отримується з попередньої.
2. Щоразу, коли число кратне числу (скажімо, ), будемо обчислювати найбільший спільний дільник будь-яким відомим методом.
3. Якщо , то знайдено часткове розкладання числа , причому .
Знайдений дільник може бути складовим, тому його також необхідно факторизувати. Якщо число складене, то продовжуємо алгоритм з модулем .
4. Обчислення повторюються раз. Наприклад, можна зупинити алгоритм при . Якщо при цьому число не було до кінця факторизовано, можна вибрати, наприклад, інше початкове число .

Сучасна версія[ред. | ред. код]

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

  1. Вибираємо невелике число та будуємо послідовність , визначаючи кожне наступне як .
  2. Одночасно на кожному i-ому кроці обчислюємо для будь-яких , таких, що , наприклад, .
  3. Якщо виявили, що , то обчислення закінчується, і знайдене на попередньому кроці число є дільником . Якщо не є простим числом, то процедуру пошуку дільників можна продовжити, узявши як число .

Як на практиці обирати функцію ? Функція має бути не надто складною для обчислення, але в той же час не має бути лінійним многочленом, а також не повинна породжувати взаємно однозначне відображення. Зазвичай за беруть функцію або [8]. Однак не слід застосовувати функції та [6].

Якщо відомо, що для дільника числа справедливо при деякому , то має сенс застосувати [6].

Істотним недоліком алгоритму в такий реалізації є необхідність зберігати велику кількість попередніх значень .

Покращення алгоритму[ред. | ред. код]

Початкова версія алгоритму має низку недоліків. На даний момент[коли?] існує кілька підходів до поліпшення оригінального методу.

Нехай . Зауважимо, що й , то , тому, якщо пара дає нам розв'язок, то розв'язок дасть будь-яка пара .

Тому, немає потреби перевіряти всі пари , а можна обмежитися парами виду , де , і пробігає набір послідовних значень 1, 2, 3,…, а набуває значення з інтервалу . Наприклад, , , а [9].

Цю ідею запропонував Річард Брент[ru] у 1980 році[10] і вона дозволяє зменшити кількість виконуваних операцій приблизно на чверть (25%)[11].

Ще одну варіацію ρ-методу Поларда розробив Флойд. За Флойдом, значення оновлюється на кожному кроці за формулою , тому на кроці i будуть отримані значення , , і НСД на цьому кроці обчислюється для та [7].

Приклад факторизації числа[ред. | ред. код]

Нехай , , , .

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

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

Обґрунтування ρ-методу Полларда[ред. | ред. код]

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

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

Нехай . Для випадкової вибірки з елементів, кожний з яких менший від , де , ймовірність того, що два елементи виявляться однаковими .

Слід зазначити, що ймовірність в парадоксі днів народження досягається при .

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

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

Якщо , тоді , тобто, для деякого цілого . Якщо , що виконується з великою ймовірністю, то шуканий дільник числа буде знайдено як . Оскільки , то з імовірністю, що перевищує 0,5, дільник буде знайдено за ітерацій[7].

Складність алгоритму[ред. | ред. код]

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

Тому складність алгоритму оцінюється, як [12]. Однак у цій оцінці не враховуються накладні витрати з обчислення найбільшого спільного дільника. Отримана складність алгоритму, хоча і не є точною, проте достатньо добре узгоджується з практикою.

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

Особливості реалізації[ред. | ред. код]

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

 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));
 }


у цьому варіанті обчислення потребує зберігати в пам'яті всього три змінні , , і , що вигідно відрізняє метод в такій реалізації від інших методів факторизації чисел[7].

Розпаралелювання алгоритму[ред. | ред. код]

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

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

Припустимо, що є однакових процесорів. Якщо ми використовуємо різних послідовностей (тобто, різних поліномів ), то ймовірність того, що перші чисел в цих послідовностях будуть різними за модулем приблизно дорівнює . Таким чином, прискорення можна оцінити як [5]. Тобто, збільшення швидкості вдвічі можна очікувати, якщо процесорів буде вчетверо більше.

Річард Крандалл припустив, що можна досягти прискорення , однак на 2000-й рік це твердження не було перевірено[13].

Див. також[ред. | ред. код]

Примітки[ред. | ред. код]

  1. Перший опис алгоритму «черепахи та зайця» з'явився в другому томі Мистецтва програмування Дональда Кнута (Knuth, Donald E. (1969), The Art of Computer Programming, vol. II: Seminumerical Algorithms, Addison-Wesley), у вправах 6 та 7 (стор. 7). На сторінці 4 Кнут приписує цей алгоритм Флойду, не посилаючись на джерела. Хоча Флойд і опублікував 1967 року статтю: Floyd, R.W. (1967), Non-deterministic Algorithms, J. ACM, 14 (4): 636—644, doi:10.1145/321420.321422, однак у ній він описав алгоритми пошуку простих циклів в орієнтованому графі.
  2. Brent, 1980, An Improved Monte Carlo Factorization Algorithm.
  3. Koshy, 2007, Elementary Number Theory with Applications.
  4. Childs, 2009, 471-473.
  5. а б Brent, 1999, Some parallel algorithms for integer factorization..
  6. а б в Pollard, 1975, A Monte Carlo method for factorization.
  7. а б в г Ішмухаметов, 2011, с. 64.
  8. Н. Ю. Золотих. Лекції по комп'ютерній алгебрі. Лекция 11. ρ-метод Полларда. [Архівовано 30 жовтня 2014 у Wayback Machine.]
  9. Ішмухаметов, 2011, Методи факторизації натуральних чисел: Навчальний посібник.
  10. Brent, 1980, с. 176-184.
  11. Reisel, 2012, Selected Areas in Cryptography. Prime Numbers and Computer Methods for Factorization. 2nd ed..
  12. Cormen, 2001, с. 976, Introduction to Algorithms. Section 31.9. Integer Factorization. Pollard's rho heuristic..
  13. Crandall, 1999, Parallelization of Polldar-rho factorization.

Література[ред. | ред. код]