Math 7 Spring 2017 TA: Serin Hong PROBLEM SET 6 SOLUTIONS

Math 7 Spring 2017
TA: Serin Hong
PROBLEM SET 6 SOLUTIONS
1. Implement a deterministic Solovay-Strassen primality test. In other words, implement a function
SSP(int n), that takes an odd natural number n and checks whether an Euler witness for n exists in
{1, · · · , C}, where C = b2(log n)2 c.
If n is prime, it should return 1. If n is composite, it should return the smallest positive Euler witness
for n.
Solution. First, we need a function that computes the Jacobi symbols. A sample implementation goes
as follows:
def Jacobi(a, n):
if gcd(a, n)>1:
return 0
a=a%n
#return 0 if a and n are not relatively prime
#make a<n; this is crucial for recursion
if a==1:
return 1
if (a%2==0):
#return 1 if a=1; this is the base for recursion
#reduce to the case when a is odd
if ((n%8==1) | (n%8==7)):
return Jacobi(a/2, n)
else:
return -Jacobi(a/2, n)
#now apply recursion using quadratic reciprocity
elif ((a%4==3) & (n%4==3)):
return -Jacobi(n, a)
else:
return Jacobi(n, a)
return
Now we can implement a deterministic Solovay-Strassen primality test as follows:
def SSP(n):
#set up initial values; note that we also require maximum residue < n
max_residue=min(floor(2*log(n)*log(n)), n-1); a=2; e=Integer((n-1)/2)
Math 7 Spring 2017
TA: Serin Hong
while (a <= max_residue):
if ((Jacobi(a, n)==0) | ((power_mod(a,e,n)-Jacobi(a,n))%n!=0)):
return a
a=a+1
return 1
2. Compute a list of all composite numbers in the range 1 ≤ a ≤ 120000 whose smallest positive Euler
witness is greater than 2.
Solution. Below is a standard way of producing (and printing) a desired list:
list_for_2_as_euler_liar=[]
for k in range(1, 60000):
n=2*k+1
if (SSP(n)>2):
list_for_2_as_euler_liar.append(n)
print list_for_2_as_euler_liar
This gives the following list:
[561, 1105, 1729, 1905, 2047, 2465, 3277, 4033, 4681, 6601, 8321, 8481, 10585,
12801, 15841, 16705, 18705, 25761, 29341, 30121, 33153, 34945, 41041, 42799,
46657, 49141, 52633, 62745, 65281, 74665, 75361, 80581, 85489, 87249, 88357,
90751, 104653, 113201, 115921]
3. Compute a list of all Carmichael numbers in the same range. What is the symmetric difference of this
list and the previous one?
Solution. To simplify our computation, it is useful to observe that every Carmichael number is odd.
Indeed, if n > 2 is even, then we have (n−1)n−1 ≡ (−1)n−1 = −1 ( mod n), so we can’t have (n−1)n−1 ≡
1 (mod n) even thought n − 1 and n are relatively prime.
For convenience, we implement a function that determines whether a given positive odd integer is a
Carmichael number.
def isCarmichael(n):
if (SSP(n)==1):
Math 7 Spring 2017
return False
TA: Serin Hong
#if n is prime, return False
for a in range(1, n):
if (gcd(a, n)==1) & (Integer(power_mod(a, n-1, n))!=1):
return False
return True
Now we produce the list of Carmichael numbers in the given range as follows:
Carmichael_list=[]
for k in range(1, 60000):
n=2*k+1
if (isCarmichael(n)==True):
Carmichael_list.append(n)
Carmichael_list
This gives the following list:
[561, 1105, 1729, 2465, 2821, 6601, 8911, 10585, 15841, 29341, 41041, 46657,
52633, 62745, 63973, 75361, 101101, 115921]
For the symmetric difference of this list and the previous one, we simply use
sorted(Set(list_for_2_as_euler_liar).symmetric_difference(Set(Carmichael_list)))
which yields the following list:
[1905, 2047, 2821, 3277, 4033, 4681, 8321, 8481, 8911, 12801, 16705, 18705,
25761, 30121, 33153, 34945, 42799, 49141, 63973, 65281, 74665, 80581, 85489,
87249, 88357, 90751, 101101, 104653, 113201]