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 (n).
Plug in an essentially random seed value. (Often the seed is 2 or 3.)
Compute the polynomial's value at the seed.
If that has a non-trivial gcd with n, 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)))
x0β‘2 (mod n)
x1β‘f(x0) (mod n)
x2β‘f(x1) (mod n)
xi+1β‘f(xi), all (mod n).
Example 12.6.2.
Let's try computing what we get for some specific numbers. Picking n=8051 as in [C.2.4, Example 3.25], we get results as in the following interact.
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 n=8051, the term x4β‘x19 (mod n), so the sequence, while seeming fairly random, will not come up with every possible divisor. With seed 3, x13β‘x28 is the first repeat; if instead we change the modulus to 8053, there is no repeat through x50. So you can see the output will be hard to predict.
Algorithm 12.6.3. Pollard Rho factoring algorithm.
Follow these steps.
Pick some polynomial f(x) that will be easy to compute mod (n) (such as x2+1, though other quadratics might be used).
Plug in an essentially random seed value x0. (Often the seed is 2 or 3.)
Compute the polynomial's value at the seed, f(x0)=x1.
Continue plugging in f(xi)=xi+1, modulo n.
-
For each k we check whether
1<gcd(x2kβxk,n)=d<n.
Example 12.6.4.
Let's try this with n=9991. Keeping x2+1 and seed 2, the numbers we would get for the first six rounds are
This gives differences as follows:
x2βx1=26β5=21
x4βx2=8735β26=8709
x6βx3=4654β677=3977
x8βx4=4973β8735=β3762
x10βx5=8153β8950=β797
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 9991 in just five iterations. These differences have the following gcds with 9991:
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 9991.
xxxxxxxxxx
PollardRhoFactor(8051)
Remark 12.6.5.
This method is called the Pollard rho method because (apparently) a very imaginative eye can interpret the xi eventually repeating (mod d) (in the example, d=97) as a tail and then a loop, i.e. a Greek Ο. John Pollard actually has another method named after him, the pβ1 method, which we will not explore; however, it is related to some of the more advanced methods we mentioned in the introduction to this section.
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 2. Because of the Ο repetition, it will never succeed. So what do you do then β bring out the really advanced methods? Not at all β just as with primality testing, you just change your starting point to try again!
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.Remark 12.6.7.
The big success of this algorithm was the 1980 factorization of F8 (the eighth Fermat number) by Pollard and Richard Brent (see Brent's website). They used one of several variants of the method, due to Brent, to found the previously unknown prime factorβ3βIf you want to memorize this historic number, Brent provides the phrase βI am now entirely persuaded to employ the method, a handy trick, on gigantic composite numbersβ to help you remember it. 1238926361552897. Finding this factor of F8 took, in total, 2 hours on a UNIVAC 1100/42 (which for the time period was very fast, indeed). Interestingly, the other (much larger) factor was not proven to be prime until significantly later.
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 [C.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 bnΒ±1 for b=2,3,5,6,7,10,11,12, up to high powers n.