Ро-алгоритм (
  
    
      
        ρ
      
    
    {\displaystyle \rho }
  
-алгоритм) — предложенный Джоном Поллардом в 1975 году алгоритм, служащий для факторизации (разложения на множители) целых чисел. Данный алгоритм основывается на алгоритме Флойда поиска длины цикла в последовательности и некоторых следствиях из парадокса дней рождения. Алгоритм наиболее эффективен при факторизации составных чисел с достаточно малыми множителями в разложении. Сложность алгоритма оценивается как 
  
    
      
        O
        (
        
          N
          
            1
            
              /
            
            4
          
        
        )
      
    
    {\displaystyle O(N^{1/4})}
  
.
 ρ-алгоритм Полларда строит числовую последовательность, элементы которой образуют цикл, начиная с некоторого номера n, что может быть проиллюстрировано, расположением чисел в виде греческой буквы ρ, что послужило названием семейству алгоритмов.
 В конце 60-х годов XX века Роберт Флойд придумал достаточно эффективный метод решения задачи нахождения цикла, также известный, как алгоритм «черепаха и заяц». Джон Поллард, Дональд Кнут и другие математики проанализировали поведение этого алгоритма в среднем случае. Было предложено несколько модификаций и улучшений алгоритма.
 В 1975 году Поллард опубликовал статью, в которой он, основываясь на алгоритме Флойда обнаружения циклов, изложил идею алгоритма факторизации чисел, работающего за время, пропорциональное 
  
    
      
        
          N
          
            1
            
              /
            
            4
          
        
      
    
    {\displaystyle N^{1/4}}
  
.
Автор алгоритма назвал его методом факторизации Монте-Карло, отражая кажущуюся случайность чисел, генерируемых в процессе вычисления. Однако позже метод всё-таки получил своё современное название — ρ-aлгоритм Полларда.
 В 1981 году Ричард Брент и Джон Поллард с помощью алгоритма нашли наименьшие делители чисел Ферма 
  
    
      
        
          F
          
            n
          
        
        =
        
          2
          
            
              2
              
                n
              
            
          
        
        +
        1
      
    
    {\displaystyle F_{n}=2^{2^{n}}+1}
  
 при 
  
    
      
        5
        ≤
        n
        ≤
        13
      
    
    {\displaystyle 5\leq n\leq 13}
  
.
Скорость алгоритма сильно зависит лишь от величины наименьшего делителя исходного числа, но не от самого числа. Так, поиск наименьшего делителя седьмого числа Ферма — 
  
    
      
        
          
            
              
                
                  F
                  
                    7
                  
                
                =
                340282366920938463463374607431768211457
                =
                59
                
                649
                
                589
                
                127
                
                497
                
                217
                ⋅
                5
                
                704
                
                689
                
                200
                
                685
                
                129
                
                054
                
                721
                ;
              
            
          
        
      
    
    {\displaystyle {\begin{array}{lll}F_{7}=340282366920938463463374607431768211457=59\,649\,589\,127\,497\,217\cdot 5\,704\,689\,200\,685\,129\,054\,721;\end{array}}}
  
, занимает гораздо больше времени, чем поиск делителя двенадцатого числа Ферма (т.к. его делитель 114689 значительно меньше, хотя само число состоит более чем из 1200 десятичных цифр).
 В рамках проекта «Cunningham project» алгоритм Полларда помог найти делитель длиной 19 цифр числа 
  
    
      
        
          2
          
            2386
          
        
        +
        1
      
    
    {\displaystyle 2^{2386}+1}
  
. Большие делители также могли бы быть найдены, однако открытие метода факторизации с помощью эллиптических кривых сделало алгоритм Полларда неконкурентоспособным.
 Рассматривается последовательность целых чисел 
  
    
      
        
          
            x
            
              n
            
          
        
      
    
    {\displaystyle {x_{n}}}
  
, такая что 
  
    
      
        
          x
          
            0
          
        
        =
        2
      
    
    {\displaystyle x_{0}=2}
  
 и 
  
    
      
        
          x
          
            i
            +
            1
          
        
        =
        (
        
          x
          
            i
          
          
            2
          
        
        −
        1
        
        )
        (
        
          m
          o
          d
        
        
        N
        )
      
    
    {\displaystyle x_{i+1}=(x_{i}^{2}-1\,)(\mathrm {mod} \,N)}
  
, где 
  
    
      
        N
      
    
    {\displaystyle N}
  
 — число, которое нужно факторизовать. Оригинальный алгоритм выглядит следующим образом:
 Пусть 
  
    
      
        N
      
    
    {\displaystyle N}
  
 составное целое положительное число, которое требуется разложить на множители. Алгоритм выглядит следующим образом:
 На практике функция 
  
    
      
        F
        (
        x
        )
      
    
    {\displaystyle F(x)}
  
 выбирается не слишком сложной для вычисления (но в то же время не линейным многочленом), при условии того, что она не должна порождать взаимно однозначное отображение. Обычно в качестве 
  
    
      
        F
        (
        x
        )
      
    
    {\displaystyle F(x)}
  
 выбираются функции 
  
    
      
        F
        (
        x
        )
        =
        
          x
          
            2
          
        
        ±
        1
        (
        
          m
          o
          d
        
        
        N
        )
      
    
    {\displaystyle F(x)=x^{2}\pm 1(\mathrm {mod} \,N)}
  
 или 
  
    
      
        F
        (
        x
        )
        =
        
          x
          
            2
          
        
        ±
        a
        (
        
          m
          o
          d
        
        
        N
        )
      
    
    {\displaystyle F(x)=x^{2}\pm a(\mathrm {mod} \,N)}
  
. Однако функции 
  
    
      
        
          x
          
            2
          
        
        −
        2
      
    
    {\displaystyle x^{2}-2}
  
 и 
  
    
      
        
          x
          
            2
          
        
      
    
    {\displaystyle x^{2}}
  
 не подходят.
 Если известно, что для делителя 
  
    
      
        p
      
    
    {\displaystyle p}
  
 числа 
  
    
      
        N
      
    
    {\displaystyle N}
  
 справедливо 
  
    
      
        p
        ≡
        1
        
        (
        
          m
          o
          d
        
        
        k
        )
      
    
    {\displaystyle p\equiv 1\,(\mathrm {mod} \,k)}
  
 при некотором 
  
    
      
        k
        >
        2
      
    
    {\displaystyle k>2}
  
, то имеет смысл использовать 
  
    
      
        F
        (
        x
        )
        =
        
          x
          
            k
          
        
        +
        b
      
    
    {\displaystyle F(x)=x^{k}+b}
  
.
 Существенным недостатком алгоритма в такой реализации является необходимость хранить большое число предыдущих значений 
  
    
      
        
          x
          
            j
          
        
      
    
    {\displaystyle x_{j}}
  
.
 Изначальная версия алгоритма обладает рядом недостатков. В настоящий момент существует несколько подходов к улучшению оригинального алгоритма.
 Пусть 
  
    
      
        F
        (
        x
        )
        =
        (
        
          x
          
            2
          
        
        −
        1
        )
        
          mod
          
            N
          
        
      
    
    {\displaystyle F(x)=(x^{2}-1){\bmod {N}}}
  
. Тогда, если 
  
    
      
        (
        
          x
          
            j
          
        
        −
        
          x
          
            i
          
        
        )
        ≡
        0
        
          
          (
          mod
          
          p
          )
        
      
    
    {\displaystyle (x_{j}-x_{i})\equiv 0{\pmod {p}}}
  
, то 
  
    
      
        (
        F
        (
        
          x
          
            j
          
        
        )
        −
        F
        (
        
          x
          
            i
          
        
        )
        )
        ≡
        0
        
          
          (
          mod
          
          p
          )
        
      
    
    {\displaystyle (F(x_{j})-F(x_{i}))\equiv 0{\pmod {p}}}
  
, поэтому, если пара 
  
    
      
        (
        
          x
          
            i
          
        
        ,
        
          x
          
            j
          
        
        )
      
    
    {\displaystyle (x_{i},x_{j})}
  
 даёт решение, то решение даст любая пара 
  
    
      
        (
        
          x
          
            i
            +
            k
          
        
        ,
        
          x
          
            j
            +
            k
          
        
        )
      
    
    {\displaystyle (x_{i+k},x_{j+k})}
  
.
 Поэтому нет необходимости проверять все пары 
  
    
      
        (
        
          x
          
            i
          
        
        ,
        
          x
          
            j
          
        
        )
      
    
    {\displaystyle (x_{i},x_{j})}
  
, а можно ограничиться парами вида 
  
    
      
        (
        
          x
          
            i
          
        
        ,
        
          x
          
            j
          
        
        )
      
    
    {\displaystyle (x_{i},x_{j})}
  
, где 
  
    
      
        j
        =
        
          2
          
            k
          
        
      
    
    {\displaystyle j=2^{k}}
  
, и 
  
    
      
        k
      
    
    {\displaystyle k}
  
 пробегает набор последовательных значений 1, 2, 3, …, а 
  
    
      
        i
      
    
    {\displaystyle i}
  
 принимает значения из интервала 
  
    
      
        [
        
          2
          
            k
          
        
        +
        1
        ;
        
          2
          
            k
            +
            1
          
        
        ]
      
    
    {\displaystyle [2^{k}+1;2^{k+1}]}
  
. Например, 
  
    
      
        k
        =
        3
      
    
    {\displaystyle k=3}
  
, 
  
    
      
        j
        =
        
          2
          
            3
          
        
        =
        8
      
    
    {\displaystyle j=2^{3}=8}
  
, а 
  
    
      
        i
        ∈
        [
        9
        ;
        16
        ]
      
    
    {\displaystyle i\in [9;16]}
  
.
 Эта идея была предложена Ричардом Брентом в 1980 году и позволяет уменьшить количество выполняемых операций приблизительно на 25 %.
 Ещё одна вариация ρ-алгоритма Полларда была разработана Флойдом. Согласно Флойду, значение 
  
    
      
        y
      
    
    {\displaystyle y}
  
 обновляется на каждом шаге по формуле 
  
    
      
        y
        =
        
          F
          
            2
          
        
        (
        y
        )
        =
        F
        (
        F
        (
        y
        )
        )
      
    
    {\displaystyle y=F^{2}(y)=F(F(y))}
  
, поэтому на шаге 
  
    
      
        i
      
    
    {\displaystyle i}
  
 будут получены значения 
  
    
      
        
          x
          
            i
          
        
        =
        
          F
          
            i
          
        
        (
        
          x
          
            0
          
        
        )
      
    
    {\displaystyle x_{i}=F^{i}(x_{0})}
  
, 
  
    
      
        
          y
          
            i
          
        
        =
        
          x
          
            2
            i
          
        
        =
        
          F
          
            2
            i
          
        
        (
        
          x
          
            0
          
        
        )
      
    
    {\displaystyle y_{i}=x_{2i}=F^{2i}(x_{0})}
  
, и НОД на этом шаге вычисляется для 
  
    
      
        N
      
    
    {\displaystyle N}
  
 и 
  
    
      
        y
        −
        x
      
    
    {\displaystyle y-x}
  
.
 Данный пример наглядно демонстрирует ρ-алгоритм факторизации (версия алгоритма, с улучшением Флойда), для числа N = 8051:
 Используя другие варианты полинома 
  
    
      
        F
        (
        x
        )
      
    
    {\displaystyle F(x)}
  
, можно также получить делитель 83:
 Таким образом, d1 = 97, d2 = 83 — нетривиальные делители числа 8051.
 После нахождения делителя числа, в ρ-алгоритме предлагается продолжать вычисления и искать делители числа 
  
    
      
        N
        
          /
        
        d
      
    
    {\displaystyle N/d}
  
, если 
  
    
      
        N
        
          /
        
        d
      
    
    {\displaystyle N/d}
  
 не является простым. В этом простом примере данного шага совершать не потребовалось.
 Алгоритм основывается на известном парадоксе дней рождения.
 Парадокс дней рождений, кратко:
Пусть 
  
    
      
        λ
        >
        0
      
    
    {\displaystyle \lambda >0}
  
. Для случайной выборки из 
  
    
      
        l
        +
        1
      
    
    {\displaystyle l+1}
  
 элементов, каждый из которых меньше 
  
    
      
        q
      
    
    {\displaystyle q}
  
, где 
  
    
      
        l
        =
        
          
            2
            λ
            q
          
        
      
    
    {\displaystyle l={\sqrt {2\lambda q}}}
  
, вероятность того, что два элемента окажутся одинаковыми 
  
    
      
        p
        >
        1
        −
        
          e
          
            −
            λ
          
        
      
    
    {\displaystyle p>1-e^{-\lambda }}
  
.
 Следует отметить, что вероятность 
  
    
      
        p
        =
        0.5
      
    
    {\displaystyle p=0.5}
  
 в парадоксе дней рождения достигается при 
  
    
      
        λ
        ≈
        0.69
      
    
    {\displaystyle \lambda \approx 0.69}
  
.
 Пусть последовательность 
  
    
      
        {
        
          u
          
            n
          
        
        }
      
    
    {\displaystyle \{u_{n}\}}
  
 состоит из разностей 
  
    
      
        
          x
          
            i
          
        
        −
        
          x
          
            j
          
        
      
    
    {\displaystyle x_{i}-x_{j}}
  
, проверяемых в ходе работы алгоритма. Определяется новая последовательность 
  
    
      
        {
        
          z
          
            n
          
        
        }
      
    
    {\displaystyle \{z_{n}\}}
  
, где 
  
    
      
        
          z
          
            n
          
        
        =
        
          u
          
            n
          
        
        
        
          m
          o
          d
        
        
        q
      
    
    {\displaystyle z_{n}=u_{n}\,\mathrm {mod} \,q}
  
, 
  
    
      
        q
      
    
    {\displaystyle q}
  
 — меньший из делителей числа 
  
    
      
        N
      
    
    {\displaystyle N}
  
.
 Все члены последовательности 
  
    
      
        {
        
          z
          
            n
          
        
        }
      
    
    {\displaystyle \{z_{n}\}}
  
 меньше 
  
    
      
        
          
            N
          
        
      
    
    {\displaystyle {\sqrt {N}}}
  
. Если рассматривать её как случайную последовательность целых чисел, меньших 
  
    
      
        q
      
    
    {\displaystyle q}
  
, то, согласно парадоксу дней рождения, вероятность того, что среди 
  
    
      
        l
        +
        1
      
    
    {\displaystyle l+1}
  
 её членов попадутся два одинаковых, превысит 
  
    
      
        1
        
          /
        
        2
      
    
    {\displaystyle 1/2}
  
 при 
  
    
      
        λ
        ≈
        0.69
      
    
    {\displaystyle \lambda \approx 0.69}
  
, тогда 
  
    
      
        l
      
    
    {\displaystyle l}
  
 должно быть не меньше 
  
    
      
        
          
            2
            λ
            q
          
        
        ≈
        
          
            1.4
            q
          
        
        ≈
        1.18
        
          
            q
          
        
      
    
    {\displaystyle {\sqrt {2\lambda q}}\approx {\sqrt {1.4q}}\approx 1.18{\sqrt {q}}}
  
.
 Если 
  
    
      
        
          z
          
            i
          
        
        =
        
          z
          
            j
          
        
      
    
    {\displaystyle z_{i}=z_{j}}
  
, тогда 
  
    
      
        
          x
          
            i
          
        
        −
        
          x
          
            j
          
        
        ≡
        0
        
        
          m
          o
          d
        
        
        q
      
    
    {\displaystyle x_{i}-x_{j}\equiv 0\,\mathrm {mod} \,q}
  
, то есть, 
  
    
      
        
          x
          
            i
          
        
        −
        
          x
          
            j
          
        
        =
        k
        q
      
    
    {\displaystyle x_{i}-x_{j}=kq}
  
 для некоторого целого 
  
    
      
        k
      
    
    {\displaystyle k}
  
. Если 
  
    
      
        
          x
          
            i
          
        
        ≠
        
          x
          
            j
          
        
      
    
    {\displaystyle x_{i}\neq x_{j}}
  
, что выполняется с большой вероятностью, то искомый делитель 
  
    
      
        q
      
    
    {\displaystyle q}
  
 числа 
  
    
      
        N
      
    
    {\displaystyle N}
  
 будет найден как 
  
    
      
        
          G
          C
          D
        
        (
        N
        ,
        
          |
        
        
          x
          
            i
          
        
        −
        
          x
          
            j
          
        
        
          |
        
        )
      
    
    {\displaystyle \mathrm {GCD} (N,|x_{i}-x_{j}|)}
  
. Поскольку 
  
    
      
        
          
            q
          
        
        ≤
        
          n
          
            1
            
              /
            
            4
          
        
      
    
    {\displaystyle {\sqrt {q}}\leq n^{1/4}}
  
, то с вероятностью, превышающей 
  
    
      
        1
        
          /
        
        2
      
    
    {\displaystyle 1/2}
  
 , делитель 
  
    
      
        N
      
    
    {\displaystyle N}
  
 будет найден за 
  
    
      
        1.18
        ×
        
          N
          
            1
            
              /
            
            4
          
        
      
    
    {\displaystyle 1.18\times N^{1/4}}
  
 итераций.
 Чтобы оценить сложность алгоритма, рассматривается последовательность, строящаяся в процессе вычислений, как случайная (разумеется, ни о какой строгости при этом говорить нельзя). Чтобы полностью факторизовать число 
  
    
      
        N
      
    
    {\displaystyle N}
  
 длиной 
  
    
      
        β
      
    
    {\displaystyle \beta }
  
 бит, достаточно найти все его делители, не превосходящие 
  
    
      
        
          
            N
          
        
      
    
    {\displaystyle {\sqrt {N}}}
  
, что требует максимум порядка 
  
    
      
        
          
            N
          
        
      
    
    {\displaystyle {\sqrt {N}}}
  
 арифметических операций, или 
  
    
      
        
          N
          
            1
            
              /
            
            4
          
        
        
          β
          
            2
          
        
        =
        
          2
          
            β
            
              /
            
            4
          
        
        
          β
          
            2
          
        
      
    
    {\displaystyle N^{1/4}\beta ^{2}=2^{\beta /4}\beta ^{2}}
  
 битовых операций.
 Поэтому сложность алгоритма оценивается, как 
  
    
      
        O
        (
        
          N
          
            1
            
              /
            
            4
          
        
        )
      
    
    {\displaystyle O(N^{1/4})}
  
. Однако в этой оценке не учитываются накладные расходы по вычислению наибольшего общего делителя. Полученная сложность алгоритма, хотя и не является точной, достаточно хорошо согласуется с практикой.
 Справедливо следующее утверждение: пусть 
  
    
      
        N
      
    
    {\displaystyle N}
  
 — составное число. Тогда существует такая константа 
  
    
      
        C
      
    
    {\displaystyle C}
  
, что для любого положительного числа 
  
    
      
        λ
      
    
    {\displaystyle \lambda }
  
 вероятность события, состоящего в том, что ρ-алгоритм Полларда не найдет нетривиального делителя 
  
    
      
        N
      
    
    {\displaystyle N}
  
 за время 
  
    
      
        C
        
          
            λ
            
              
                N
              
            
          
        
        (
        log
        ⁡
        N
        
          )
          
            2
          
        
      
    
    {\displaystyle C{\sqrt {\lambda {\sqrt {N}}}}(\log N)^{2}}
  
, не превосходит величины 
  
    
      
        
          e
          
            −
            λ
          
        
      
    
    {\displaystyle e^{-\lambda }}
  
. Данное утверждение следует из парадокса дней рождения.
 Объём памяти, используемый алгоритмом, можно значительно уменьшить.
 В этом варианте вычисление требует хранить в памяти всего три переменные 
  
    
      
        N
      
    
    {\displaystyle N}
  
, 
  
    
      
        x
      
    
    {\displaystyle x}
  
, и 
  
    
      
        y
      
    
    {\displaystyle y}
  
, что выгодно отличает алгоритм в такой реализации от других методов факторизации чисел.
 Алгоритм Полларда допускает распараллеливание с использованием как систем с разделяемой памятью, так и систем с распределенной памятью (передача сообщений), однако второй случай является наиболее интересным с практической точки зрения.
 Существующий метод распараллеливания заключается в том, что каждый вычислительный узел исполняет один и тот же последовательный алгоритм, однако, исходное число 
  
    
      
        
          x
          
            0
          
        
      
    
    {\displaystyle x_{0}}
  
 и/или полином 
  
    
      
        F
        (
        x
        )
      
    
    {\displaystyle F(x)}
  
 берутся различными. Для упрощения распараллеливания, предлагается получать их из генератора случайных чисел. Однако такая параллельная реализация не даёт линейного ускорения.
 Предположим что есть 
  
    
      
        P
      
    
    {\displaystyle P}
  
 одинаковых исполнителей. Если мы используем 
  
    
      
        P
      
    
    {\displaystyle P}
  
 различных последовательностей (то есть различных полиномов 
  
    
      
        F
        (
        x
        )
      
    
    {\displaystyle F(x)}
  
), то вероятность того, что первые 
  
    
      
        k
      
    
    {\displaystyle k}
  
 чисел в этих последовательностях будут различными по модулю 
  
    
      
        p
      
    
    {\displaystyle p}
  
, будет примерно равна 
  
    
      
        exp
        ⁡
        (
        
          −
          
            k
            
              2
            
          
          P
        
        
          /
        
        2
        p
        )
      
    
    {\displaystyle \exp({-k^{2}P}/2p)}
  
. Таким образом, максимальное ускорение можно оценить как 
  
    
      
        
          P
          
            1
            
              /
            
            2
          
        
      
    
    {\displaystyle P^{1/2}}
  
.
 Ричард Крэндалл предположил, что достижимо ускорение 
  
    
      
        O
        (
        P
        
          /
        
        (
        log
        ⁡
        P
        
          )
          
            2
          
        
        )
      
    
    {\displaystyle O(P/(\log P)^{2})}
  
, однако данное утверждение пока не проверено.
 Предыдущий метод, очевидно, можно использовать и на системах с общей памятью, однако, гораздо разумнее использовать единый генератор 
  
    
      
        F
        (
        x
        )
      
    
    {\displaystyle F(x)}
  
.