forked from TheAlgorithms/Python
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmatrix_multiplication_recursion.py
149 lines (130 loc) · 4.14 KB
/
matrix_multiplication_recursion.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
# @Author : ojas-wani
# @File : matrix_multiplication_recursion.py
# @Date : 10/06/2023
"""
Perform matrix multiplication using a recursive algorithm.
https://en.wikipedia.org/wiki/Matrix_multiplication
"""
# type Matrix = list[list[int]] # psf/black currenttly fails on this line
Matrix = list[list[int]]
matrix_1_to_4 = [
[1, 2],
[3, 4],
]
matrix_5_to_8 = [
[5, 6],
[7, 8],
]
matrix_5_to_9_wide = [
[5, 6],
[7, 8, 9],
]
matrix_5_to_9_high = [
[5, 6],
[7, 8],
[9],
]
matrix_count_up = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
[13, 14, 15, 16],
]
matrix_unordered = [
[5, 8, 1, 2],
[6, 7, 3, 0],
[4, 5, 9, 1],
[2, 6, 10, 14],
]
matrices = (
matrix_1_to_4,
matrix_5_to_8,
matrix_5_to_9_wide,
matrix_5_to_9_high,
matrix_count_up,
matrix_unordered,
)
def is_square(matrix: Matrix) -> bool:
len_matrix = len(matrix)
return all(len(row) == len_matrix for row in matrix)
def matrix_multiply_recursive(matrix_a: Matrix, matrix_b: Matrix) -> Matrix:
"""
:param matrix_a: A square Matrix.
:param matrix_b: Another square Matrix with the same dimensions as matrix_a.
:return: Result of matrix_a * matrix_b.
:raises ValueError: If the matrices cannot be multiplied.
>>> matrix_multiply_recursive([], [])
[]
>>> matrix_multiply_recursive(matrix_1_to_4, matrix_5_to_8)
[[19, 22], [43, 50]]
>>> matrix_multiply_recursive(matrix_count_up, matrix_unordered)
[[37, 61, 74, 61], [105, 165, 166, 129], [173, 269, 258, 197], [241, 373, 350, 265]]
>>> matrix_multiply_recursive(matrix_1_to_4, matrix_5_to_9_wide)
Traceback (most recent call last):
...
ValueError: Invalid matrix dimensions
>>> matrix_multiply_recursive(matrix_1_to_4, matrix_5_to_9_high)
Traceback (most recent call last):
...
ValueError: Invalid matrix dimensions
>>> matrix_multiply_recursive(matrix_1_to_4, matrix_count_up)
Traceback (most recent call last):
...
ValueError: Invalid matrix dimensions
"""
if not matrix_a or not matrix_b:
return []
if not all(
(len(matrix_a) == len(matrix_b), is_square(matrix_a), is_square(matrix_b))
):
raise ValueError("Invalid matrix dimensions")
# Initialize the result matrix with zeros
result = [[0] * len(matrix_b[0]) for _ in range(len(matrix_a))]
# Recursive multiplication of matrices
def multiply(
i_loop: int,
j_loop: int,
k_loop: int,
matrix_a: Matrix,
matrix_b: Matrix,
result: Matrix,
) -> None:
"""
:param matrix_a: A square Matrix.
:param matrix_b: Another square Matrix with the same dimensions as matrix_a.
:param result: Result matrix
:param i: Index used for iteration during multiplication.
:param j: Index used for iteration during multiplication.
:param k: Index used for iteration during multiplication.
"""
if i_loop >= len(matrix_a):
return
if j_loop >= len(matrix_b[0]):
return multiply(i_loop + 1, 0, 0, matrix_a, matrix_b, result)
if k_loop >= len(matrix_b):
return multiply(i_loop, j_loop + 1, 0, matrix_a, matrix_b, result)
result[i_loop][j_loop] += matrix_a[i_loop][k_loop] * matrix_b[k_loop][j_loop]
return multiply(i_loop, j_loop, k_loop + 1, matrix_a, matrix_b, result)
# Perform the recursive matrix multiplication
multiply(0, 0, 0, matrix_a, matrix_b, result)
return result
if __name__ == "__main__":
from doctest import testmod
failure_count, test_count = testmod()
if not failure_count:
matrix_a = matrices[0]
for matrix_b in matrices[1:]:
print("Multiplying:")
for row in matrix_a:
print(row)
print("By:")
for row in matrix_b:
print(row)
print("Result:")
try:
for row in matrix_multiply_recursive(matrix_a, matrix_b):
print(row)
except ValueError as e:
print(f"{e!r}")
print()
matrix_a = matrix_b