Section 12.6 A Taste of Modernity
Subsection 12.6.1 The Pollard Rho algorithm
Here is the essence of this random (or βMonte Carloβ) approach; it is highly recursive, like many good algorithms.Algorithm 12.6.1. Generic routine for βrandomβ factoring.
Follow these steps.
Pick some polynomial that will be easy to compute mod
Plug in an essentially random seed value. (Often the seed is
or )Compute the polynomial's value at the seed.
If that has a non-trivial gcd with
we have a factor. Otherwise, plug the new value back into the polynomial, and repeat (and hope it eventually succeeds).
xxxxxxxxxx
def PollardRhoFactor(n,kstop=50,seed=2):
d=1
a,b=seed,seed
k=1
def f(x):
return (x^2+1)%n
while (d==1 or d==n):
a = f(a)
b = f(f(b))
d=gcd(a-b,n)
k=k+1
if k>kstop:
print("Pollard Rho breaking off after %s rounds"%k)
break
if d>1:
print("Pollard Rho took %s rounds"%k)
print("The number it tried in the last round was %s, which shares factor %s"%(a-b,d))
print("And %s is a factor of %s since %s * %s=%s"%(d,n,d,n/d,d*(n/d)))
(mod ) (mod ) (mod ) all (mod ).
Example 12.6.2.
Let's try computing what we get for some specific numbers. Picking
xxxxxxxxxx
var('x')
def _(seed=2,n=8051,poly=x^2+1,trials=(10,[2..50])):
f(x)=poly
for i in range(trials):
pretty_print(html("$x_{%s}=%s$"%(i,seed)))
seed = (ZZ(f(seed)) % ZZ(n))
pretty_print(html("$x_{%s}=%s$"%(i+1,seed)))
Notice that for
Algorithm 12.6.3. Pollard Rho factoring algorithm.
Follow these steps.
Pick some polynomial
that will be easy to compute (mod ) (such as though other quadratics might be used).Plug in an essentially random seed value
(Often the seed is or )Compute the polynomial's value at the seed,
Continue plugging in
modulo-
For each
we check whether
Example 12.6.4.
Let's try this with
This gives differences as follows:
These factor as follows:
xxxxxxxxxx
factor(21), factor(8709), factor(3977), factor(3672), factor(797)
That is an impressive list of eight different prime factors that could potentially be shared with
xxxxxxxxxx
gcd(9991,21), gcd(9991,8709), gcd(9991,3977), gcd(9991,3672), gcd(9991,797)
Indeed the third one already caught a common divisor with
xxxxxxxxxx
PollardRhoFactor(8051)
Remark 12.6.5.
This method is called the Pollard rho method because (apparently) a very imaginative eye can interpret the
Example 12.6.6.
Sometimes the rho method doesn't come up with an answer quickly, or at all.
xxxxxxxxxx
PollardRhoFactor(991*997)
Here we took 50 rounds without success, using the seed
xxxxxxxxxx
PollardRhoFactor(991*997,seed=3)
Subsection 12.6.2 More factorization
In general, there are other such probabilistic algorithms, and they are quite successful with factoring numbers which might have reasonably sized but not gigantic factors.Historical remark 12.6.7. Factoring Fermat.
The big success of this algorithm was the 1980 factorization of
Interestingly, the other (much larger) factor was not proven to be prime until significantly later; and as of this writing (January 2021) even
xxxxxxxxxx
PollardRhoFactor(2^(2^8)+1,1000000) # one million rounds!
xxxxxxxxxx
PollardRhoFactor(2^(2^8)+1,1000000,seed=3)
xxxxxxxxxx
factor(2^(2^8)+1)
xxxxxxxxxx
def TrialDivFactor(n):
p = next_prime(1)
top = ceil(math.sqrt(n))
while p < top:
if mod(n,p)==0:
break
p=next_prime(p)
if n==1:
print("1 is not prime")
elif p==n:
print(n,"is prime")
elif mod(n,p)==0:
print(n,"factors as",p,"times",n/p)
else:
print(n,"is prime")
β
def FermatFactor(n,verbose=False):
if n%2==0:
raise TypeError("Input must be odd!")
s=ceil(math.sqrt(n))
top=(n+1)/2
while is_square(s^2-n)==0:
if verbose:
print(s,"squared minus",n,"is",s^2-n,"which is not a perfect square")
s=s+1
t=sqrt(s^2-n)
print("Fermat found that",s,"squared minus",t,"squared equals",n)
if s^2==n:
print("So",n,"was already a perfect square,",s,"times",s)
elif s<top:
print("So",s+t,"times",s-t,"equals",(s-t)*(s+t),"which is",n)
elif s==top:
print("So Fermat did not find a factor, which means",n,"is prime!")
xxxxxxxxxx
def _(n=991*997,method=['trial','Fermat','Pollard Rho']):
if method=='trial':
TrialDivFactor(n)
if method=='Fermat':
FermatFactor(n)
if method=='Pollard Rho':
PollardRhoFactor(n)
Sage note 12.6.8. Building interacts.
An interact is just a Sage/Python function, except with @interact
before it. There are many different input widgets you can use; this one demonstrates using a list and an input box which takes any input. See the interact documentation or Quickstart for many examples and more details.
Another interesting resource is Sage developer Paul Zimmermann's Integer Factoring Records. Finally, Wagstaff's The joy of factoring [E.4.12] has tons of awesome examples and procedures β far too many, really, as well as an excellent discussion of how to speed up trial division, etc.The Cunningham Project seeks to factor the numbers
for up to high powers