You are on page 1of 6

RA_Assg1

May 12, 2020

0.1 Assignment

0.1.1 Matrix Multiplication Check

• To check if the provided product of multiplying two square matrices is indeed their product

Single Run
• Freivalds Algorithm
– Choose a random binary vector r ie, Pr [ri = 1] = 1/2 independently for i = 1, ..., n
– If A( Br ) = Cr, output Yes
– Else, output No
Source
[0]: import numpy as np

def check_matrix_multiplication(A, B, C) -> int:


'''
Input:
A - First nxn matrix that was multiplied
B - Second nxn matrix that was multiplied
C - Output of multiplication of A & B

Output:
1, if C is the actual product of AB with P >= 1/2
0 else

'''
# check dim of A & B matches
assert A.shape == B.shape
n = A.shape[0]

# https://docs.scipy.org/doc/numpy-1.16.0/reference/generated/numpy.random.
,→ randint.html
r = np.random.randint(2, size=n)

left_product = np.dot(A, np.dot(B, r))

1
right_product = np.dot(C, r)

verdict = True if (np.array_equal(left_product, right_product)) else False

print(f"Frievald's algorithm says that C is {str(verdict)}ly the product of A␣


,→& B for r = {r}")

return int(verdict)

[0]: A = np.array([[2, 3],


[3, 4]])
B = np.array([[1, 0],
[1, 2]])
C = np.array([[6, 5],
[8, 7]])

sum = 0
iter = 10
for i in range(iter):
output = check_matrix_multiplication(A, B, C)
sum += output

print(f"\n\nThe algorithm was correct {(iter-sum)}/{iter} times")

Frievald's algorithm says that C is Truely the product of A & B for r = [1 1]


Frievald's algorithm says that C is Falsely the product of A & B for r = [0 1]
Frievald's algorithm says that C is Falsely the product of A & B for r = [0 1]
Frievald's algorithm says that C is Falsely the product of A & B for r = [1 0]
Frievald's algorithm says that C is Truely the product of A & B for r = [0 0]
Frievald's algorithm says that C is Falsely the product of A & B for r = [0 1]
Frievald's algorithm says that C is Truely the product of A & B for r = [0 0]
Frievald's algorithm says that C is Falsely the product of A & B for r = [1 0]
Frievald's algorithm says that C is Truely the product of A & B for r = [0 0]
Frievald's algorithm says that C is Truely the product of A & B for r = [0 0]

The algorithm was correct 5/10 times


• For r = [0, 1] & r = [1, 0], Frievald’s algorithm correctly outputs that C isn’t product of A &
B whereas otherwise for the other 2 r values
• So, for half of the values the output is correct ie, the algorithm is True with Pr = 1/2

Multiple runs
• Now, we can run the algorithm multiple times when it outputs true to further increase the
probability of correctness

2
[0]: def check_matrix_multiplication_repeat(A, B, C, k) -> int:
'''
Input:
A - First nxn matrix that was multiplied
B - Second nxn matrix that was multiplied
C - Output of multiplication of A & B
k - maximum number of repeats

Output:
1, if C is the actual product of AB with P >= 1/2
0 else

'''
# check dim of A & B matches
assert A.shape == B.shape
n = A.shape[0]

counter = k
verdict = True
# repeat the algorithm if
# algorithm outputs True, and
# hasn't reached max number of repeats
while(verdict == True and counter > 0):
r = np.random.randint(2, size=n)

left_product = np.dot(A, np.dot(B, r))


right_product = np.dot(C, r)

verdict = True if (np.array_equal(left_product, right_product)) else False

counter -= 1

print(f"Frievald's algorithm says that C is {str(verdict)}ly the product of A␣


& B for r = {r} with probability {1 - (0.5 ** k)}")
,→

return int(verdict)

[0]: A = np.array([[2, 3],


[3, 4]])
B = np.array([[1, 0],
[1, 2]])
C = np.array([[6, 5],
[8, 7]])

sum = 0
iter = 10

3
for i in range(iter):
output = check_matrix_multiplication_repeat(A, B, C, 5)
sum += output

print(f"\n\nThe algorithm was correct {(iter-sum)}/{iter} times")

Frievald's algorithm says that C is Falsely the product of A & B for r = [0 1]


with probability 0.96875
Frievald's algorithm says that C is Falsely the product of A & B for r = [1 0]
with probability 0.96875
Frievald's algorithm says that C is Falsely the product of A & B for r = [0 1]
with probability 0.96875
Frievald's algorithm says that C is Falsely the product of A & B for r = [0 1]
with probability 0.96875
Frievald's algorithm says that C is Falsely the product of A & B for r = [1 0]
with probability 0.96875
Frievald's algorithm says that C is Falsely the product of A & B for r = [1 0]
with probability 0.96875
Frievald's algorithm says that C is Falsely the product of A & B for r = [1 0]
with probability 0.96875
Frievald's algorithm says that C is Falsely the product of A & B for r = [0 1]
with probability 0.96875
Frievald's algorithm says that C is Falsely the product of A & B for r = [0 1]
with probability 0.96875
Frievald's algorithm says that C is Falsely the product of A & B for r = [1 0]
with probability 0.96875

The algorithm was correct 10/10 times


References: 1. Randomization: Matrix Multiply, Quicksort 2. Freivald’s Algorithm - Wiki

0.1.2 Miller-Rabin Primality Testing

Algorithm:
To check if a natural number is prime or not
1. Find n − 1 = 2k ∗ m
2. Choose: a where 1 < a < n − 1
3. Compute b0 = am (modn), bi = bi2−1
Ref1 Ref2
[0]: import random

def check_primality(n, r):


"""

4
Input #1: n > 3, an odd integer to be tested for primality
Input #2: r, the number of rounds of testing to perform
Output: âĂIJcompositeâĂİ if n is found to be composite, âĂIJprobably primeâĂİ␣
,→otherwise

"""

if n % 2 == 0:
return False

# 1. Find m
m, k = find_params(n)
print('k: ', k, ' m: ', m)
for i in range(r):
print('i: ', i)
# 2. Choose 'a' randomly in the range [2, n-1]
a = random.randint(2, n - 1)
print('a: ', a)
# 3. Check condition & repeat accordingly
bi = (a ** m) % n
print('bi: ', bi)
if (bi in [1, n-1]):
# repeat experiment to increase correctness probability
continue
else:
for j in range(k - 1):
print('j: ', j)
bi = (bi ** 2) % n
print('bi: ', bi)
if (bi == n - 1):
break

# check if the for loop ran the whole cycle


if bi != (n-1):
return False

return True

def find_params(n):
"""
Input: n, natural number
Output: number remaining after dividing largest multiple of 2 from n -1
"""
m = n - 1
k = 0

while m % 2 == 0:
m /= 2

5
k += 1

return int(m), k

[55]: check_primality(15, 1)

k: 1 m: 7
i: 0
a: 5
bi: 5

[55]: False

[56]: check_primality(29, 1)

k: 2 m: 7
i: 0
a: 3
bi: 12
j: 0
bi: 28

[56]: True

[57]: check_primality(53, 1)

k: 2 m: 13
i: 0
a: 25
bi: 52

[57]: True

[58]: check_primality(53, 2)

k: 2 m: 13
i: 0
a: 12
bi: 23
j: 0
bi: 52
i: 1
a: 38
bi: 52

[58]: True

You might also like