Skip to content

Commit 50707ea

Browse files
Create matrix_operations.py
Implements comprehensive matrix operations module with: - Matrix multiplication using standard algorithm (O(n*m*p) complexity) - Matrix transpose operation (O(n*m) complexity) - Determinant calculation using recursive cofactor expansion (O(n!) complexity) - Sparse matrix conversion to/from COO format Each function includes: - Detailed algorithm descriptions - Time and space complexity analysis - Comprehensive docstrings with examples - Input validation and error handling - Practical usage examples in __main__ section
1 parent a748c54 commit 50707ea

1 file changed

Lines changed: 256 additions & 0 deletions

File tree

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
"""Matrix Operations Module
2+
3+
This module provides comprehensive matrix operations including:
4+
- Matrix multiplication
5+
- Matrix transpose
6+
- Determinant calculation
7+
- Sparse matrix conversion
8+
9+
Each function includes detailed comments, complexity analysis, and examples.
10+
"""
11+
12+
def matrix_multiply(matrix_a, matrix_b):
13+
"""Multiply two matrices using standard algorithm.
14+
15+
Algorithm:
16+
- For each element (i,j) in result matrix, compute dot product
17+
of row i from matrix_a with column j from matrix_b
18+
- Time Complexity: O(n * m * p) where matrix_a is n×m and matrix_b is m×p
19+
- Space Complexity: O(n * p) for result matrix
20+
21+
Args:
22+
matrix_a: First matrix (list of lists)
23+
matrix_b: Second matrix (list of lists)
24+
25+
Returns:
26+
Resulting matrix from multiplication
27+
28+
Example:
29+
>>> A = [[1, 2], [3, 4]]
30+
>>> B = [[5, 6], [7, 8]]
31+
>>> matrix_multiply(A, B)
32+
[[19, 22], [43, 50]]
33+
"""
34+
if not matrix_a or not matrix_b:
35+
raise ValueError("Matrices cannot be empty")
36+
37+
rows_a = len(matrix_a)
38+
cols_a = len(matrix_a[0])
39+
rows_b = len(matrix_b)
40+
cols_b = len(matrix_b[0])
41+
42+
# Check if multiplication is possible
43+
if cols_a != rows_b:
44+
raise ValueError(f"Cannot multiply: columns of A ({cols_a}) != rows of B ({rows_b})")
45+
46+
# Initialize result matrix with zeros
47+
result = [[0 for _ in range(cols_b)] for _ in range(rows_a)]
48+
49+
# Perform multiplication
50+
for i in range(rows_a):
51+
for j in range(cols_b):
52+
# Compute dot product of row i and column j
53+
for k in range(cols_a):
54+
result[i][j] += matrix_a[i][k] * matrix_b[k][j]
55+
56+
return result
57+
58+
59+
def matrix_transpose(matrix):
60+
"""Transpose a matrix by swapping rows and columns.
61+
62+
Algorithm:
63+
- Create new matrix where element (i,j) becomes element (j,i)
64+
- Time Complexity: O(n * m) where matrix is n×m
65+
- Space Complexity: O(n * m) for transposed matrix
66+
67+
Args:
68+
matrix: Input matrix (list of lists)
69+
70+
Returns:
71+
Transposed matrix
72+
73+
Example:
74+
>>> M = [[1, 2, 3], [4, 5, 6]]
75+
>>> matrix_transpose(M)
76+
[[1, 4], [2, 5], [3, 6]]
77+
"""
78+
if not matrix:
79+
return []
80+
81+
rows = len(matrix)
82+
cols = len(matrix[0])
83+
84+
# Create transposed matrix
85+
transposed = [[matrix[i][j] for i in range(rows)] for j in range(cols)]
86+
87+
return transposed
88+
89+
90+
def calculate_determinant(matrix):
91+
"""Calculate determinant of a square matrix using recursive cofactor expansion.
92+
93+
Algorithm:
94+
- Base case: 1×1 matrix returns the single element
95+
- Base case: 2×2 matrix uses formula ad - bc
96+
- Recursive case: Expand along first row using cofactors
97+
- Time Complexity: O(n!) due to recursive expansion
98+
- Space Complexity: O(n²) for recursive call stack and submatrices
99+
100+
Args:
101+
matrix: Square matrix (list of lists)
102+
103+
Returns:
104+
Determinant value (float or int)
105+
106+
Example:
107+
>>> M = [[4, 3], [6, 3]]
108+
>>> calculate_determinant(M)
109+
-6
110+
>>> M = [[1, 2, 3], [0, 1, 4], [5, 6, 0]]
111+
>>> calculate_determinant(M)
112+
1
113+
"""
114+
if not matrix:
115+
raise ValueError("Matrix cannot be empty")
116+
117+
n = len(matrix)
118+
119+
# Check if matrix is square
120+
for row in matrix:
121+
if len(row) != n:
122+
raise ValueError("Matrix must be square")
123+
124+
# Base case: 1x1 matrix
125+
if n == 1:
126+
return matrix[0][0]
127+
128+
# Base case: 2x2 matrix
129+
if n == 2:
130+
return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]
131+
132+
# Recursive case: cofactor expansion along first row
133+
determinant = 0
134+
for j in range(n):
135+
# Create minor matrix by removing row 0 and column j
136+
minor = [[matrix[i][k] for k in range(n) if k != j]
137+
for i in range(1, n)]
138+
139+
# Calculate cofactor: (-1)^(0+j) * matrix[0][j] * det(minor)
140+
cofactor = ((-1) ** j) * matrix[0][j] * calculate_determinant(minor)
141+
determinant += cofactor
142+
143+
return determinant
144+
145+
146+
def to_sparse_matrix(matrix, threshold=0):
147+
"""Convert dense matrix to sparse representation (COO format).
148+
149+
Algorithm:
150+
- Scan all matrix elements
151+
- Store only non-zero elements (or above threshold) with their positions
152+
- COO format: list of (row, col, value) tuples
153+
- Time Complexity: O(n * m) where matrix is n×m
154+
- Space Complexity: O(k) where k is number of non-zero elements
155+
156+
Args:
157+
matrix: Dense matrix (list of lists)
158+
threshold: Values above this are considered non-zero (default: 0)
159+
160+
Returns:
161+
Dictionary with 'shape' and 'data' (list of (row, col, value) tuples)
162+
163+
Example:
164+
>>> M = [[1, 0, 0], [0, 5, 0], [0, 0, 9]]
165+
>>> to_sparse_matrix(M)
166+
{'shape': (3, 3), 'data': [(0, 0, 1), (1, 1, 5), (2, 2, 9)]}
167+
"""
168+
if not matrix:
169+
return {'shape': (0, 0), 'data': []}
170+
171+
rows = len(matrix)
172+
cols = len(matrix[0]) if matrix[0] else 0
173+
174+
# Store non-zero elements
175+
sparse_data = []
176+
for i in range(rows):
177+
for j in range(len(matrix[i])):
178+
if matrix[i][j] > threshold:
179+
sparse_data.append((i, j, matrix[i][j]))
180+
181+
return {
182+
'shape': (rows, cols),
183+
'data': sparse_data
184+
}
185+
186+
187+
def from_sparse_matrix(sparse_dict):
188+
"""Convert sparse matrix representation back to dense matrix.
189+
190+
Algorithm:
191+
- Initialize matrix with zeros
192+
- Fill in values from sparse data
193+
- Time Complexity: O(n * m + k) where k is number of non-zero elements
194+
- Space Complexity: O(n * m) for dense matrix
195+
196+
Args:
197+
sparse_dict: Dictionary with 'shape' and 'data' keys
198+
199+
Returns:
200+
Dense matrix (list of lists)
201+
202+
Example:
203+
>>> sparse = {'shape': (2, 3), 'data': [(0, 0, 5), (1, 2, 7)]}
204+
>>> from_sparse_matrix(sparse)
205+
[[5, 0, 0], [0, 0, 7]]
206+
"""
207+
rows, cols = sparse_dict['shape']
208+
209+
# Initialize matrix with zeros
210+
matrix = [[0 for _ in range(cols)] for _ in range(rows)]
211+
212+
# Fill in non-zero values
213+
for row, col, value in sparse_dict['data']:
214+
matrix[row][col] = value
215+
216+
return matrix
217+
218+
219+
if __name__ == "__main__":
220+
# Example usage and testing
221+
print("Matrix Operations Examples\n" + "="*50)
222+
223+
# Example 1: Matrix Multiplication
224+
print("\n1. Matrix Multiplication:")
225+
A = [[1, 2], [3, 4]]
226+
B = [[5, 6], [7, 8]]
227+
print(f"A = {A}")
228+
print(f"B = {B}")
229+
result = matrix_multiply(A, B)
230+
print(f"A × B = {result}")
231+
232+
# Example 2: Matrix Transpose
233+
print("\n2. Matrix Transpose:")
234+
M = [[1, 2, 3], [4, 5, 6]]
235+
print(f"Original: {M}")
236+
print(f"Transposed: {matrix_transpose(M)}")
237+
238+
# Example 3: Determinant Calculation
239+
print("\n3. Determinant Calculation:")
240+
M2 = [[4, 3], [6, 3]]
241+
print(f"Matrix: {M2}")
242+
print(f"Determinant: {calculate_determinant(M2)}")
243+
244+
M3 = [[1, 2, 3], [0, 1, 4], [5, 6, 0]]
245+
print(f"\nMatrix: {M3}")
246+
print(f"Determinant: {calculate_determinant(M3)}")
247+
248+
# Example 4: Sparse Matrix Conversion
249+
print("\n4. Sparse Matrix Conversion:")
250+
dense = [[1, 0, 0, 0], [0, 5, 0, 0], [0, 0, 9, 0], [0, 0, 0, 0]]
251+
print(f"Dense matrix: {dense}")
252+
sparse = to_sparse_matrix(dense)
253+
print(f"Sparse representation: {sparse}")
254+
print(f"Converted back: {from_sparse_matrix(sparse)}")
255+
256+
print("\n" + "="*50)

0 commit comments

Comments
 (0)