Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Implement Matrix , its Methods and Some Functions including Strassen Matrix Multiplication in Go #662

Merged
merged 20 commits into from
Oct 26, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
6a9aa2c
feat: Implement Strassen Matrix Multiplication
mohit07raghav19 Sep 30, 2023
b6fa85e
This commit introduces the Strassen matrix multiplication algorithm
mohit07raghav19 Oct 2, 2023
bcc7475
refactor: Rename functions and add implement new functionality
mohit07raghav19 Oct 3, 2023
400e75a
Implement Matrix as a struct type
mohit07raghav19 Oct 4, 2023
b1e4e01
Implement StrassenMatrixMultiply and Matrix Methods
mohit07raghav19 Oct 4, 2023
24fe1a6
Refactor to Use Value Type `Matrix` and Add Benchmarks
mohit07raghav19 Oct 5, 2023
7923f0b
Fixed Golang CI lint errors for file copy_test.go & submatrix_test.go
mohit07raghav19 Oct 6, 2023
f810d01
Merge branch 'TheAlgorithms:master' into master
mohit07raghav19 Oct 11, 2023
3fab688
refactor: Change type variable T to constraints.Integer, rename SameD…
mohit07raghav19 Oct 11, 2023
4d67ed9
refractor: Implement goroutines in Add, CheckEqual, Copy, New, Multip…
mohit07raghav19 Oct 11, 2023
910bb85
Merge branch 'TheAlgorithms:master' into master
mohit07raghav19 Oct 14, 2023
20bb9ee
refractor : Handled error in StrassenMatrixMultiply method instead of…
mohit07raghav19 Oct 14, 2023
dec410b
refractor : Handle errors gracefully by returning an error message in…
mohit07raghav19 Oct 16, 2023
a7e43d2
refractor : Updated the 'copy' function to return an empty matrix if …
mohit07raghav19 Oct 16, 2023
cabf07b
Merge branch 'TheAlgorithms:master' into master
mohit07raghav19 Oct 25, 2023
3c787c7
Updated Documentation in README.md
Oct 25, 2023
fc232f2
refactor: matrix operations to use context and sync packages
mohit07raghav19 Oct 25, 2023
382b49f
refactor: matrix operations to use context and sync packages
mohit07raghav19 Oct 25, 2023
51206f7
Updated Documentation in README.md
Oct 25, 2023
24dcb8f
chore: Add empty commit to trigger actions
mohit07raghav19 Oct 26, 2023
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
138 changes: 138 additions & 0 deletions math/matrix/strassenmatrixmultiply.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// filename: main.go
// description: Implements matrix multiplication using the Strassen algorithm.
// details:
// This program takes two matrices as input and performs matrix multiplication
// using the Strassen algorithm, which is an optimized divide-and-conquer
// approach. It allows for efficient multiplication of large matrices.
// author(s): Mohit Raghav(https://github.com/mohit07raghav19)
// See strassenmatrixmultiply_test.go for test cases
package matrix

// Perform matrix multiplication using Strassen's algorithm
func strassenMatrixMultiply(A, B [][]int) [][]int {
mohit07raghav19 marked this conversation as resolved.
Show resolved Hide resolved
mohit07raghav19 marked this conversation as resolved.
Show resolved Hide resolved
n := len(A)

// Check if matrices are 2x2 or smaller
if n <= 2 {
return standardMatrixMultiply(A, B)
}

// Calculate the size of submatrices
mid := n / 2

// Create submatrices
A11 := make([][]int, mid)
A12 := make([][]int, mid)
A21 := make([][]int, mid)
A22 := make([][]int, mid)

B11 := make([][]int, mid)
B12 := make([][]int, mid)
B21 := make([][]int, mid)
B22 := make([][]int, mid)

for i := 0; i < mid; i++ {
A11[i] = make([]int, mid)
A12[i] = make([]int, mid)
A21[i] = make([]int, mid)
A22[i] = make([]int, mid)

B11[i] = make([]int, mid)
B12[i] = make([]int, mid)
B21[i] = make([]int, mid)
B22[i] = make([]int, mid)

for j := 0; j < mid; j++ {
A11[i][j] = A[i][j]
A12[i][j] = A[i][j+mid]
A21[i][j] = A[i+mid][j]
A22[i][j] = A[i+mid][j+mid]

B11[i][j] = B[i][j]
B12[i][j] = B[i][j+mid]
B21[i][j] = B[i+mid][j]
B22[i][j] = B[i+mid][j+mid]
}
}

// Recursive steps
M1 := strassenMatrixMultiply(addMatrices(A11, A22), addMatrices(B11, B22))
M2 := strassenMatrixMultiply(addMatrices(A21, A22), B11)
M3 := strassenMatrixMultiply(A11, subtractMatrices(B12, B22))
M4 := strassenMatrixMultiply(A22, subtractMatrices(B21, B11))
M5 := strassenMatrixMultiply(addMatrices(A11, A12), B22)
M6 := strassenMatrixMultiply(subtractMatrices(A21, A11), addMatrices(B11, B12))
M7 := strassenMatrixMultiply(subtractMatrices(A12, A22), addMatrices(B21, B22))

// Calculate result submatrices
C11 := subtractMatrices(addMatrices(addMatrices(M1, M4), M7), M5)
C12 := addMatrices(M3, M5)
C21 := addMatrices(M2, M4)
C22 := subtractMatrices(addMatrices(addMatrices(M1, M3), M6), M2)

// Combine submatrices into the result matrix
C := make([][]int, n)
for i := 0; i < n; i++ {
C[i] = make([]int, n)
for j := 0; j < n; j++ {
if i < mid && j < mid {
C[i][j] = C11[i][j]
} else if i < mid && j >= mid {
C[i][j] = C12[i][j-mid]
} else if i >= mid && j < mid {
C[i][j] = C21[i-mid][j]
} else {
C[i][j] = C22[i-mid][j-mid]
}
}
}

return C
}

// Add two matrices element-wise
func addMatrices(A, B [][]int) [][]int {
mohit07raghav19 marked this conversation as resolved.
Show resolved Hide resolved
mohit07raghav19 marked this conversation as resolved.
Show resolved Hide resolved
n := len(A)
result := make([][]int, n)

for i := 0; i < n; i++ {
result[i] = make([]int, n)
for j := 0; j < n; j++ {
result[i][j] = A[i][j] + B[i][j]
}
}

return result
}

// Subtract one matrix from another element-wise
func subtractMatrices(A, B [][]int) [][]int {
n := len(A)
result := make([][]int, n)

for i := 0; i < n; i++ {
result[i] = make([]int, n)
for j := 0; j < n; j++ {
result[i][j] = A[i][j] - B[i][j]
}
}

return result
}

// Perform standard matrix multiplication
func standardMatrixMultiply(A, B [][]int) [][]int {
n := len(A)
result := make([][]int, n)

for i := 0; i < n; i++ {
result[i] = make([]int, n)
for j := 0; j < n; j++ {
for k := 0; k < n; k++ {
result[i][j] += A[i][k] * B[k][j]
}
}
}

return result
}
91 changes: 91 additions & 0 deletions math/matrix/strassenmatrixmultiply_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package matrix
mohit07raghav19 marked this conversation as resolved.
Show resolved Hide resolved

import (
"fmt"
"math/rand"
"os"
"testing"
"time"
)

// Example usage of the matrix multiplication function
func Example() {
matrixA := [][]int{
{1, 2},
{3, 4},
}

matrixB := [][]int{
{5, 6},
{7, 8},
}

result := strassenMatrixMultiply(matrixA, matrixB)
printMatrix(result)

// Output:
// [19 22]
// [43 50]
}

// TestMatrixMultiplication performs a test on matrix multiplication.
func TestMatrixMultiplication(t *testing.T) {
rand.Seed(time.Now().UnixNano())

// Generate random matrices for testing
size := 4
matrixA := makeRandomMatrix(size)
matrixB := makeRandomMatrix(size)

// Calculate the expected result using the standard multiplication
expected := standardMatrixMultiply(matrixA, matrixB)

// Calculate the result using the Strassen algorithm
result := strassenMatrixMultiply(matrixA, matrixB)

// Check if the result matches the expected result
for i := 0; i < size; i++ {
for j := 0; j < size; j++ {
if result[i][j] != expected[i][j] {
t.Errorf("Mismatch at position (%d, %d). Expected %d, but got %d.", i, j, expected[i][j], result[i][j])
}
}
}
}

// Generate a random matrix of the given size
func makeRandomMatrix(size int) [][]int {
mohit07raghav19 marked this conversation as resolved.
Show resolved Hide resolved
matrix := make([][]int, size)
for i := 0; i < size; i++ {
matrix[i] = make([]int, size)
for j := 0; j < size; j++ {
matrix[i][j] = rand.Intn(10) // Generate random integers between 0 and 9
}
}
return matrix
}

func TestMain(m *testing.M) {
mohit07raghav19 marked this conversation as resolved.
Show resolved Hide resolved
// Run the tests
code := m.Run()
os.Exit(code)
}

// BenchmarkStrassenMatrixMultiply benchmarks the strassenMatrixMultiply function.
func BenchmarkStrassenMatrixMultiply(b *testing.B) {
size := 128 // Change the size as needed for your benchmark
matrixA := makeRandomMatrix(size)
matrixB := makeRandomMatrix(size)

b.ResetTimer() // Reset the benchmark timer before the actual benchmark
for i := 0; i < b.N; i++ {
_ = strassenMatrixMultiply(matrixA, matrixB)
}
}

// Print a matrix
func printMatrix(matrix [][]int) {
mohit07raghav19 marked this conversation as resolved.
Show resolved Hide resolved
for _, row := range matrix {
fmt.Println(row)
}
}