Repository: keon/algorithms
Pull request #711 (2020-10-02 12:28:51)

Added Matrix Exponentiation


Patch:
diff --git a/README.md b/README.md
index 54f6c6a..618c4fd 100644
--- a/README.md
+++ b/README.md
@@ -230,6 +230,7 @@ If you want to uninstall algorithms, it is as simple as:
     - [bomb_enemy](algorithms/matrix/bomb_enemy.py)
     - [copy_transform](algorithms/matrix/copy_transform.py)
     - [count_paths](algorithms/matrix/count_paths.py)
+    - [matrix_exponentiation](algorithms/matrix/matrix_exponentiation.py)
     - [matrix_rotation.txt](algorithms/matrix/matrix_rotation.txt)
     - [matrix_inversion](algorithms/matrix/matrix_inversion.py)
     - [matrix_multiplication](algorithms/matrix/multiply.py)
diff --git a/algorithms/matrix/__init__.py b/algorithms/matrix/__init__.py
index 8b13789..e69de29 100644
--- a/algorithms/matrix/__init__.py
+++ b/algorithms/matrix/__init__.py
@@ -1,1 +0,0 @@
-
diff --git a/algorithms/matrix/matrix_exponentiation.py b/algorithms/matrix/matrix_exponentiation.py
new file mode 100644
index 0000000..f842bc2
--- /dev/null
+++ b/algorithms/matrix/matrix_exponentiation.py
@@ -0,0 +1,41 @@
+def multiply(matA: list, matB: list) -> list:
+    """
+    Multiplies two square matrices matA and matB od size n x n
+    Time Complexity: O(n^3)
+    """
+    n = len(matA)
+    matC = [[0 for i in range(n)] for j in range(n)]
+
+    for i in range(n):
+        for j in range(n):
+            for k in range(n):
+                matC[i][j] += matA[i][k] * matB[k][j]
+
+    return matC
+
+def identity(n: int) -> list:
+    """
+    Returns the Identity matrix of size n x n
+    Time Complecity: O(n^2)
+    """
+    I = [[0 for i in range(n)] for j in range(n)]
+    
+    for i in range(n):
+        I[i][i] = 1
+    
+    return I
+
+def matrix_exponentiation(mat: list, n: int) -> list:
+    """
+    Calculates mat^n by repeated squaring
+    Time Complexity: O(d^3 log(n))
+                     d: dimesion of the square matrix mat
+                     n: power the matrix is raised to
+    """
+    if n == 0:
+        return identity(len(mat))
+    elif n % 2 == 1:
+        return multiply(matrix_exponentiation(mat, n - 1), mat)
+    else:
+        tmp = matrix_exponentiation(mat, n // 2)
+        return multiply(tmp, tmp)


Test patch:
diff --git a/tests/test_matrix.py b/tests/test_matrix.py
index da041e0..88a9b6f 100644
--- a/tests/test_matrix.py
+++ b/tests/test_matrix.py
@@ -3,6 +3,7 @@ from algorithms.matrix import (
     copy_transform,
     crout_matrix_decomposition,
     cholesky_matrix_decomposition,
+    matrix_exponentiation,
     matrix_inversion,
     multiply,
     rotate_image,
@@ -159,6 +160,29 @@ class TestInversion(unittest.TestCase):
                                                               [Fraction(13, 53), Fraction(-22, 53), Fraction(5, 53)]])
 
 
+class TestMatrixExponentiation(unittest.TestCase):
+    """[summary]
+    Test for the file matrix_exponentiation.py
+
+    Arguments:
+        unittest {[type]} -- [description]
+    """
+
+    def test_matrix_exponentiation(self):
+        mat = [[1, 0, 2], [2, 1, 0], [0, 2, 1]]
+
+        self.assertEqual(matrix_exponentiation.matrix_exponentiation(mat, 0),
+            [[1, 0, 0], [0, 1, 0], [0, 0, 1]])
+
+        self.assertEqual(matrix_exponentiation.matrix_exponentiation(mat, 1),
+            [[1, 0, 2], [2, 1, 0], [0, 2, 1]])
+
+        self.assertEqual(matrix_exponentiation.matrix_exponentiation(mat, 2),
+            [[1, 4, 4], [4, 1, 4], [4, 4, 1]])
+
+        self.assertEqual(matrix_exponentiation.matrix_exponentiation(mat, 5),
+            [[81, 72, 90], [90, 81, 72], [72, 90, 81]])
+
 
 class TestMultiply(unittest.TestCase):
     """[summary]