Home DSA Strassen's Matrix Multiplication — O(n^2.807) Algorithm

Strassen's Matrix Multiplication — O(n^2.807) Algorithm

Where developers are forged. · Structured learning · Free forever.
📍 Part of: Recursion → Topic 8 of 9
Learn Strassen's matrix multiplication algorithm.
🔥 Advanced — solid DSA foundation required
In this tutorial, you'll learn:
  • 7 multiplications instead of 8 for 2×2 blocks gives T(n) = 7T(n/2) + O(n^2). Master Theorem Case 1: T(n) = O(n^log_2(7)) ≈ O(n^2.807).
  • Saving one multiplication per level compounds exponentially through the recursion. This is the Master Theorem in action — the recursive term dominates.
  • Not used in practice: numerical instability (catastrophic cancellation in the additions), large constant factor, crossover point ~512-1024. NumPy/BLAS use optimised O(n^3).
✦ Plain-English analogy ✦ Real code with output ✦ Interview questions
⚡ Quick Answer
Multiplying two n×n matrices naively takes n³ multiplications. Strassen's 1969 insight: for 2×2 matrices, you can get away with 7 multiplications instead of 8, using some clever additions. Recursively applying this to n/2×n/2 blocks gives O(n^2.807) — beating the O(n³) barrier. Each multiplication saved at the 2×2 level propagates to asymptotic improvement at scale.

For decades, everyone assumed matrix multiplication required exactly n^3 multiplications for n×n matrices. In 1969, Volker Strassen proved them wrong by showing you only need 7 recursive multiplications instead of 8 for the 2×2 case. Applied recursively, this changes the exponent from log_2(8)=3 to log_2(7)≈2.807.

Strassen's algorithm matters less for its practical use (numerical stability issues and large constants make it impractical below n≈512) than for what it proved: the O(n^3) barrier is not a fundamental law. It opened the door to algorithms approaching O(n^2) — Coppersmith-Winograd (1987) achieved O(n^2.376), and subsequent work has continued pushing toward O(n^2). As of 2026, the theoretical lower bound is unknown. The entire sub-cubic matrix multiplication literature traces back to Strassen's 1969 insight.

Standard Matrix Multiplication

For C = A × B where A, B are n×n matrices: C[i][j] = Σ A[i][k] × B[k][j] for k in 0..n-1

This requires n³ multiplications and n²(n-1) additions → O(n³).

Strassen's 7-Multiplication Formula

For 2×2 matrices A and B split into quadrants: A = [[a,b],[c,d]], B = [[e,f],[g,h]]

Define 7 products: - M1 = (a+d)(e+h) - M2 = (c+d)e - M3 = a(f-h) - M4 = d(g-e) - M5 = (a+b)h - M6 = (c-a)(e+f) - M7 = (b-d)(g+h)

Result: C = [[M1+M4-M5+M7, M3+M5],[M2+M4, M1-M2+M3+M6]]

strassen.py · PYTHON
1234567891011121314151617181920212223242526272829303132333435363738394041424344
def strassen(A, B):
    n = len(A)
    if n == 1:
        return [[A[0][0] * B[0][0]]]
    # Split into quadrants
    mid = n // 2
    a = [r[:mid] for r in A[:mid]]
    b = [r[mid:] for r in A[:mid]]
    c = [r[:mid] for r in A[mid:]]
    d = [r[mid:] for r in A[mid:]]
    e = [r[:mid] for r in B[:mid]]
    f = [r[mid:] for r in B[:mid]]
    g = [r[:mid] for r in B[mid:]]
    h = [r[mid:] for r in B[mid:]]

    def add(X, Y): return [[X[i][j]+Y[i][j] for j in range(len(X[0]))] for i in range(len(X))]
    def sub(X, Y): return [[X[i][j]-Y[i][j] for j in range(len(X[0]))] for i in range(len(X))]

    M1 = strassen(add(a,d), add(e,h))
    M2 = strassen(add(c,d), e)
    M3 = strassen(a, sub(f,h))
    M4 = strassen(d, sub(g,e))
    M5 = strassen(add(a,b), h)
    M6 = strassen(sub(c,a), add(e,f))
    M7 = strassen(sub(b,d), add(g,h))

    C11 = add(sub(add(M1,M4),M5), M7)
    C12 = add(M3, M5)
    C21 = add(M2, M4)
    C22 = add(sub(add(M1,M3),M2), M6)

    n2 = len(C11)
    C = [[0]*(2*n2) for _ in range(2*n2)]
    for i in range(n2):
        for j in range(n2):
            C[i][j]       = C11[i][j]
            C[i][j+n2]    = C12[i][j]
            C[i+n2][j]    = C21[i][j]
            C[i+n2][j+n2] = C22[i][j]
    return C

A = [[1,2],[3,4]]
B = [[5,6],[7,8]]
print(strassen(A,B))  # [[19,22],[43,50]]
▶ Output
[[19, 22], [43, 50]]

Master Theorem Analysis

T(n) = 7T(n/2) + O(n²)

a=7, b=2, f(n)=n² log_b(a) = log₂(7) ≈ 2.807

Since f(n) = O(n^(2.807-ε)), we are in Master Theorem Case 1: T(n) = Θ(n^log₂7) ≈ Θ(n^2.807)

Saving just one multiplication per level of recursion changed the exponent from 3 to 2.807.

🔥
Practical NoteStrassen is rarely used in production due to numerical instability and large constant factors. NumPy and BLAS use highly optimised cache-friendly O(n³) implementations that outperform Strassen for all practical matrix sizes. Strassen matters theoretically as the first sub-cubic algorithm.

Crossover Point

Strassen is only faster than naive multiplication for large n (typically n > 128-512 depending on implementation). The large number of additions and the overhead of recursion make it slower for small matrices. Practical implementations switch to naive multiplication below a threshold.

🎯 Key Takeaways

  • 7 multiplications instead of 8 for 2×2 blocks gives T(n) = 7T(n/2) + O(n^2). Master Theorem Case 1: T(n) = O(n^log_2(7)) ≈ O(n^2.807).
  • Saving one multiplication per level compounds exponentially through the recursion. This is the Master Theorem in action — the recursive term dominates.
  • Not used in practice: numerical instability (catastrophic cancellation in the additions), large constant factor, crossover point ~512-1024. NumPy/BLAS use optimised O(n^3).
  • The theoretical significance: Strassen proved the O(n^3) barrier is not fundamental. Post-Strassen, algorithms down to O(n^2.376) exist but are impractical.
  • In interviews: understand the algorithm and Master Theorem analysis. Don't implement it — use numpy.dot() in production.

Interview Questions on This Topic

  • QHow many multiplications does Strassen use for 2×2 matrices vs naive?
  • QApply the Master Theorem to T(n) = 7T(n/2) + O(n²).
  • QWhy is Strassen's algorithm not commonly used in numerical computing?
  • QWhat is the significance of Strassen's algorithm in the history of algorithms?

Frequently Asked Questions

Has anyone beaten O(n^2.807) since Strassen?

Yes — Coppersmith-Winograd (1987) achieved O(n^2.376), and subsequent improvements have pushed this toward O(n^2.37). The theoretical lower bound is unknown — it might be as low as O(n^2). However, all known sub-cubic algorithms have huge constant factors and are impractical.

🔥
Naren Founder & Author

Developer and founder of TheCodeForge. I built this site because I was tired of tutorials that explain what to type without explaining why it works. Every article here is written to make concepts actually click.

← PreviousClosest Pair of Points — Divide and ConquerNext →Convex Hull — Graham Scan and Jarvis March
Forged with 🔥 at TheCodeForge.io — Where Developers Are Forged