Skip to content

Commit e40d4a2

Browse files
anirudnitscclauss
authored andcommitted
Added Matrix Exponentiation (#1203)
* Added the matrix_exponentiation.py file in maths directory * Implemented the requested changes * Update matrix_exponentiation.py
1 parent 01601e6 commit e40d4a2

File tree

1 file changed

+99
-0
lines changed

1 file changed

+99
-0
lines changed

Diff for: maths/matrix_exponentiation.py

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
"""Matrix Exponentiation"""
2+
3+
import timeit
4+
5+
"""
6+
Matrix Exponentiation is a technique to solve linear recurrences in logarithmic time.
7+
You read more about it here:
8+
http://zobayer.blogspot.com/2010/11/matrix-exponentiation.html
9+
https://www.hackerearth.com/practice/notes/matrix-exponentiation-1/
10+
"""
11+
12+
13+
class Matrix(object):
14+
def __init__(self, arg):
15+
if isinstance(arg, list): # Initialzes a matrix identical to the one provided.
16+
self.t = arg
17+
self.n = len(arg)
18+
else: # Initializes a square matrix of the given size and set the values to zero.
19+
self.n = arg
20+
self.t = [[0 for _ in range(self.n)] for _ in range(self.n)]
21+
22+
def __mul__(self, b):
23+
matrix = Matrix(self.n)
24+
for i in range(self.n):
25+
for j in range(self.n):
26+
for k in range(self.n):
27+
matrix.t[i][j] += self.t[i][k] * b.t[k][j]
28+
return matrix
29+
30+
31+
def modular_exponentiation(a, b):
32+
matrix = Matrix([[1, 0], [0, 1]])
33+
while b > 0:
34+
if b & 1:
35+
matrix *= a
36+
a *= a
37+
b >>= 1
38+
return matrix
39+
40+
41+
def fibonacci_with_matrix_exponentiation(n, f1, f2):
42+
# Trivial Cases
43+
if n == 1:
44+
return f1
45+
elif n == 2:
46+
return f2
47+
matrix = Matrix([[1, 1], [1, 0]])
48+
matrix = modular_exponentiation(matrix, n - 2)
49+
return f2 * matrix.t[0][0] + f1 * matrix.t[0][1]
50+
51+
52+
def simple_fibonacci(n, f1, f2):
53+
# Trival Cases
54+
if n == 1:
55+
return f1
56+
elif n == 2:
57+
return f2
58+
59+
fn_1 = f1
60+
fn_2 = f2
61+
n -= 2
62+
63+
while n > 0:
64+
fn_1, fn_2 = fn_1 + fn_2, fn_1
65+
n -= 1
66+
67+
return fn
68+
69+
70+
def matrix_exponentiation_time():
71+
setup = """
72+
from random import randint
73+
from __main__ import fibonacci_with_matrix_exponentiation
74+
"""
75+
code = "fibonacci_with_matrix_exponentiation(randint(1,70000), 1, 1)"
76+
exec_time = timeit.timeit(setup=setup, stmt=code, number=100)
77+
print("With matrix exponentiation the average execution time is ", exec_time / 100)
78+
return exec_time
79+
80+
81+
def simple_fibonacci_time():
82+
setup = """
83+
from random import randint
84+
from __main__ import simple_fibonacci
85+
"""
86+
code = "simple_fibonacci(randint(1,70000), 1, 1)"
87+
exec_time = timeit.timeit(setup=setup, stmt=code, number=100)
88+
print("Without matrix exponentiation the average execution time is ",
89+
exec_time / 100)
90+
return exec_time
91+
92+
93+
def main():
94+
matrix_exponentiation_time()
95+
simple_fibonacci_time()
96+
97+
98+
if __name__ == "__main__":
99+
main()

0 commit comments

Comments
 (0)