Proving Primality
February 2, 2010
We examined algorithms for checking the primality of a number in two previous exercises. Both algorithms are probabilistic; the Rabin-Miller algorithm has known false positives, and Carl Pomerance proved that the Baillie-Wagstaff algorithm has an infinite number of false positives, even though none are known.
Today’s exercise describes an algorithm for proving that a number is prime, not probably but certainly. The algorithm works by a theorem of Edouard Lucas, which is based on Fermat’s Little Theorem (if n is prime then bn-1 ≡ 1 (mod n) for every integer b coprime to n):
If, for some integer b, bn-1 ≡ 1 (mod n), and if b(n-1)/q ≢ 1 (mod n) for any prime divisor q of n-1, then n is a prime number.
Thus, if the factors of n-1 are known, it is easy to determine the primality of n.
Your task is to write a function that determines the primality of an integer using Lucas’ primality test; use it to prove the primality of 289-1. When you are finished, you are welcome to read or run a suggested solution , or to post your own solution or discuss the exercise in the comments below.
[…] Praxis – Proving Primality By Remco Niemeijer In today’s Programming Praxis exercise we have to implement an algorithm to prove the primality of a number. […]
My Haskell solution (see http://bonsaicode.wordpress.com/2010/02/02/programming-praxis-proving-primality/ for a version with comments):
I found the description of the algorithm confusing. When I implemented it, the routine would report some multiples of 5 (e.g., 15 and 35) to be prime.
Studying the proof at the mathpages.com link, given above, I think the algorithm should be to find a b so that b^(x-1) == 1 (mod n) then, if b^((n-1)/q) != 1 (mod n) for *all* prime divisors q of n-1, n is prime. If b^((n-1)/q) == 1 (mod n) for some q, then try a new value for b. This matches the pseudocode at wikipedia.
My python code is below:
It wasn’t confusing, it was wrong. Thanks for pointing out the bug. I’ve updated the solution and added a test function.
By the way, your version of is_prime incorrectly reports that 2 is composite. You should change the test at lines 22 and 23 to read:
if n%2 == 0:
return n == 2
Don’t feel bad; Jon Bentley got that wrong in one of his books, so you’re in good company.
D’oh…guess that’ll teach me not to edit a routine and not test it again before posting.
Is there a way to edit my earlier post fix lines 22 and 23? Or should I just repost a correct version?
My confusion was over the word “any” in
“… if b^((n-1)/q) != 1 (mod n) for *any* prime divisor q of n-1, n is prime.”
At first, I read the phrase to mean if I found any one q for which the non-congruence was true, then n is prime. However, the correct reading is that the non-congruence holds no matter which q you try. Therefore, you have to try every q to prove n is prime. Perhaps using “every” instead of “any” would be clearer.
Here’s a corrected version of the python code for proving a number is prime using the Lucas algorithm.