d2jsp
Log InRegister
d2jsp Forums > Off-Topic > Computers & IT > Programming & Development > Python > And The Miller- Rabin Test
Add Reply New Topic New Poll
Member
Posts: 24,396
Joined: Oct 21 2007
Gold: 0.38
Mar 25 2013 11:23pm
So we're reviewing the Miller-Rabin test, for homework we had to do this:

Code
import random

#Define a Python function G(t,n) that returns '1' if t is equivalent to
#1 modulo n, returns '-1' if t is equivalent to -1 modulo n, and returns
#'*' otherwise.
def G(t,n):
   if t%n == 1: return 1
   if t%-n == -1: return -1
   return '*'


#Define a Python function seeG(L,n) that takes a list L of numbers and prints
#out, on one line, the characters G(t,n) for t in L.
def seeG(L,n):
   for t in L:
       print G(t,n),
   

#Define a Python function sd(n) that returns the list [s,d], or the pair
#(s,d), where d is odd and n-1 = 2^s*d.
def sd(n):
   d = n-1
   s = 0
   while d%2 == 0:
       s += 1
       d /= 2
   return [s,d]


#Define a Python function MR(n) that creates a random number a between 2 and
#n-2, sets x equal to pow(a,d,n), and returns the list
#[x,pow(x,2,n),pow(x,4,n),...,pow(x,2**s,n)]. Here d and s are the numbers
#returned by sd(n).
def MR(n):
   a  = random.randint(2,n-2)
   s_d= sd(n)
   x  = pow(a, s_d[1], n)
   MR = [x]
   for s in xrange(2, pow(2,s_d[0])+1, 2):
       MR += [pow(x,s,n)]
   return MR


#Define a Python function seeMR(n) that prints out the list returned by MR(n)
#using seeG(L,n).
def seeMR(n):
   L = MR(n)
   seeG(L,n)


#Apply seeMR(n) ten times to various large Carmichael numbers n, such as
#56052361. What do the results mean? You can find large Carmichael numbers
#here. The ones with no small factors are the most stubborn ones.
for i in xrange(10):
   seeMR(56052361)
   print


...but I don't think it's working properly. I have no idea what could be wrong with it. Please if you know math and can read python help me out! (#'s are just comments; what we're supposed to do)

Thank you! :LOVE: Will pay if desired!



e/ Sample output:
Code
1 1 1 1 1
* * 1 * 1
* * 1 * 1
* 1 1 1 1
* * 1 * 1
* * 1 * 1
* 1 1 1 1
* * 1 * 1
* * 1 * 1
-1 1 1 1 1


This post was edited by DeadlySanity on Mar 25 2013 11:38pm
Member
Posts: 16,144
Joined: Mar 27 2008
Gold: 14,618.00
Mar 26 2013 04:23am
check second line again:
Code
if t%-n == -1: return -1

t modulo "-n" is wrong imo
Member
Posts: 24,396
Joined: Oct 21 2007
Gold: 0.38
Mar 26 2013 07:54am
Quote (Richter @ Mar 26 2013 05:23am)
check second line again:
Code
if t%-n == -1: return -1

t modulo "-n" is wrong imo


t modulo (-n) should return the negative version of t modulo n.

i.e: 5%-6 = -1, which is right.


Unless you mean that's not what the comments meant, in which case, can you explain more? :LOVE:
Member
Posts: 16,144
Joined: Mar 27 2008
Gold: 14,618.00
Mar 26 2013 09:49am
ooooh =)
you're right ofc!
i've just never used it like this...

because in c, the sign of the remainder is implementation defined... here a sentence i found on wikipedia:
"the binary % operator yields the remainder from the division of the first expression by the second. .... If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementation-defined"
Member
Posts: 16,144
Joined: Mar 27 2008
Gold: 14,618.00
Mar 26 2013 11:28am
well after thinking about some lines of the code (not all) and searching for errors, i started testing the algorithms... and it seems to work imo ^^ but i'm not 100% sure!

why do you think the algorithm doesn't work?

some prime numbers: (found a list by searching for "prime numbers above 10000000")
10000019
10000079
10000103
10000121
10000139
-> all passed the test

some NOT prime numbers: (i've just taken the prime numbers from above and added a small digit)
10000021
10000083
10000105
10000133
10000141
-> only the last one was detected as to-be-prime. but that seems to be just such a case where the algorithm fails.
here i found a page, on which you can do a miller rabin test. it also fails on this number ;) http://primzahlen.zeta24.com/de/online_primzahltest.php

and the number your prof gave you is also not a prime :)
Member
Posts: 24,396
Joined: Oct 21 2007
Gold: 0.38
Mar 26 2013 09:20pm
Quote (Richter @ Mar 26 2013 12:28pm)
well after thinking about some lines of the code (not all) and searching for errors, i started testing the algorithms... and it seems to work imo ^^ but i'm not 100% sure!

why do you think the algorithm doesn't work?

some prime numbers: (found a list by searching for "prime numbers above 10000000")
10000019
10000079
10000103
10000121
10000139
-> all passed the test

some NOT prime numbers: (i've just taken the prime numbers from above and added a small digit)
10000021
10000083
10000105
10000133
10000141
-> only the last one was detected as to-be-prime. but that seems to be just such a case where the algorithm fails.
here i found a page, on which you can do a miller rabin test. it also fails on this number ;) http://primzahlen.zeta24.com/de/online_primzahltest.php

and the number your prof gave you is also not a prime :)


I was under the impression that it should print stars would have to be printed first, if any, then -1's, then 1's. All 1's is fine. On a few tests (for example your 10000121) it gave stuff like:
Code
* -1 1 -1 1
* * -1 * 1


Which implies a fail I thought.
Member
Posts: 24,396
Joined: Oct 21 2007
Gold: 0.38
Mar 26 2013 09:45pm
The reading on this subject if it helps... generally this stuff is much much more straightforward which leaves me to believe I'm overlooking something dumb.

Quote
4.2 The Miller-Rabin test
The most commonly used probabilistic primality test is the Miller-Rabin
test. This test, which is a variant of Fermat’s test, cannot be fooled by
Carmichael numbers. If the numbers a that we use to test are chosen at
random, then the probability that a composite n will pass the test is less
than 1/2. So if we test 20 times in succession, choosing the numbers a
independently, then the probability of a composite passing these 20 tests is
less than 1/2^20, that is, less than 1 in a million.
Here is the test. You are given a number n that wish to test for primality.
Write n - 1 = 2^s*d where d is odd. This is always possible: you just keep
dividing n - 1 by 2 until you get an odd number. For the test, you choose a
number a at random so that 0 < a < n. Then you compute x = a^d (mod n).
The test is to consider, modulo n, the sequence
x, x^2, x^4, x^8, . . . , x^2^s
There are s + 1 terms in this sequence (because the exponents of x are
0,1,2,3, . . ., 2^s), and the last is x^2^s = a^(d*2^s) = a^(n-1). Of course the last
term should be 1— that’s Fermat’s test.
22
The key observation for the test is that if z^2 = 1 modulo n, and n is a
prime, then z = 1 modulo n. That’s because if z^2 - 1 = (z - 1) (z + 1) is
divisible by a prime n, then n has to divide either z - 1 or z + 1.
Now each term in our sequence is the square of the previous term. So if a
term is 1, and the last term must be 1 or we would reject the hypothesis that
n was a prime, then the previous term must be 1. If that doesn’t happen,
we reject the hypothesis that n is a prime. So the good sequences look like
1; 1; 1; 1; 1; 1; 1; 1
-1; 1; 1; 1; 1; 1; 1
*; *; *;-1; 1; 1; 1
where  is a number di¤erent from 1. The bad sequences look like
*; *; *; 1; 1; 1; 1
*; *; *; *; *; *;-1
*; *; *; *; *; *; 
The bad sequences either don’t end in 1, so the Fermat test fails, or they
contain a 1 immediately following a .
If we denote the sequence by t0; t1; t2; : : : ; ts, then for the sequence to be
good we must have ts = 1 and there must not be an index i such that ti != ±1
and ti+1 = 1. You don’t need a list to perform this test, but you may …n^d
it convenient. Just compute x, keep squaring it, looking for the forbidden
z != 1 and z^2 = 1, and make sure that x^2^s = 1. While developing this
program you might want to print out the sequence t0; t1; t2; : : : ; ts.
Try this test out on the largest Carmichael numbers above.
If you …nd that a number passes the Fermat test, but fails the Miller-
Rabin test, then you will have computed a number x so that x != 1 (mod n)
but x^2 = 1 (mod n). So n divides (x - 1) (x + 1), but n does not divide
either x - 1 or x + 1. In that case, gcd (x - 1; n) has to be a proper fac-
tor of n, showing directly that n is not prime. This gives a quick way of
factoring because the Euclidean algorithm is very fast. For example, for
the number 56052361, and the random number 40202214, the sequence is
55252883; 1; 1; 1, so gcd (55252882; 56052361) = 88831 is a factor of 56052361.


This post was edited by DeadlySanity on Mar 26 2013 09:58pm
Member
Posts: 16,144
Joined: Mar 27 2008
Gold: 14,618.00
Mar 27 2013 06:11am
oh, true, i've overlooked that one :)

imo the s_d calculation is right.
to find the error i set the random number a=3 (just one case where the result fails)
to simplify i set the s_d[0] to s and s_d[1] to d
now i have a problem, the iteration variable is 's', so i rename it to 'i'
the code gets:
Code

def MR(n):
 n = 10000121
 a = 3
 s_d = sd(n)
 s = s_d[0]
 d = s_d[1]
 print "a:",
 print a
 print "s:",
 print s
 print "d:",
 print d
 x  = pow(a, d, n)
 MR = [x]
 print '0',
 for i in xrange(2, pow(2,s)+1, 2):
   print i,
   MR += [pow(x,i,n)]
 print
 return MR

if you look at the output of the prints, you see that you first start with
x^0, then with x^2 then x^4 (correct so far) but then you calculate x^6 instead of x^16

problem: you need to square each 'i' for the next step, instead of just adding '2'
Member
Posts: 24,396
Joined: Oct 21 2007
Gold: 0.38
Mar 27 2013 07:09am
Quote (Richter @ Mar 27 2013 07:11am)
oh, true, i've overlooked that one :)

imo the s_d calculation is right.
to find the error i set the random number a=3 (just one case where the result fails)
to simplify i set the s_d[0] to s and s_d[1] to d
now i have a problem, the iteration variable is 's', so i rename it to 'i'
the code gets:
Code
def MR(n):
 n = 10000121
 a = 3
 s_d = sd(n)
 s = s_d[0]
 d = s_d[1]
 print "a:",
 print a
 print "s:",
 print s
 print "d:",
 print d
 x  = pow(a, d, n)
 MR = [x]
 print '0',
 for i in xrange(2, pow(2,s)+1, 2):
   print i,
   MR += [pow(x,i,n)]
 print
 return MR

if you look at the output of the prints, you see that you first start with
x^0, then with x^2 then x^4 (correct so far) but then you calculate x^6 instead of x^16

problem: you need to square each 'i' for the next step, instead of just adding '2'


I love you...

I don't know why at the time I thought that was right, I knew what I was supposed to do. Thanks so much. <3
Member
Posts: 16,144
Joined: Mar 27 2008
Gold: 14,618.00
Mar 27 2013 08:22am
thx =) love you too ;)
<3
Go Back To Programming & Development Topic List
Add Reply New Topic New Poll