1+ def multiply (matA : list , matB : list ) -> list :
2+ """
3+ Multiplies two square matrices matA and matB od size n x n
4+ Time Complexity: O(n^3)
5+ """
6+ n = len (matA )
7+ matC = [[0 for i in range (n )] for j in range (n )]
8+
9+ for i in range (n ):
10+ for j in range (n ):
11+ for k in range (n ):
12+ matC [i ][j ] += matA [i ][k ] * matB [k ][j ]
13+
14+ return matC
15+
16+ def identity (n : int ) -> list :
17+ """
18+ Returns the Identity matrix of size n x n
19+ Time Complecity: O(n^2)
20+ """
21+ I = [[0 for i in range (n )] for j in range (n )]
22+
23+ for i in range (n ):
24+ I [i ][i ] = 1
25+
26+ return I
27+
28+ def matrix_exponentiation (mat : list , n : int ) -> list :
29+ """
30+ Calculates mat^n by repeated squaring
31+ Time Complexity: O(d^3 log(n))
32+ d: dimesion of the square matrix mat
33+ n: power the matrix is raised to
34+ """
35+ if n == 0 :
36+ return identity (len (mat ))
37+ elif n % 2 == 1 :
38+ return multiply (matrix_exponentiation (mat , n - 1 ), mat )
39+ else :
40+ tmp = matrix_exponentiation (mat , n // 2 )
41+ return multiply (tmp , tmp )
42+
43+ if __name__ == "__main__" :
44+ mat = [[1 , 0 , 2 ], [2 , 1 , 0 ], [0 , 2 , 1 ]]
45+
46+ res0 = matrix_exponentiation (mat , 0 )
47+ assert res0 == [[1 , 0 , 0 ], [0 , 1 , 0 ], [0 , 0 , 1 ]]
48+ print (f"{ mat } ^0 = { res0 } " )
49+
50+ res1 = matrix_exponentiation (mat , 1 )
51+ assert res1 == [[1 , 0 , 2 ], [2 , 1 , 0 ], [0 , 2 , 1 ]]
52+ print (f"{ mat } ^1 = { res1 } " )
53+
54+ res2 = matrix_exponentiation (mat , 2 )
55+ assert res2 == [[1 , 4 , 4 ], [4 , 1 , 4 ], [4 , 4 , 1 ]]
56+ print (f"{ mat } ^2 = { res2 } " )
57+
58+ res5 = matrix_exponentiation (mat , 5 )
59+ assert res5 == [[81 , 72 , 90 ], [90 , 81 , 72 ], [72 , 90 , 81 ]]
60+ print (f"{ mat } ^5 = { res5 } " )
0 commit comments