This project implements and compares two matrix multiplication algorithms: the standard O(n³) algorithm and Strassen's O(n^log₂(7)) algorithm. The implementation includes performance testing and correctness verification.
Matrix multiplication is a fundamental operation in linear algebra and computer science. This project demonstrates the trade-offs between different algorithmic approaches:
- Standard Algorithm: Simple, straightforward implementation with O(n³) time complexity
- Strassen Algorithm: More complex divide-and-conquer approach with O(n^log₂(7)) ≈ O(n^2.81) time complexity
Contains the standard matrix multiplication algorithm:
- Time Complexity: O(n³)
- Space Complexity: O(n²)
- Algorithm: Three nested loops performing dot product for each element
- Best for: Small matrices or when simplicity is preferred
Implements Strassen's matrix multiplication algorithm:
- Time Complexity: O(n^log₂(7)) ≈ O(n^2.81)
- Space Complexity: O(n²)
- Algorithm: Divide-and-conquer approach using 7 recursive multiplications instead of 8
- Best for: Large matrices where the asymptotic improvement matters
Key Functions:
add_matrix(A, B): Matrix additionsub_matrix(A, B): Matrix subtractionsplit_matrix(M): Divides matrix into four quadrantscombine_quadrants(C11, C12, C21, C22): Combines quadrants into result matrixstrassen_multiply(A, B): Main Strassen algorithm implementation
Performance comparison and testing script:
- Generates random test matrices
- Measures execution time for both algorithms
- Verifies correctness by comparing results
- Tests matrices of sizes 2×2, 4×4, and 8×8
Contains the mathematical pseudocode and algorithm description for Strassen's matrix multiplication algorithm.
The standard algorithm uses the definition of matrix multiplication:
C[i][j] = Σ(A[i][k] * B[k][j]) for k = 0 to n-1
Steps:
- Initialize result matrix C with zeros
- For each element C[i][j]:
- Calculate dot product of row i from A and column j from B
- Store result in C[i][j]
Strassen's algorithm reduces the number of recursive multiplications from 8 to 7 by cleverly combining matrix operations.
Key Insight: Instead of computing 8 submatrix multiplications:
- A11×B11, A11×B12, A12×B21, A12×B22
- A21×B11, A21×B12, A22×B21, A22×B22
Strassen computes 7 products:
- P1 = A11 × (B12 - B22)
- P2 = (A11 + A12) × B22
- P3 = (A21 + A22) × B11
- P4 = A22 × (B21 - B11)
- P5 = (A11 + A22) × (B11 + B22)
- P6 = (A12 - A22) × (B21 + B22)
- P7 = (A11 - A21) × (B11 + B12)
Then combines them:
- C11 = P5 + P4 - P2 + P6
- C12 = P1 + P2
- C21 = P3 + P4
- C22 = P1 + P5 - P3 - P7
- Python 3.6 or higher
- NumPy library
pip install numpyTo run the performance comparison:
python compare.pyThis will:
- Generate random matrices of sizes 2×2, 4×4, and 8×8
- Measure execution time for both algorithms
- Verify correctness by comparing results
- Display performance metrics
=== Comparison with 2x2 matrix ===
Standard multiplication time: 0.000012 seconds
Strassen multiplication time: 0.000045 seconds
✅ Results match!
=== Comparison with 4x4 matrix ===
Standard multiplication time: 0.000045 seconds
Strassen multiplication time: 0.000123 seconds
✅ Results match!
=== Comparison with 8x8 matrix ===
Standard multiplication time: 0.000234 seconds
Strassen multiplication time: 0.000456 seconds
✅ Results match!
=== Comparison with 1000x1000 matrix ===
Standard multiplication time: 52.808272 seconds
Strassen multiplication time: 40.234893 seconds
✅ Results match!
from standard_multiply import standard_matrix_multiply
A = [[1, 2], [3, 4]]
B = [[5, 6], [7, 8]]
result = standard_matrix_multiply(A, B)
print(result) # [[19, 22], [43, 50]]from strassen import strassen_multiply
A = [[1, 2], [3, 4]]
B = [[5, 6], [7, 8]]
result = strassen_multiply(A, B)
print(result) # [[19, 22], [43, 50]]The compare.py script automatically tests both algorithms with:
- Random matrices of different sizes
- Correctness verification using NumPy's
allclose()function - Performance timing measurements
You can create custom test cases:
import numpy as np
from standard_multiply import standard_matrix_multiply
from strassen import strassen_multiply
# Create test matrices
A = np.random.randint(0, 10, (4, 4)).tolist()
B = np.random.randint(0, 10, (4, 4)).tolist()
# Test both algorithms
result_standard = standard_matrix_multiply(A, B)
result_strassen = strassen_multiply(A, B)
# Verify correctness
print("Results match:", np.allclose(result_standard, result_strassen))| Algorithm | Time Complexity | Space Complexity |
|---|---|---|
| Standard | O(n³) | O(n²) |
| Strassen | O(n^log₂(7)) | O(n²) |
Use Standard Algorithm when:
- Matrices are small (n < 100)
- Simplicity and readability are important
- Memory usage is a concern
- Working with non-square matrices
Use Strassen Algorithm when:
- Matrices are large (n > 100)
- Performance is critical
- Working with square matrices that are powers of 2
- The overhead of recursive calls is acceptable
- For small matrices, the standard algorithm often performs better due to lower overhead
- Strassen's algorithm shows its advantage with larger matrices
- The crossover point depends on implementation details and hardware
- Strassen's algorithm requires matrices to be square and preferably powers of 2
- Matrix Size: Works best with square matrices that are powers of 2
- Numerical Stability: May introduce more floating-point errors due to additional operations
- Memory Overhead: Higher memory usage due to recursive calls and temporary matrices
- Implementation Complexity: More complex to implement and debug
- Matrix Requirements: Both algorithms assume square matrices
- Memory Constraints: Large matrices may cause memory issues
- Numerical Precision: Floating-point arithmetic limitations
- Hybrid Approach: Use Strassen for large matrices and standard for small ones
- Padding: Handle non-power-of-2 matrices by padding
- Parallelization: Implement parallel versions for better performance
- Memory Optimization: Reduce memory usage in Strassen implementation
- Numerical Stability: Improve floating-point precision handling
- Strassen, V. (1969). "Gaussian elimination is not optimal". Numerische Mathematik.
- Cormen, T. H., Leiserson, C. E., Rivest, R. L., & Stein, C. (2009). "Introduction to Algorithms" (3rd ed.). MIT Press.
This project is for educational purposes. Feel free to use and modify the code for learning and research.