## Project#1: Primality Test ### Instructions

1. Download the provided code for Project 1. Before you can run the provided GUI, you will need to setup Python 3 and install PyQT5 (visit the python-setup slack channel for additional help).
2. You will need to implement the code that will be executed when the "Test Primality" button is clicked. The provided file ``` fermat.py ``` includes six functions, three of which are called from the GUI. You will need to implement five of these functions (the sixth simply passes your results back to the GUI):
1. Code up the Fermat primality test pseudocode from Figure 1.8 of the text. You may set k to any value you like (see p. 27), this value indicates how many random trials (values of a ) are used.
2. Implement modular exponentiation (pseudo-code in Figure 1.4 on p. 19). Your primality test should use your modular exponentiation function and should work properly for numbers as large as 2 30 = 1073741824.
3. Code the probability that k Fermat trials gave you the correct answer -- see the discussion between Figure 1.7 and Figure 1.8.
4. Implement the Miller-Rabin primality test. There is no pseudo-code in the book for this, but you can find what you need in the sidebar on p. 28 and in the discussion that follows.
5. Code the probability that k Miller-Rabin trials gave you the correct answer -- see the note in the sidebar on p. 28 and the discussion below.

### The Miller-Rabin test

Let's say the number we are testing is N =97; just as in the Fermat case, we choose a random test in the range1 ≤ a < N ; suppose for our test we chose a =3. Then,

a ^( N -1) = 3^96 = 6362685441135942358474828762538534230890216321 ≣ 1 (mod 97),

as Fermat's theorem says it should. Since this is 1 (mod 97), if we take the square root, we would expect the result to be either 1 or -1. We can check this by computing

(3^96)^(1/2) = 3^(48) = 79766443076872509863361 ≣ 1 (mod 97),

just as expected. But, since this is also 1, we can take the square root again by computing

(3^48)^(1/2) = 3^24 = 282429536481 ≣ 96 ≣ -1 (mod 97). <-- Passed. Still looks prime.

Continuing the sequence, we can take yet another square root, but since we are now taking the square root of -1, we don't expect such nice behavior, and indeed, we get

(3^24)^(1/2) = 3^12 = 531441 ≣ 75 (mod 97).

We can complete the sequence with

(3^12)^(1/2) = 3^6 = 729 ≣ 50 (mod 97) and

(3^6)^(1/2) = 3^3 = 27 ≣ 27 (mod 97),

and we can't divide the exponent by 2 anymore, so we are done.

To summarize, what we are doing here is repeatedly taking the square root of a number that is ≣ 1 (mod N). For a while, the result is, not unexpectedly, 1 (mod N), but at some point it is -1 (mod N). As we know, taking the square root of -1 is weird (though in this modular case that doesn't mean complex numbers; rather, we just get away from 1). What Miller and Rabin showed is that for prime numbers, for all choices of a , 1 ≤ a < N this sequence of square roots, starting with a 1 (mod N) will either consist of all 1s (mod N), or, if at some point it changes to something else, that something else will always be N -1 ≣ -1 (mod N), which is exactly what we saw in our example. What they also showed was that for composites ( including Carmichael numbers), for at least 3/4 of the possible choices for a , this will not be the case---either the initial test will not equal 1 (mod N), just as in the Fermat case, or, if it does, in taking the series of square roots, the first number to show up after the sequence of 1s will be something other than N -1 ≣ -1 (mod N).

Here is another example: suppose N =561 and we choose a =4. Then, computing our sequence of square roots, we get

4^560 = a really big number ≣ 1 (mod 561)

4^280 = a smaller but still really big number ≣ 1 (mod 561)

4^140 = a still pretty big number ≣ 1 (mod 561)

4^70 = 1393796574908163946345982392040522594123776 ≣ 67 (mod 561) <-- Failed. Composite.

4^35 = 1180591620717411303424 ≣ 166 (mod 561)

Notice that this time, that when we encountered something other than 1 (mod N) in the sequence, it was also not N -1 ≣ -1 (mod N).This is common for composites, but never happens for primes. Also notice in both examples that we stopped the sequence when taking the square root (halving the exponent) resulted in an odd exponent. Hopefully now it is becoming clear how we can implement an alternative to the Fermat-test-based primality testing algorithm with this new information---if our number N passes the initial test a (which is equivalent to a Fermat test, right?), we then compute this sequence of square roots (until we get to an odd exponent), looking for the first result that is not 1 (mod N). If there isn't one (because the entire sequence is 1s) or if the first such number is N -1 ≣ -1 (mod N), N has passed Miller-Rabin test a , and we still don't know anything for sure (so, we should continue to choose another random a and repeat our test); however, if we insteadfind that there is a first result in the sequence that is neither 1 nor N -1 ≣ -1 (mod N), then we know the number is composite.

### Submission

A report consisting of:

1. [10 points] At least one screenshot of your application with a working example (distinct from the one above).