Skip to content
Sahithyan's S2
Sahithyan's S2 — Data Structures and Algorithms

Strassen's Algorithm

An efficient algorithm for matrix multiplication that reduces the time complexity compared to the standard matrix multiplication method. The algorithm works by dividing each matrix into smaller submatrices and recursively performing multiplications and additions.

Explanation

Suppose 2 matrices and are given. is to be calculated. and are broken into smaller square submatrices, and the multiplication is performed recursively.

  1. Divide the matrices and into four submatrices:
  1. Compute the following 7 products (Strassen’s formulas):
  2. Combine the results to compute the submatrices of :
  3. Reconstruct the resulting matrix :

Implementation

#include <iostream>
#include <vector>
using namespace std;
typedef vector<vector<int>> Matrix;
Matrix add(const Matrix &A, const Matrix &B) {
int n = A.size();
Matrix result(n, vector<int>(n));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
result[i][j] = A[i][j] + B[i][j];
return result;
}
Matrix subtract(const Matrix &A, const Matrix &B) {
int n = A.size();
Matrix result(n, vector<int>(n));
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
result[i][j] = A[i][j] - B[i][j];
return result;
}
Matrix strassen(const Matrix &A, const Matrix &B) {
int n = A.size();
if (n == 1) {
return {{A[0][0] * B[0][0]}};
}
int newSize = n / 2;
Matrix A11(newSize, vector<int>(newSize)), A12(newSize, vector<int>(newSize)),
A21(newSize, vector<int>(newSize)), A22(newSize, vector<int>(newSize)),
B11(newSize, vector<int>(newSize)), B12(newSize, vector<int>(newSize)),
B21(newSize, vector<int>(newSize)), B22(newSize, vector<int>(newSize));
for (int i = 0; i < newSize; ++i) {
for (int j = 0; j < newSize; ++j) {
A11[i][j] = A[i][j];
A12[i][j] = A[i][j + newSize];
A21[i][j] = A[i + newSize][j];
A22[i][j] = A[i + newSize][j + newSize];
B11[i][j] = B[i][j];
B12[i][j] = B[i][j + newSize];
B21[i][j] = B[i + newSize][j];
B22[i][j] = B[i + newSize][j + newSize];
}
}
Matrix M1 = strassen(add(A11, A22), add(B11, B22));
Matrix M2 = strassen(add(A21, A22), B11);
Matrix M3 = strassen(A11, subtract(B12, B22));
Matrix M4 = strassen(A22, subtract(B21, B11));
Matrix M5 = strassen(add(A11, A12), B22);
Matrix M6 = strassen(subtract(A21, A11), add(B11, B12));
Matrix M7 = strassen(subtract(A12, A22), add(B21, B22));
Matrix C11 = add(subtract(add(M1, M4), M5), M7);
Matrix C12 = add(M3, M5);
Matrix C21 = add(M2, M4);
Matrix C22 = add(subtract(add(M1, M3), M2), M6);
Matrix C(n, vector<int>(n));
for (int i = 0; i < newSize; ++i) {
for (int j = 0; j < newSize; ++j) {
C[i][j] = C11[i][j];
C[i][j + newSize] = C12[i][j];
C[i + newSize][j] = C21[i][j];
C[i + newSize][j + newSize] = C22[i][j];
}
}
return C;
}
int main() {
Matrix A = {{1, 2}, {3, 4}};
Matrix B = {{5, 6}, {7, 8}};
Matrix C = strassen(A, B);
for (const auto &row : C) {
for (int val : row) {
cout << val << " ";
}
cout << endl;
}
return 0;
}

Time and Space Complexity

AspectStandard MultiplicationStrassen’s Algorithm
Time Complexity
Space Complexity (due to recursion overhead)
Efficiency for Small MatricesHigh (less overhead)Low (recursion overhead dominates)
Efficiency for Large MatricesLow (slower growth rate)High (faster growth rate)

Strassen’s Algorithm is not always the best choice for small matrices due to the overhead of recursion and additional operations, but it is highly effective for large matrices.