Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions divide_and_conquer/strassen_matrix_multiplication.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,19 @@ def actual_strassen(matrix_a: list, matrix_b: list) -> list:
"""
Recursive function to calculate the product of two matrices, using the Strassen
Algorithm. It only supports square matrices of any size that is a power of 2.

Strassen's algorithm reduces the number of recursive multiplications needed to
multiply two n x n matrices from the 8 required by the naive divide-and-conquer
approach down to 7, at the cost of a few extra matrix additions/subtractions
(which are cheaper, O(n^2), operations). Each matrix is split into four
(n/2) x (n/2) quadrants, 7 products of quadrant combinations are computed
recursively, and those products are combined with additions/subtractions to
form the four quadrants of the result.

Time complexity: O(n^log2(7)) ~= O(n^2.807), an improvement over the O(n^3) of
the standard/naive matrix multiplication algorithm.
Space complexity: O(n^2) for storing the intermediate quadrant matrices, plus
O(log n) recursion stack depth.
"""
if matrix_dimensions(matrix_a) == (2, 2):
return default_matrix_multiplication(matrix_a, matrix_b)
Expand Down Expand Up @@ -106,6 +119,13 @@ def actual_strassen(matrix_a: list, matrix_b: list) -> list:

def strassen(matrix1: list, matrix2: list) -> list:
"""
Multiplies two matrices using Strassen's algorithm, which runs in
O(n^log2(7)) ~= O(n^2.807) time, compared to O(n^3) for naive matrix
multiplication. This implementation pads both input matrices with zeros
until they are square matrices whose dimension is a power of 2 (required
by the divide-and-conquer recursion in actual_strassen), performs the
multiplication, then trims the padding back off the result.

>>> strassen([[2,1,3],[3,4,6],[1,4,2],[7,6,7]], [[4,2,3,4],[2,1,1,1],[8,6,4,2]])
[[34, 23, 19, 15], [68, 46, 37, 28], [28, 18, 15, 12], [96, 62, 55, 48]]
>>> strassen([[3,7,5,6,9],[1,5,3,7,8],[1,4,4,5,7]], [[2,4],[5,2],[1,7],[5,5],[7,8]])
Expand Down