Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
2
Task/Strassens-algorithm/00-META.yaml
Normal file
2
Task/Strassens-algorithm/00-META.yaml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
---
|
||||
from: http://rosettacode.org/wiki/Strassen's_algorithm
|
||||
20
Task/Strassens-algorithm/00-TASK.txt
Normal file
20
Task/Strassens-algorithm/00-TASK.txt
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
;Description
|
||||
In linear algebra, the Strassen algorithm (named after Volker Strassen), is an algorithm for matrix multiplication.
|
||||
|
||||
It is faster than the standard matrix multiplication algorithm and is useful in practice for large matrices, but would be slower than the fastest known algorithms for extremely large matrices.
|
||||
|
||||
|
||||
;Task
|
||||
Write a routine, function, procedure etc. in your language to implement the Strassen algorithm for matrix multiplication.
|
||||
|
||||
While practical implementations of Strassen's algorithm usually switch to standard methods of matrix multiplication for small enough sub-matrices (currently anything less than 512×512 according to Wikipedia), for the purposes of this task you should not switch until reaching a size of 1 or 2.
|
||||
|
||||
|
||||
;Related task
|
||||
:* [[Matrix multiplication]]
|
||||
|
||||
|
||||
;See also
|
||||
:* [[wp:Strassen algorithm|Wikipedia article]]
|
||||
<br><br>
|
||||
|
||||
165
Task/Strassens-algorithm/Go/strassens-algorithm.go
Normal file
165
Task/Strassens-algorithm/Go/strassens-algorithm.go
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"math"
|
||||
)
|
||||
|
||||
type Matrix [][]float64
|
||||
|
||||
func (m Matrix) rows() int { return len(m) }
|
||||
func (m Matrix) cols() int { return len(m[0]) }
|
||||
|
||||
func (m Matrix) add(m2 Matrix) Matrix {
|
||||
if m.rows() != m2.rows() || m.cols() != m2.cols() {
|
||||
log.Fatal("Matrices must have the same dimensions.")
|
||||
}
|
||||
c := make(Matrix, m.rows())
|
||||
for i := 0; i < m.rows(); i++ {
|
||||
c[i] = make([]float64, m.cols())
|
||||
for j := 0; j < m.cols(); j++ {
|
||||
c[i][j] = m[i][j] + m2[i][j]
|
||||
}
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (m Matrix) sub(m2 Matrix) Matrix {
|
||||
if m.rows() != m2.rows() || m.cols() != m2.cols() {
|
||||
log.Fatal("Matrices must have the same dimensions.")
|
||||
}
|
||||
c := make(Matrix, m.rows())
|
||||
for i := 0; i < m.rows(); i++ {
|
||||
c[i] = make([]float64, m.cols())
|
||||
for j := 0; j < m.cols(); j++ {
|
||||
c[i][j] = m[i][j] - m2[i][j]
|
||||
}
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (m Matrix) mul(m2 Matrix) Matrix {
|
||||
if m.cols() != m2.rows() {
|
||||
log.Fatal("Cannot multiply these matrices.")
|
||||
}
|
||||
c := make(Matrix, m.rows())
|
||||
for i := 0; i < m.rows(); i++ {
|
||||
c[i] = make([]float64, m2.cols())
|
||||
for j := 0; j < m2.cols(); j++ {
|
||||
for k := 0; k < m2.rows(); k++ {
|
||||
c[i][j] += m[i][k] * m2[k][j]
|
||||
}
|
||||
}
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func (m Matrix) toString(p int) string {
|
||||
s := make([]string, m.rows())
|
||||
pow := math.Pow(10, float64(p))
|
||||
for i := 0; i < m.rows(); i++ {
|
||||
t := make([]string, m.cols())
|
||||
for j := 0; j < m.cols(); j++ {
|
||||
r := math.Round(m[i][j]*pow) / pow
|
||||
t[j] = fmt.Sprintf("%g", r)
|
||||
if t[j] == "-0" {
|
||||
t[j] = "0"
|
||||
}
|
||||
}
|
||||
s[i] = fmt.Sprintf("%v", t)
|
||||
}
|
||||
return fmt.Sprintf("%v", s)
|
||||
}
|
||||
|
||||
func params(r, c int) [4][6]int {
|
||||
return [4][6]int{
|
||||
{0, r, 0, c, 0, 0},
|
||||
{0, r, c, 2 * c, 0, c},
|
||||
{r, 2 * r, 0, c, r, 0},
|
||||
{r, 2 * r, c, 2 * c, r, c},
|
||||
}
|
||||
}
|
||||
|
||||
func toQuarters(m Matrix) [4]Matrix {
|
||||
r := m.rows() / 2
|
||||
c := m.cols() / 2
|
||||
p := params(r, c)
|
||||
var quarters [4]Matrix
|
||||
for k := 0; k < 4; k++ {
|
||||
q := make(Matrix, r)
|
||||
for i := p[k][0]; i < p[k][1]; i++ {
|
||||
q[i-p[k][4]] = make([]float64, c)
|
||||
for j := p[k][2]; j < p[k][3]; j++ {
|
||||
q[i-p[k][4]][j-p[k][5]] = m[i][j]
|
||||
}
|
||||
}
|
||||
quarters[k] = q
|
||||
}
|
||||
return quarters
|
||||
}
|
||||
|
||||
func fromQuarters(q [4]Matrix) Matrix {
|
||||
r := q[0].rows()
|
||||
c := q[0].cols()
|
||||
p := params(r, c)
|
||||
r *= 2
|
||||
c *= 2
|
||||
m := make(Matrix, r)
|
||||
for i := 0; i < c; i++ {
|
||||
m[i] = make([]float64, c)
|
||||
}
|
||||
for k := 0; k < 4; k++ {
|
||||
for i := p[k][0]; i < p[k][1]; i++ {
|
||||
for j := p[k][2]; j < p[k][3]; j++ {
|
||||
m[i][j] = q[k][i-p[k][4]][j-p[k][5]]
|
||||
}
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func strassen(a, b Matrix) Matrix {
|
||||
if a.rows() != a.cols() || b.rows() != b.cols() || a.rows() != b.rows() {
|
||||
log.Fatal("Matrices must be square and of equal size.")
|
||||
}
|
||||
if a.rows() == 0 || (a.rows()&(a.rows()-1)) != 0 {
|
||||
log.Fatal("Size of matrices must be a power of two.")
|
||||
}
|
||||
if a.rows() == 1 {
|
||||
return a.mul(b)
|
||||
}
|
||||
qa := toQuarters(a)
|
||||
qb := toQuarters(b)
|
||||
p1 := strassen(qa[1].sub(qa[3]), qb[2].add(qb[3]))
|
||||
p2 := strassen(qa[0].add(qa[3]), qb[0].add(qb[3]))
|
||||
p3 := strassen(qa[0].sub(qa[2]), qb[0].add(qb[1]))
|
||||
p4 := strassen(qa[0].add(qa[1]), qb[3])
|
||||
p5 := strassen(qa[0], qb[1].sub(qb[3]))
|
||||
p6 := strassen(qa[3], qb[2].sub(qb[0]))
|
||||
p7 := strassen(qa[2].add(qa[3]), qb[0])
|
||||
var q [4]Matrix
|
||||
q[0] = p1.add(p2).sub(p4).add(p6)
|
||||
q[1] = p4.add(p5)
|
||||
q[2] = p6.add(p7)
|
||||
q[3] = p2.sub(p3).add(p5).sub(p7)
|
||||
return fromQuarters(q)
|
||||
}
|
||||
|
||||
func main() {
|
||||
a := Matrix{{1, 2}, {3, 4}}
|
||||
b := Matrix{{5, 6}, {7, 8}}
|
||||
c := Matrix{{1, 1, 1, 1}, {2, 4, 8, 16}, {3, 9, 27, 81}, {4, 16, 64, 256}}
|
||||
d := Matrix{{4, -3, 4.0 / 3, -1.0 / 4}, {-13.0 / 3, 19.0 / 4, -7.0 / 3, 11.0 / 24},
|
||||
{3.0 / 2, -2, 7.0 / 6, -1.0 / 4}, {-1.0 / 6, 1.0 / 4, -1.0 / 6, 1.0 / 24}}
|
||||
e := Matrix{{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}}
|
||||
f := Matrix{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}
|
||||
fmt.Println("Using 'normal' matrix multiplication:")
|
||||
fmt.Printf(" a * b = %v\n", a.mul(b))
|
||||
fmt.Printf(" c * d = %v\n", c.mul(d).toString(6))
|
||||
fmt.Printf(" e * f = %v\n", e.mul(f))
|
||||
fmt.Println("\nUsing 'Strassen' matrix multiplication:")
|
||||
fmt.Printf(" a * b = %v\n", strassen(a, b))
|
||||
fmt.Printf(" c * d = %v\n", strassen(c, d).toString(6))
|
||||
fmt.Printf(" e * f = %v\n", strassen(e, f))
|
||||
}
|
||||
117
Task/Strassens-algorithm/Julia/strassens-algorithm-1.julia
Normal file
117
Task/Strassens-algorithm/Julia/strassens-algorithm-1.julia
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
"""
|
||||
Strassen's matrix multiplication algorithm.
|
||||
Use dynamic padding in order to reduce required auxiliary memory.
|
||||
"""
|
||||
function strassen(x::Matrix, y::Matrix)
|
||||
# Check that the sizes of these matrices match.
|
||||
(r1, c1) = size(x)
|
||||
(r2, c2) = size(y)
|
||||
if c1 != r2
|
||||
error("Multiplying $r1 x $c1 and $r2 x $c2 matrix: dimensions do not match.")
|
||||
end
|
||||
|
||||
# Put a matrix into the top left of a matrix of zeros.
|
||||
# `rows` and `cols` are the dimensions of the output matrix.
|
||||
function embed(mat, rows, cols)
|
||||
# If the matrix is already of the right dimensions, don't allocate new memory.
|
||||
(r, c) = size(mat)
|
||||
if (r, c) == (rows, cols)
|
||||
return mat
|
||||
end
|
||||
|
||||
# Pad the matrix with zeros to be the right size.
|
||||
out = zeros(Int, rows, cols)
|
||||
out[1:r, 1:c] = mat
|
||||
out
|
||||
end
|
||||
|
||||
# Make sure both matrices are the same size.
|
||||
# This is exclusively for simplicity:
|
||||
# this algorithm can be implemented with matrices of different sizes.
|
||||
r = max(r1, r2); c = max(c1, c2)
|
||||
x = embed(x, r, c)
|
||||
y = embed(y, r, c)
|
||||
|
||||
# Our recursive multiplication function.
|
||||
function block_mult(a, b, rows, cols)
|
||||
# For small matrices, resort to naive multiplication.
|
||||
# if rows <= 128 || cols <= 128
|
||||
if rows == 1 && cols == 1
|
||||
# if rows == 2 && cols == 2
|
||||
return a * b
|
||||
end
|
||||
|
||||
# Apply dynamic padding.
|
||||
if rows % 2 == 1 && cols % 2 == 1
|
||||
a = embed(a, rows + 1, cols + 1)
|
||||
b = embed(b, rows + 1, cols + 1)
|
||||
elseif rows % 2 == 1
|
||||
a = embed(a, rows + 1, cols)
|
||||
b = embed(b, rows + 1, cols)
|
||||
elseif cols % 2 == 1
|
||||
a = embed(a, rows, cols + 1)
|
||||
b = embed(b, rows, cols + 1)
|
||||
end
|
||||
|
||||
half_rows = Int(size(a, 1) / 2)
|
||||
half_cols = Int(size(a, 2) / 2)
|
||||
|
||||
# Subdivide input matrices.
|
||||
a11 = a[1:half_rows, 1:half_cols]
|
||||
b11 = b[1:half_rows, 1:half_cols]
|
||||
|
||||
a12 = a[1:half_rows, half_cols+1:size(a, 2)]
|
||||
b12 = b[1:half_rows, half_cols+1:size(a, 2)]
|
||||
|
||||
a21 = a[half_rows+1:size(a, 1), 1:half_cols]
|
||||
b21 = b[half_rows+1:size(a, 1), 1:half_cols]
|
||||
|
||||
a22 = a[half_rows+1:size(a, 1), half_cols+1:size(a, 2)]
|
||||
b22 = b[half_rows+1:size(a, 1), half_cols+1:size(a, 2)]
|
||||
|
||||
# Compute intermediate values.
|
||||
multip(x, y) = block_mult(x, y, half_rows, half_cols)
|
||||
m1 = multip(a11 + a22, b11 + b22)
|
||||
m2 = multip(a21 + a22, b11)
|
||||
m3 = multip(a11, b12 - b22)
|
||||
m4 = multip(a22, b21 - b11)
|
||||
m5 = multip(a11 + a12, b22)
|
||||
m6 = multip(a21 - a11, b11 + b12)
|
||||
m7 = multip(a12 - a22, b21 + b22)
|
||||
|
||||
# Combine intermediate values into the output.
|
||||
c11 = m1 + m4 - m5 + m7
|
||||
c12 = m3 + m5
|
||||
c21 = m2 + m4
|
||||
c22 = m1 - m2 + m3 + m6
|
||||
|
||||
# Crop output to the desired size (undo dynamic padding).
|
||||
out = [c11 c12; c21 c22]
|
||||
out[1:rows, 1:cols]
|
||||
end
|
||||
|
||||
block_mult(x, y, r, c)
|
||||
end
|
||||
|
||||
const A = [[1, 2] [3, 4]]
|
||||
const B = [[5, 6] [7, 8]]
|
||||
const C = [[1, 1, 1, 1] [2, 4, 8, 16] [3, 9, 27, 81] [4, 16, 64, 256]]
|
||||
const D = [[4, -3, 4/3, -1/4] [-13/3, 19/4, -7/3, 11/24] [3/2, -2, 7/6, -1/4] [-1/6, 1/4, -1/6, 1/24]]
|
||||
const E = [[1, 2, 3, 4] [5, 6, 7, 8] [9, 10, 11, 12] [13, 14, 15, 16]]
|
||||
const F = [[1, 0, 0, 0] [0, 1, 0, 0] [0, 0, 1, 0] [0, 0, 0, 1]]
|
||||
|
||||
""" For pretty printing: change matrix to integer if it is within 0.00000001 of an integer """
|
||||
intprint(s, mat) = println(s, map(x -> Int(round(x, digits=8)), mat)')
|
||||
|
||||
intprint("Regular multiply: ", A' * B')
|
||||
intprint("Strassen multiply: ", strassen(Matrix(A'), Matrix(B')))
|
||||
intprint("Regular multiply: ", C * D)
|
||||
intprint("Strassen multiply: ", strassen(C, D))
|
||||
intprint("Regular multiply: ", E * F)
|
||||
intprint("Strassen multiply: ", strassen(E, F))
|
||||
|
||||
const r = sqrt(2)/2
|
||||
const R = [[r, r] [-r, r]]
|
||||
|
||||
intprint("Regular multiply: ", R * R)
|
||||
intprint("Strassen multiply: ", strassen(R,R))
|
||||
50
Task/Strassens-algorithm/Julia/strassens-algorithm-2.julia
Normal file
50
Task/Strassens-algorithm/Julia/strassens-algorithm-2.julia
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
function Strassen(A, B)
|
||||
n = size(A, 1)
|
||||
if n == 1
|
||||
return A * B
|
||||
end
|
||||
@views A11 = A[1:n÷2, 1:n÷2]
|
||||
@views A12 = A[1:n÷2, n÷2+1:n]
|
||||
@views A21 = A[n÷2+1:n, 1:n÷2]
|
||||
@views A22 = A[n÷2+1:n, n÷2+1:n]
|
||||
@views B11 = B[1:n÷2, 1:n÷2]
|
||||
@views B12 = B[1:n÷2, n÷2+1:n]
|
||||
@views B21 = B[n÷2+1:n, 1:n÷2]
|
||||
@views B22 = B[n÷2+1:n, n÷2+1:n]
|
||||
|
||||
P1 = Strassen(A12 - A22, B21 + B22)
|
||||
P2 = Strassen(A11 + A22, B11 + B22)
|
||||
P3 = Strassen(A11 - A21, B11 + B12)
|
||||
P4 = Strassen(A11 + A12, B22)
|
||||
P5 = Strassen(A11, B12 - B22)
|
||||
P6 = Strassen(A22, B21 - B11)
|
||||
P7 = Strassen(A21 + A22, B11)
|
||||
|
||||
C11 = P1 + P2 - P4 + P6
|
||||
C12 = P4 + P5
|
||||
C21 = P6 + P7
|
||||
C22 = P2 - P3 + P5 - P7
|
||||
|
||||
return [C11 C12; C21 C22]
|
||||
end
|
||||
|
||||
const A = [[1, 2] [3, 4]]
|
||||
const B = [[5, 6] [7, 8]]
|
||||
const C = [[1, 1, 1, 1] [2, 4, 8, 16] [3, 9, 27, 81] [4, 16, 64, 256]]
|
||||
const D = [[4, -3, 4/3, -1/4] [-13/3, 19/4, -7/3, 11/24] [3/2, -2, 7/6, -1/4] [-1/6, 1/4, -1/6, 1/24]]
|
||||
const E = [[1, 2, 3, 4] [5, 6, 7, 8] [9, 10, 11, 12] [13, 14, 15, 16]]
|
||||
const F = [[1, 0, 0, 0] [0, 1, 0, 0] [0, 0, 1, 0] [0, 0, 0, 1]]
|
||||
|
||||
intprint(s, mat) = println(s, map(x -> Int(round(x, digits=8)), mat)')
|
||||
intprint("Regular multiply: ", A' * B')
|
||||
intprint("Strassen multiply: ", Strassen(Matrix(A'), Matrix(B')))
|
||||
intprint("Regular multiply: ", C * D)
|
||||
intprint("Strassen multiply: ", Strassen(C, D))
|
||||
intprint("Regular multiply: ", E * F)
|
||||
intprint("Strassen multiply: ", Strassen(E, F))
|
||||
|
||||
const r = sqrt(2)/2
|
||||
const R = [[r, r] [-r, r]]
|
||||
|
||||
intprint("Regular multiply: ", R * R)
|
||||
intprint("Strassen multiply: ", Strassen(R,R))
|
||||
140
Task/Strassens-algorithm/Nim/strassens-algorithm.nim
Normal file
140
Task/Strassens-algorithm/Nim/strassens-algorithm.nim
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
import math, sequtils, strutils
|
||||
|
||||
type Matrix = seq[seq[float]]
|
||||
|
||||
template rows(m: Matrix): Positive = m.len
|
||||
template cols(m: Matrix): Positive = m[0].len
|
||||
|
||||
|
||||
func `+`(m1, m2: Matrix): Matrix =
|
||||
doAssert m1.rows == m2.rows and m1.cols == m2.cols, "Matrices must have the same dimensions."
|
||||
result = newSeqWith(m1.rows, newSeq[float](m1.cols))
|
||||
for i in 0..<m1.rows:
|
||||
for j in 0..<m1.cols:
|
||||
result[i][j] = m1[i][j] + m2[i][j]
|
||||
|
||||
|
||||
func `-`(m1, m2: Matrix): Matrix =
|
||||
doAssert m1.rows == m2.rows and m1.cols == m2.cols, "Matrices must have the same dimensions."
|
||||
result = newSeqWith(m1.rows, newSeq[float](m1.cols))
|
||||
for i in 0..<m1.rows:
|
||||
for j in 0..<m1.cols:
|
||||
result[i][j] = m1[i][j] - m2[i][j]
|
||||
|
||||
|
||||
func `*`(m1, m2: Matrix): Matrix =
|
||||
doAssert m1.cols == m2.rows, "Cannot multiply these matrices."
|
||||
result = newSeqWith(m1.rows, newSeq[float](m2.cols))
|
||||
for i in 0..<m1.rows:
|
||||
for j in 0..<m2.cols:
|
||||
for k in 0..<m2.rows:
|
||||
result[i][j] += m1[i][k] * m2[k][j]
|
||||
|
||||
|
||||
func toString(m: Matrix; p: Natural): string =
|
||||
## Round all elements to 'p' places.
|
||||
var res: seq[string]
|
||||
let pow = 10.0^p
|
||||
for row in m:
|
||||
var line: seq[string]
|
||||
for val in row:
|
||||
let r = round(val * pow) / pow
|
||||
var s = r.formatFloat(precision = -1)
|
||||
if s == "-0": s = "0"
|
||||
line.add s
|
||||
res.add '[' & line.join(" ") & ']'
|
||||
result = '[' & res.join(" ") & ']'
|
||||
|
||||
|
||||
func params(r, c: int): array[4, array[6, int]] =
|
||||
[[0, r, 0, c, 0, 0],
|
||||
[0, r, c, 2 * c, 0, c],
|
||||
[r, 2 * r, 0, c, r, 0],
|
||||
[r, 2 * r, c, 2 * c, r, c]]
|
||||
|
||||
|
||||
func toQuarters(m: Matrix): array[4, Matrix] =
|
||||
let
|
||||
r = m.rows() div 2
|
||||
c = m.cols() div 2
|
||||
p = params(r, c)
|
||||
for k in 0..3:
|
||||
var q = newSeqWith(r, newSeq[float](c))
|
||||
for i in p[k][0]..<p[k][1]:
|
||||
for j in p[k][2]..<p[k][3]:
|
||||
q[i-p[k][4]][j-p[k][5]] = m[i][j]
|
||||
result[k] = move(q)
|
||||
|
||||
|
||||
func fromQuarters(q: array[4, Matrix]): Matrix =
|
||||
var
|
||||
r = q[0].rows
|
||||
c = q[0].cols
|
||||
let p = params(r, c)
|
||||
r *= 2
|
||||
c *= 2
|
||||
result = newSeqWith(r, newSeq[float](c))
|
||||
for k in 0..3:
|
||||
for i in p[k][0]..<p[k][1]:
|
||||
for j in p[k][2]..<p[k][3]:
|
||||
result[i][j] = q[k][i-p[k][4]][j-p[k][5]]
|
||||
|
||||
|
||||
func strassen(a, b: Matrix): Matrix =
|
||||
doAssert a.rows == a.cols() and b.rows == b.cols and a.rows == b.rows,
|
||||
"Matrices must be square and of equal size."
|
||||
doAssert a.rows != 0 and (a.rows and (a.rows-1)) == 0,
|
||||
"Size of matrices must be a power of two."
|
||||
if a.rows == 1: return a * b
|
||||
|
||||
let
|
||||
qa = a.toQuarters()
|
||||
qb = b.toQuarters()
|
||||
p1 = strassen(qa[1] - qa[3], qb[2] + qb[3])
|
||||
p2 = strassen(qa[0] + qa[3], qb[0] + qb[3])
|
||||
p3 = strassen(qa[0] - qa[2], qb[0] + qb[1])
|
||||
p4 = strassen(qa[0] + qa[1], qb[3])
|
||||
p5 = strassen(qa[0], qb[1] - qb[3])
|
||||
p6 = strassen(qa[3], qb[2] - qb[0])
|
||||
p7 = strassen(qa[2] + qa[3], qb[0])
|
||||
|
||||
var q: array[4, Matrix]
|
||||
q[0] = p1 + p2 - p4 + p6
|
||||
q[1] = p4 + p5
|
||||
q[2] = p6 + p7
|
||||
q[3] = p2 - p3 + p5 - p7
|
||||
result = fromQuarters(q)
|
||||
|
||||
|
||||
when isMainModule:
|
||||
let
|
||||
a = @[@[float 1, 2],
|
||||
@[float 3, 4]]
|
||||
b = @[@[float 5, 6],
|
||||
@[float 7, 8]]
|
||||
c = @[@[float 1, 1, 1, 1],
|
||||
@[float 2, 4, 8, 16],
|
||||
@[float 3, 9, 27, 81],
|
||||
@[float 4, 16, 64, 256]]
|
||||
d = @[@[4.0, -3, 4/3, -1/4],
|
||||
@[-13/3, 19/4, -7/3, 11/24],
|
||||
@[3/2, -2, 7/6, -1/4],
|
||||
@[-1/6, 1/4, -1/6, 1/24]]
|
||||
e = @[@[float 1, 2, 3, 4],
|
||||
@[float 5, 6, 7, 8],
|
||||
@[float 9, 10, 11, 12],
|
||||
@[float 13, 14, 15, 16]]
|
||||
f = @[@[float 1, 0, 0, 0],
|
||||
@[float 0, 1, 0, 0],
|
||||
@[float 0, 0, 1, 0],
|
||||
@[float 0, 0, 0, 1]]
|
||||
|
||||
echo "Using 'normal' matrix multiplication:"
|
||||
echo " a * b = ", (a * b).toString(10)
|
||||
echo " c * d = ", (c * d).toString(6)
|
||||
echo " e * f = ", (e * f).toString(10)
|
||||
|
||||
echo "\nUsing 'Strassen' matrix multiplication:"
|
||||
echo " a * b = ", strassen(a, b).toString(10)
|
||||
echo " c * d = ", strassen(c, d).toString(6)
|
||||
echo " e * f = ", strassen(e, f).toString(10)
|
||||
84
Task/Strassens-algorithm/Phix/strassens-algorithm.phix
Normal file
84
Task/Strassens-algorithm/Phix/strassens-algorithm.phix
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
(phixonline)-->
|
||||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
|
||||
<span style="color: #008080;">function</span> <span style="color: #000000;">strassen</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">l</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])!=</span><span style="color: #000000;">l</span>
|
||||
<span style="color: #008080;">or</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)!=</span><span style="color: #000000;">l</span>
|
||||
<span style="color: #008080;">or</span> <span style="color: #7060A8;">length</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])!=</span><span style="color: #000000;">l</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"two equal square matrices only"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span> <span style="color: #008080;">return</span> <span style="color: #7060A8;">sq_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #008080;">if</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
|
||||
<span style="color: #7060A8;">crash</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"2^n matrices only"</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
|
||||
<span style="color: #004080;">integer</span> <span style="color: #000000;">h</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">a11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a12</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a21</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a22</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b12</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b21</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b22</span><span style="color: #0000FF;">}</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">h</span><span style="color: #0000FF;">),</span><span style="color: #000000;">h</span><span style="color: #0000FF;">),</span><span style="color: #000000;">8</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">h</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">h</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">a11</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #000000;">a12</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">h</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #000000;">a21</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">h</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #000000;">a22</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">h</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">h</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #000000;">b11</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #000000;">b12</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">h</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #000000;">b21</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">h</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #000000;">b22</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">h</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">h</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #004080;">sequence</span> <span style="color: #000000;">p1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">strassen</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a12</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a22</span><span style="color: #0000FF;">),</span> <span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b21</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b22</span><span style="color: #0000FF;">)),</span>
|
||||
<span style="color: #000000;">p2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">strassen</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a22</span><span style="color: #0000FF;">),</span> <span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b22</span><span style="color: #0000FF;">)),</span>
|
||||
<span style="color: #000000;">p3</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">strassen</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a21</span><span style="color: #0000FF;">),</span> <span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b12</span><span style="color: #0000FF;">)),</span>
|
||||
<span style="color: #000000;">p4</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">strassen</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a12</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">b22</span><span style="color: #0000FF;">),</span>
|
||||
<span style="color: #000000;">p5</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">strassen</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a11</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">sq_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b12</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b22</span><span style="color: #0000FF;">)),</span>
|
||||
<span style="color: #000000;">p6</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">strassen</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a22</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">sq_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b21</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b11</span><span style="color: #0000FF;">)),</span>
|
||||
<span style="color: #000000;">p7</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">strassen</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">a21</span><span style="color: #0000FF;">,</span><span style="color: #000000;">a22</span><span style="color: #0000FF;">),</span> <span style="color: #000000;">b11</span><span style="color: #0000FF;">),</span>
|
||||
|
||||
<span style="color: #000000;">c11</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_sub</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p2</span><span style="color: #0000FF;">),</span><span style="color: #000000;">p4</span><span style="color: #0000FF;">),</span><span style="color: #000000;">p6</span><span style="color: #0000FF;">),</span>
|
||||
<span style="color: #000000;">c12</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p4</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p5</span><span style="color: #0000FF;">),</span>
|
||||
<span style="color: #000000;">c21</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p6</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p7</span><span style="color: #0000FF;">),</span>
|
||||
<span style="color: #000000;">c22</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sq_sub</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_add</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">sq_sub</span><span style="color: #0000FF;">(</span><span style="color: #000000;">p2</span><span style="color: #0000FF;">,</span><span style="color: #000000;">p3</span><span style="color: #0000FF;">),</span><span style="color: #000000;">p5</span><span style="color: #0000FF;">),</span><span style="color: #000000;">p7</span><span style="color: #0000FF;">),</span>
|
||||
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">l</span><span style="color: #0000FF;">),</span><span style="color: #000000;">l</span><span style="color: #0000FF;">)</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">i</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">h</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #008080;">for</span> <span style="color: #000000;">j</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">h</span> <span style="color: #008080;">do</span>
|
||||
<span style="color: #000000;">c</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">c11</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #000000;">c</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">h</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">c12</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #000000;">c</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">h</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">c21</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #000000;">c</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">+</span><span style="color: #000000;">h</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">+</span><span style="color: #000000;">h</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">c22</span><span style="color: #0000FF;">[</span><span style="color: #000000;">i</span><span style="color: #0000FF;">][</span><span style="color: #000000;">j</span><span style="color: #0000FF;">]</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
|
||||
<span style="color: #008080;">return</span> <span style="color: #000000;">c</span>
|
||||
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
|
||||
|
||||
<span style="color: #7060A8;">ppOpt</span><span style="color: #0000FF;">({</span><span style="color: #004600;">pp_Nest</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #004600;">pp_IntFmt</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%3d"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">pp_FltFmt</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%3.0f"</span><span style="color: #0000FF;">,</span><span style="color: #004600;">pp_IntCh</span><span style="color: #0000FF;">,</span><span style="color: #004600;">false</span><span style="color: #0000FF;">})</span>
|
||||
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">A</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">4</span><span style="color: #0000FF;">}},</span>
|
||||
<span style="color: #000000;">B</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #000000;">6</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">7</span><span style="color: #0000FF;">,</span><span style="color: #000000;">8</span><span style="color: #0000FF;">}}</span>
|
||||
<span style="color: #7060A8;">pp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">strassen</span><span style="color: #0000FF;">(</span><span style="color: #000000;">A</span><span style="color: #0000FF;">,</span><span style="color: #000000;">B</span><span style="color: #0000FF;">))</span>
|
||||
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">C</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span> <span style="color: #0000FF;">{</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span> <span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">16</span> <span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">27</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">81</span> <span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">16</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">64</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">256</span> <span style="color: #0000FF;">}},</span>
|
||||
<span style="color: #000000;">D</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{</span> <span style="color: #0000FF;">{</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">/</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">/</span> <span style="color: #000000;">4</span> <span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{-</span><span style="color: #000000;">13</span><span style="color: #0000FF;">/</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">19</span><span style="color: #0000FF;">/</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">7</span><span style="color: #0000FF;">/</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">11</span><span style="color: #0000FF;">/</span><span style="color: #000000;">24</span> <span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">/</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">/</span> <span style="color: #000000;">4</span> <span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">/</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">/</span><span style="color: #000000;">4</span><span style="color: #0000FF;">,</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">/</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">/</span><span style="color: #000000;">24</span> <span style="color: #0000FF;">}}</span>
|
||||
<span style="color: #7060A8;">pp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">strassen</span><span style="color: #0000FF;">(</span><span style="color: #000000;">C</span><span style="color: #0000FF;">,</span><span style="color: #000000;">D</span><span style="color: #0000FF;">))</span>
|
||||
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">F</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">2</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">3</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">4</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span> <span style="color: #000000;">5</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">6</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">7</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">8</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span> <span style="color: #000000;">9</span><span style="color: #0000FF;">,</span><span style="color: #000000;">10</span><span style="color: #0000FF;">,</span><span style="color: #000000;">11</span><span style="color: #0000FF;">,</span><span style="color: #000000;">12</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">13</span><span style="color: #0000FF;">,</span><span style="color: #000000;">14</span><span style="color: #0000FF;">,</span><span style="color: #000000;">15</span><span style="color: #0000FF;">,</span><span style="color: #000000;">16</span><span style="color: #0000FF;">}},</span>
|
||||
<span style="color: #000000;">G</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">}}</span>
|
||||
<span style="color: #7060A8;">pp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">strassen</span><span style="color: #0000FF;">(</span><span style="color: #000000;">F</span><span style="color: #0000FF;">,</span><span style="color: #000000;">G</span><span style="color: #0000FF;">))</span>
|
||||
|
||||
<span style="color: #008080;">constant</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">sqrt</span><span style="color: #0000FF;">(</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">,</span>
|
||||
<span style="color: #000000;">R</span> <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">{{</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">},</span>
|
||||
<span style="color: #0000FF;">{-</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span><span style="color: #000000;">r</span><span style="color: #0000FF;">}}</span>
|
||||
<span style="color: #7060A8;">pp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">strassen</span><span style="color: #0000FF;">(</span><span style="color: #000000;">R</span><span style="color: #0000FF;">,</span><span style="color: #000000;">R</span><span style="color: #0000FF;">))</span>
|
||||
<!--
|
||||
166
Task/Strassens-algorithm/Python/strassens-algorithm.py
Normal file
166
Task/Strassens-algorithm/Python/strassens-algorithm.py
Normal file
|
|
@ -0,0 +1,166 @@
|
|||
"""Matrix multiplication using Strassen's algorithm. Requires Python >= 3.7."""
|
||||
|
||||
from __future__ import annotations
|
||||
from itertools import chain
|
||||
from typing import List
|
||||
from typing import NamedTuple
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class Shape(NamedTuple):
|
||||
rows: int
|
||||
cols: int
|
||||
|
||||
|
||||
class Matrix(List):
|
||||
"""A matrix implemented as a two-dimensional list."""
|
||||
|
||||
@classmethod
|
||||
def block(cls, blocks) -> Matrix:
|
||||
"""Return a new Matrix assembled from nested blocks."""
|
||||
m = Matrix()
|
||||
for hblock in blocks:
|
||||
for row in zip(*hblock):
|
||||
m.append(list(chain.from_iterable(row)))
|
||||
|
||||
return m
|
||||
|
||||
def dot(self, b: Matrix) -> Matrix:
|
||||
"""Return a new Matrix that is the product of this matrix and matrix `b`.
|
||||
Uses 'simple' or 'naive' matrix multiplication."""
|
||||
assert self.shape.cols == b.shape.rows
|
||||
m = Matrix()
|
||||
for row in self:
|
||||
new_row = []
|
||||
for c in range(len(b[0])):
|
||||
col = [b[r][c] for r in range(len(b))]
|
||||
new_row.append(sum(x * y for x, y in zip(row, col)))
|
||||
m.append(new_row)
|
||||
return m
|
||||
|
||||
def __matmul__(self, b: Matrix) -> Matrix:
|
||||
return self.dot(b)
|
||||
|
||||
def __add__(self, b: Matrix) -> Matrix:
|
||||
"""Matrix addition."""
|
||||
assert self.shape == b.shape
|
||||
rows, cols = self.shape
|
||||
return Matrix(
|
||||
[[self[i][j] + b[i][j] for j in range(cols)] for i in range(rows)]
|
||||
)
|
||||
|
||||
def __sub__(self, b: Matrix) -> Matrix:
|
||||
"""Matrix subtraction."""
|
||||
assert self.shape == b.shape
|
||||
rows, cols = self.shape
|
||||
return Matrix(
|
||||
[[self[i][j] - b[i][j] for j in range(cols)] for i in range(rows)]
|
||||
)
|
||||
|
||||
def strassen(self, b: Matrix) -> Matrix:
|
||||
"""Return a new Matrix that is the product of this matrix and matrix `b`.
|
||||
Uses strassen algorithm."""
|
||||
rows, cols = self.shape
|
||||
|
||||
assert rows == cols, "matrices must be square"
|
||||
assert self.shape == b.shape, "matrices must be the same shape"
|
||||
assert rows and (rows & rows - 1) == 0, "shape must be a power of 2"
|
||||
|
||||
if rows == 1:
|
||||
return self.dot(b)
|
||||
|
||||
p = rows // 2 # partition
|
||||
|
||||
a11 = Matrix([n[:p] for n in self[:p]])
|
||||
a12 = Matrix([n[p:] for n in self[:p]])
|
||||
a21 = Matrix([n[:p] for n in self[p:]])
|
||||
a22 = Matrix([n[p:] for n in self[p:]])
|
||||
|
||||
b11 = Matrix([n[:p] for n in b[:p]])
|
||||
b12 = Matrix([n[p:] for n in b[:p]])
|
||||
b21 = Matrix([n[:p] for n in b[p:]])
|
||||
b22 = Matrix([n[p:] for n in b[p:]])
|
||||
|
||||
m1 = (a11 + a22).strassen(b11 + b22)
|
||||
m2 = (a21 + a22).strassen(b11)
|
||||
m3 = a11.strassen(b12 - b22)
|
||||
m4 = a22.strassen(b21 - b11)
|
||||
m5 = (a11 + a12).strassen(b22)
|
||||
m6 = (a21 - a11).strassen(b11 + b12)
|
||||
m7 = (a12 - a22).strassen(b21 + b22)
|
||||
|
||||
c11 = m1 + m4 - m5 + m7
|
||||
c12 = m3 + m5
|
||||
c21 = m2 + m4
|
||||
c22 = m1 - m2 + m3 + m6
|
||||
|
||||
return Matrix.block([[c11, c12], [c21, c22]])
|
||||
|
||||
def round(self, ndigits: Optional[int] = None) -> Matrix:
|
||||
return Matrix([[round(i, ndigits) for i in row] for row in self])
|
||||
|
||||
@property
|
||||
def shape(self) -> Shape:
|
||||
cols = len(self[0]) if self else 0
|
||||
return Shape(len(self), cols)
|
||||
|
||||
|
||||
def examples():
|
||||
a = Matrix(
|
||||
[
|
||||
[1, 2],
|
||||
[3, 4],
|
||||
]
|
||||
)
|
||||
b = Matrix(
|
||||
[
|
||||
[5, 6],
|
||||
[7, 8],
|
||||
]
|
||||
)
|
||||
c = Matrix(
|
||||
[
|
||||
[1, 1, 1, 1],
|
||||
[2, 4, 8, 16],
|
||||
[3, 9, 27, 81],
|
||||
[4, 16, 64, 256],
|
||||
]
|
||||
)
|
||||
d = Matrix(
|
||||
[
|
||||
[4, -3, 4 / 3, -1 / 4],
|
||||
[-13 / 3, 19 / 4, -7 / 3, 11 / 24],
|
||||
[3 / 2, -2, 7 / 6, -1 / 4],
|
||||
[-1 / 6, 1 / 4, -1 / 6, 1 / 24],
|
||||
]
|
||||
)
|
||||
e = Matrix(
|
||||
[
|
||||
[1, 2, 3, 4],
|
||||
[5, 6, 7, 8],
|
||||
[9, 10, 11, 12],
|
||||
[13, 14, 15, 16],
|
||||
]
|
||||
)
|
||||
f = Matrix(
|
||||
[
|
||||
[1, 0, 0, 0],
|
||||
[0, 1, 0, 0],
|
||||
[0, 0, 1, 0],
|
||||
[0, 0, 0, 1],
|
||||
]
|
||||
)
|
||||
|
||||
print("Naive matrix multiplication:")
|
||||
print(f" a * b = {a @ b}")
|
||||
print(f" c * d = {(c @ d).round()}")
|
||||
print(f" e * f = {e @ f}")
|
||||
|
||||
print("Strassen's matrix multiplication:")
|
||||
print(f" a * b = {a.strassen(b)}")
|
||||
print(f" c * d = {c.strassen(d).round()}")
|
||||
print(f" e * f = {e.strassen(f)}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
examples()
|
||||
94
Task/Strassens-algorithm/Raku/strassens-algorithm.raku
Normal file
94
Task/Strassens-algorithm/Raku/strassens-algorithm.raku
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
# 20210126 Raku programming solution
|
||||
|
||||
use Math::Libgsl::Constants;
|
||||
use Math::Libgsl::Matrix;
|
||||
use Math::Libgsl::BLAS;
|
||||
|
||||
my @M;
|
||||
|
||||
sub SQM (\in) { # create custom sq matrix from CSV
|
||||
die "Not a ■" if (my \L = in.split(/\,/)).sqrt != (my \size = L.sqrt.Int);
|
||||
my Math::Libgsl::Matrix \M .= new: size, size;
|
||||
for ^size Z L.rotor(size) -> ($i, @row) { M.set-row: $i, @row }
|
||||
M
|
||||
}
|
||||
|
||||
sub infix:<⊗>(\x,\y) { # custom multiplication
|
||||
my Math::Libgsl::Matrix \z .= new: x.size1, x.size2;
|
||||
dgemm(CblasNoTrans, CblasNoTrans, 1, x, y, 1, z);
|
||||
z
|
||||
}
|
||||
|
||||
sub infix:<⊕>(\x,\y) { # custom addition
|
||||
my Math::Libgsl::Matrix \z .= new: x.size1, x.size2;
|
||||
z.copy(x).add(y)
|
||||
}
|
||||
|
||||
sub infix:<⊖>(\x,\y) { # custom subtraction
|
||||
my Math::Libgsl::Matrix \z .= new: x.size1, x.size2;
|
||||
z.copy(x).sub(y)
|
||||
}
|
||||
|
||||
sub Strassen($A, $B) {
|
||||
|
||||
{ return $A ⊗ $B } if (my \n = $A.size1) == 1;
|
||||
|
||||
my Math::Libgsl::Matrix ($A11,$A12,$A21,$A22,$B11,$B12,$B21,$B22);
|
||||
my Math::Libgsl::Matrix ($P1,$P2,$P3,$P4,$P5,$P6,$P7);
|
||||
my Math::Libgsl::Matrix::View ($mv1,$mv2,$mv3,$mv4,$mv5,$mv6,$mv7,$mv8);
|
||||
($mv1,$mv2,$mv3,$mv4,$mv5,$mv6,$mv7,$mv8)».=new ;
|
||||
|
||||
my \half = n div 2; # dimension of quarter submatrices
|
||||
|
||||
$A11 = $mv1.submatrix($A, 0,0, half,half); #
|
||||
$A12 = $mv2.submatrix($A, 0,half, half,half); # create quarter views
|
||||
$A21 = $mv3.submatrix($A, half,0, half,half); # of operand matrices
|
||||
$A22 = $mv4.submatrix($A, half,half, half,half); #
|
||||
$B11 = $mv5.submatrix($B, 0,0, half,half); # 11 12
|
||||
$B12 = $mv6.submatrix($B, 0,half, half,half); #
|
||||
$B21 = $mv7.submatrix($B, half,0, half,half); # 21 22
|
||||
$B22 = $mv8.submatrix($B, half,half, half,half); #
|
||||
|
||||
$P1 = Strassen($A12 ⊖ $A22, $B21 ⊕ $B22);
|
||||
$P2 = Strassen($A11 ⊕ $A22, $B11 ⊕ $B22);
|
||||
$P3 = Strassen($A11 ⊖ $A21, $B11 ⊕ $B12);
|
||||
$P4 = Strassen($A11 ⊕ $A12, $B22 );
|
||||
$P5 = Strassen($A11, $B12 ⊖ $B22);
|
||||
$P6 = Strassen($A22, $B21 ⊖ $B11);
|
||||
$P7 = Strassen($A21 ⊕ $A22, $B11 );
|
||||
|
||||
my Math::Libgsl::Matrix $C .= new: n, n; # Build C from
|
||||
my Math::Libgsl::Matrix::View ($mvC11,$mvC12,$mvC21,$mvC22); # C11 C12
|
||||
($mvC11,$mvC12,$mvC21,$mvC22)».=new ; # C21 C22
|
||||
|
||||
given $mvC11.submatrix($C, 0,0, half,half) { .add: (($P1 ⊕ $P2) ⊖ $P4) ⊕ $P6 };
|
||||
given $mvC12.submatrix($C, 0,half, half,half) { .add: $P4 ⊕ $P5 };
|
||||
given $mvC21.submatrix($C, half,0, half,half) { .add: $P6 ⊕ $P7 };
|
||||
given $mvC22.submatrix($C, half,half, half,half) { .add: (($P2 ⊖ $P3) ⊕ $P5) ⊖ $P7 };
|
||||
|
||||
$C
|
||||
}
|
||||
|
||||
for $=pod[0].contents { next if /^\n$/ ; @M.append: SQM $_ }
|
||||
|
||||
for @M.rotor(2) {
|
||||
my $product = @_[0] ⊗ @_[1];
|
||||
# $product.get-row($_)».round(1).fmt('%2d').put for ^$product.size1;
|
||||
|
||||
say "Regular multiply:";
|
||||
$product.get-row($_)».fmt('%.10g').put for ^$product.size1;
|
||||
|
||||
$product = Strassen @_[0], @_[1];
|
||||
|
||||
say "Strassen multiply:";
|
||||
$product.get-row($_)».fmt('%.10g').put for ^$product.size1;
|
||||
}
|
||||
|
||||
=begin code
|
||||
1,2,3,4
|
||||
5,6,7,8
|
||||
1,1,1,1,2,4,8,16,3,9,27,81,4,16,64,256
|
||||
4,-3,4/3,-1/4,-13/3,19/4,-7/3,11/24,3/2,-2,7/6,-1/4,-1/6,1/4,-1/6,1/24
|
||||
1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
|
||||
1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1
|
||||
=end code
|
||||
163
Task/Strassens-algorithm/Swift/strassens-algorithm.swift
Normal file
163
Task/Strassens-algorithm/Swift/strassens-algorithm.swift
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
// Matrix Strassen Multiplication
|
||||
func strassenMultiply(matrix1: Matrix, matrix2: Matrix) -> Matrix {
|
||||
precondition(matrix1.columns == matrix2.columns,
|
||||
"Two matrices can only be matrix multiplied if one has dimensions mxn & the other has dimensions nxp where m, n, p are in R")
|
||||
|
||||
// Transform to square matrix
|
||||
let maxColumns = Swift.max(matrix1.rows, matrix1.columns, matrix2.rows, matrix2.columns)
|
||||
let pwr2 = nextPowerOfTwo(num: maxColumns)
|
||||
var sqrMatrix1 = Matrix(rows: pwr2, columns: pwr2)
|
||||
var sqrMatrix2 = Matrix(rows: pwr2, columns: pwr2)
|
||||
|
||||
// fill square matrix 1 with values
|
||||
for i in 0..<matrix1.rows {
|
||||
for j in 0..<matrix1.columns{
|
||||
sqrMatrix1[i, j] = matrix1[i, j]
|
||||
}
|
||||
}
|
||||
// fill square matrix 2 with values
|
||||
for i in 0..<matrix2.rows {
|
||||
for j in 0..<matrix2.columns{
|
||||
sqrMatrix2[i, j] = matrix2[i, j]
|
||||
}
|
||||
}
|
||||
|
||||
// Get strassen result and transfer to array with proper size
|
||||
let formulaResult = strassenFormula(matrix1: sqrMatrix1, matrix2: sqrMatrix2)
|
||||
var finalResult = Matrix(rows: matrix1.rows, columns: matrix2.columns)
|
||||
for i in 0..<finalResult.rows{
|
||||
for j in 0..<finalResult.columns {
|
||||
finalResult[i, j] = formulaResult[i, j]
|
||||
}
|
||||
}
|
||||
return finalResult
|
||||
}
|
||||
|
||||
// Calculate next power of 2
|
||||
func nextPowerOfTwo(num: Int) -> Int {
|
||||
// formula for next power of 2
|
||||
return Int(pow(2,(ceil(log2(Double(num))))))
|
||||
}
|
||||
|
||||
// Multiply Matrices Using Strassen Formula
|
||||
func strassenFormula(matrix1: Matrix, matrix2: Matrix) -> Matrix {
|
||||
precondition(matrix1.rows == matrix1.columns && matrix2.rows == matrix2.columns, "Matrices need to be square")
|
||||
guard matrix1.rows > 1 && matrix2.rows > 1 else { return matrix1 * matrix2 }
|
||||
|
||||
let rowHalf = matrix1.rows / 2
|
||||
// Strassen Formula https://www.geeksforgeeks.org/easy-way-remember-strassens-matrix-equation/
|
||||
// p1 = a(f-h) p2 = (a+b)h
|
||||
// p2 = (c+d)e p4 = d(g-e)
|
||||
// p5 = (a+d)(e+h) p6 = (b-d)(g+h)
|
||||
// p7 = (a-c)(e+f)
|
||||
|a b| x |e f| = |(p5+p4-p2+p6) (p1+p2)|
|
||||
|c d| |g h| |(p3+p4) (p1+p5-p3-p7)|
|
||||
Matrix 1 Matrix 2 Result
|
||||
|
||||
// create empty matrices for a, b, c, d, e, f, g, h
|
||||
var a = Matrix(rows: rowHalf, columns: rowHalf)
|
||||
var b = Matrix(rows: rowHalf, columns: rowHalf)
|
||||
var c = Matrix(rows: rowHalf, columns: rowHalf)
|
||||
var d = Matrix(rows: rowHalf, columns: rowHalf)
|
||||
var e = Matrix(rows: rowHalf, columns: rowHalf)
|
||||
var f = Matrix(rows: rowHalf, columns: rowHalf)
|
||||
var g = Matrix(rows: rowHalf, columns: rowHalf)
|
||||
var h = Matrix(rows: rowHalf, columns: rowHalf)
|
||||
|
||||
// fill the matrices with values
|
||||
for i in 0..<rowHalf {
|
||||
for j in 0..<rowHalf {
|
||||
a[i, j] = matrix1[i, j]
|
||||
b[i, j] = matrix1[i, j+rowHalf]
|
||||
c[i, j] = matrix1[i+rowHalf, j]
|
||||
d[i, j] = matrix1[i+rowHalf, j+rowHalf]
|
||||
e[i, j] = matrix2[i, j]
|
||||
f[i, j] = matrix2[i, j+rowHalf]
|
||||
g[i, j] = matrix2[i+rowHalf, j]
|
||||
h[i, j] = matrix2[i+rowHalf, j+rowHalf]
|
||||
}
|
||||
}
|
||||
|
||||
// a * (f - h)
|
||||
let p1 = strassenFormula(matrix1: a, matrix2: (f - h))
|
||||
// (a + b) * h
|
||||
let p2 = strassenFormula(matrix1: (a + b), matrix2: h)
|
||||
// (c + d) * e
|
||||
let p3 = strassenFormula(matrix1: (c + d), matrix2: e)
|
||||
// d * (g - e)
|
||||
let p4 = strassenFormula(matrix1: d, matrix2: (g - e))
|
||||
// (a + d) * (e + h)
|
||||
let p5 = strassenFormula(matrix1: (a + d), matrix2: (e + h))
|
||||
// (b - d) * (g + h)
|
||||
let p6 = strassenFormula(matrix1: (b - d), matrix2: (g + h))
|
||||
// (a - c) * (e + f)
|
||||
let p7 = strassenFormula(matrix1: (a - c), matrix2: (e + f))
|
||||
|
||||
// p5 + p4 - p2 + p6
|
||||
let result11 = p5 + p4 - p2 + p6
|
||||
// p1 + p2
|
||||
let result12 = p1 + p2
|
||||
// p3 + p4
|
||||
let result21 = p3 + p4
|
||||
// p1 + p5 - p3 - p7
|
||||
let result22 = p1 + p5 - p3 - p7
|
||||
|
||||
// create an empty matrix for result and fill with values
|
||||
var result = Matrix(rows: matrix1.rows, columns: matrix1.rows)
|
||||
for i in 0..<rowHalf {
|
||||
for j in 0..<rowHalf {
|
||||
result[i, j] = result11[i, j]
|
||||
result[i, j+rowHalf] = result12[i, j]
|
||||
result[i+rowHalf, j] = result21[i, j]
|
||||
result[i+rowHalf, j+rowHalf] = result22[i, j]
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func main(){
|
||||
// Matrix Class https://github.com/hollance/Matrix/blob/master/Matrix.swift
|
||||
var a = Matrix(rows: 2, columns: 2)
|
||||
a[row: 0] = [1, 2]
|
||||
a[row: 1] = [3, 4]
|
||||
|
||||
var b = Matrix(rows: 2, columns: 2)
|
||||
b[row: 0] = [5, 6]
|
||||
b[row: 1] = [7, 8]
|
||||
|
||||
var c = Matrix(rows: 4, columns: 4)
|
||||
c[row: 0] = [1, 1, 1,1]
|
||||
c[row: 1] = [2, 4, 8, 16]
|
||||
c[row: 2] = [3, 9, 27, 81]
|
||||
c[row: 3] = [4, 16, 64, 256]
|
||||
|
||||
var d = Matrix(rows: 4, columns: 4)
|
||||
d[row: 0] = [4, -3, Double(4/3), Double(-1/4)]
|
||||
d[row: 1] = [Double(-13/3), Double(19/4), Double(-7/3), Double(11/24)]
|
||||
d[row: 2] = [Double(3/2), Double(-2), Double(7/6), Double(-1/4)]
|
||||
d[row: 3] = [Double(-1/6), Double(1/4), Double(-1/6), Double(1/24)]
|
||||
|
||||
var e = Matrix(rows: 4, columns: 4)
|
||||
e[row: 0] = [1, 2, 3, 4]
|
||||
e[row: 1] = [5, 6, 7, 8]
|
||||
e[row: 2] = [9, 10, 11, 12]
|
||||
e[row: 3] = [13, 14, 15, 16]
|
||||
|
||||
var f = Matrix(rows: 4, columns: 4)
|
||||
f[row: 0] = [1, 0, 0, 0]
|
||||
f[row: 1] = [0, 1, 0 ,0]
|
||||
f[row: 2] = [0 ,0 ,1, 0]
|
||||
f[row: 3] = [0, 0 ,0 ,1]
|
||||
|
||||
let result1 = strassenMultiply(matrix1: a, matrix2: b)
|
||||
print("AxB")
|
||||
print(result1.description)
|
||||
let result2 = strassenMultiply(matrix1: c, matrix2: d)
|
||||
print("CxD")
|
||||
print(result2.description)
|
||||
let result3 = strassenMultiply(matrix1: e, matrix2: f)
|
||||
print("ExF")
|
||||
print(result3.description)
|
||||
}
|
||||
main()
|
||||
154
Task/Strassens-algorithm/Wren/strassens-algorithm-1.wren
Normal file
154
Task/Strassens-algorithm/Wren/strassens-algorithm-1.wren
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
class Matrix {
|
||||
construct new(a) {
|
||||
if (a.type != List || a.count == 0 || a[0].type != List || a[0].count == 0 || a[0][0].type != Num) {
|
||||
Fiber.abort("Argument must be a non-empty two dimensional list of numbers.")
|
||||
}
|
||||
_a = a
|
||||
}
|
||||
|
||||
rows { _a.count }
|
||||
cols { _a[0].count }
|
||||
|
||||
+(b) {
|
||||
if (b.type != Matrix) Fiber.abort("Argument must be a matrix.")
|
||||
if ((this.rows != b.rows) || (this.cols != b.cols)) {
|
||||
Fiber.abort("Matrices must have the same dimensions.")
|
||||
}
|
||||
var c = List.filled(rows, null)
|
||||
for (i in 0...rows) {
|
||||
c[i] = List.filled(cols, 0)
|
||||
for (j in 0...cols) c[i][j] = _a[i][j] + b[i, j]
|
||||
}
|
||||
return Matrix.new(c)
|
||||
}
|
||||
|
||||
- { this * -1 }
|
||||
|
||||
-(b) { this + (-b) }
|
||||
|
||||
*(b) {
|
||||
var c = List.filled(rows, null)
|
||||
if (b is Num) {
|
||||
for (i in 0...rows) {
|
||||
c[i] = List.filled(cols, 0)
|
||||
for (j in 0...cols) c[i][j] = _a[i][j] * b
|
||||
}
|
||||
} else if (b is Matrix) {
|
||||
if (this.cols != b.rows) Fiber.abort("Cannot multiply these matrices.")
|
||||
for (i in 0...rows) {
|
||||
c[i] = List.filled(b.cols, 0)
|
||||
for (j in 0...b.cols) {
|
||||
for (k in 0...b.rows) c[i][j] = c[i][j] + _a[i][k] * b[k, j]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Fiber.abort("Argument must be a matrix or a number.")
|
||||
}
|
||||
return Matrix.new(c)
|
||||
}
|
||||
|
||||
[i] { _a[i].toList }
|
||||
|
||||
[i, j] { _a[i][j] }
|
||||
|
||||
toString { _a.toString }
|
||||
|
||||
// rounds all elements to 'p' places
|
||||
toString(p) {
|
||||
var s = List.filled(rows, "")
|
||||
var pow = 10.pow(p)
|
||||
for (i in 0...rows) {
|
||||
var t = List.filled(cols, "")
|
||||
for (j in 0...cols) {
|
||||
var r = (_a[i][j]*pow).round / pow
|
||||
t[j] = r.toString
|
||||
if (t[j] == "-0") t[j] = "0"
|
||||
}
|
||||
s[i] = t.toString
|
||||
}
|
||||
return s
|
||||
}
|
||||
}
|
||||
|
||||
var params = Fn.new { |r, c|
|
||||
return [
|
||||
[0...r, 0...c, 0, 0],
|
||||
[0...r, c...2*c, 0, c],
|
||||
[r...2*r, 0...c, r, 0],
|
||||
[r...2*r, c...2*c, r, c]
|
||||
]
|
||||
}
|
||||
|
||||
var toQuarters = Fn.new { |m|
|
||||
var r = (m.rows/2).floor
|
||||
var c = (m.cols/2).floor
|
||||
var p = params.call(r, c)
|
||||
var quarters = []
|
||||
for (k in 0..3) {
|
||||
var q = List.filled(r, null)
|
||||
for (i in p[k][0]) {
|
||||
q[i - p[k][2]] = List.filled(c, 0)
|
||||
for (j in p[k][1]) q[i - p[k][2]][j - p[k][3]] = m[i, j]
|
||||
}
|
||||
quarters.add(Matrix.new(q))
|
||||
}
|
||||
return quarters
|
||||
}
|
||||
|
||||
var fromQuarters = Fn.new { |q|
|
||||
var r = q[0].rows
|
||||
var c = q[0].cols
|
||||
var p = params.call(r, c)
|
||||
r = r * 2
|
||||
c = c * 2
|
||||
var m = List.filled(r, null)
|
||||
for (i in 0...c) m[i] = List.filled(c, 0)
|
||||
for (k in 0..3) {
|
||||
for (i in p[k][0]) {
|
||||
for (j in p[k][1]) m[i][j] = q[k][i - p[k][2], j - p[k][3]]
|
||||
}
|
||||
}
|
||||
return Matrix.new(m)
|
||||
}
|
||||
|
||||
var strassen // recursive
|
||||
strassen = Fn.new { |a, b|
|
||||
if (a.rows != a.cols || b.rows != b.cols || a.rows != b.rows) {
|
||||
Fiber.abort("Matrices must be square and of equal size.")
|
||||
}
|
||||
if (a.rows == 0 || (a.rows & (a.rows - 1)) != 0) {
|
||||
Fiber.abort("Size of matrices must be a power of two.")
|
||||
}
|
||||
if (a.rows == 1) return a * b
|
||||
var qa = toQuarters.call(a)
|
||||
var qb = toQuarters.call(b)
|
||||
var p1 = strassen.call(qa[1] - qa[3], qb[2] + qb[3])
|
||||
var p2 = strassen.call(qa[0] + qa[3], qb[0] + qb[3])
|
||||
var p3 = strassen.call(qa[0] - qa[2], qb[0] + qb[1])
|
||||
var p4 = strassen.call(qa[0] + qa[1], qb[3])
|
||||
var p5 = strassen.call(qa[0], qb[1] - qb[3])
|
||||
var p6 = strassen.call(qa[3], qb[2] - qb[0])
|
||||
var p7 = strassen.call(qa[2] + qa[3], qb[0])
|
||||
var q = List.filled(4, null)
|
||||
q[0] = p1 + p2 - p4 + p6
|
||||
q[1] = p4 + p5
|
||||
q[2] = p6 + p7
|
||||
q[3] = p2 - p3 + p5 - p7
|
||||
return fromQuarters.call(q)
|
||||
}
|
||||
|
||||
var a = Matrix.new([ [1,2], [3, 4] ])
|
||||
var b = Matrix.new([ [5,6], [7, 8] ])
|
||||
var c = Matrix.new([ [1, 1, 1, 1], [2, 4, 8, 16], [3, 9, 27, 81], [4, 16, 64, 256] ])
|
||||
var d = Matrix.new([ [4, -3, 4/3, -1/4], [-13/3, 19/4, -7/3, 11/24],
|
||||
[3/2, -2, 7/6, -1/4], [-1/6, 1/4, -1/6, 1/24] ])
|
||||
var e = Matrix.new([ [1, 2, 3, 4], [5, 6, 7, 8], [9,10,11,12], [13,14,15,16] ])
|
||||
var f = Matrix.new([ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1] ])
|
||||
System.print("Using 'normal' matrix multiplication:")
|
||||
System.print(" a * b = %(a * b)")
|
||||
System.print(" c * d = %((c * d).toString(6))")
|
||||
System.print(" e * f = %(e * f)")
|
||||
System.print("\nUsing 'Strassen' matrix multiplication:")
|
||||
System.print(" a * b = %(strassen.call(a, b))")
|
||||
System.print(" c * d = %(strassen.call(c, d).toString(6))")
|
||||
System.print(" e * f = %(strassen.call(e, f))")
|
||||
84
Task/Strassens-algorithm/Wren/strassens-algorithm-2.wren
Normal file
84
Task/Strassens-algorithm/Wren/strassens-algorithm-2.wren
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
import "./matrix" for Matrix
|
||||
|
||||
var params = Fn.new { |r, c|
|
||||
return [
|
||||
[0...r, 0...c, 0, 0],
|
||||
[0...r, c...2*c, 0, c],
|
||||
[r...2*r, 0...c, r, 0],
|
||||
[r...2*r, c...2*c, r, c]
|
||||
]
|
||||
}
|
||||
|
||||
var toQuarters = Fn.new { |m|
|
||||
var r = (m.numRows/2).floor
|
||||
var c = (m.numCols/2).floor
|
||||
var p = params.call(r, c)
|
||||
var quarters = []
|
||||
for (k in 0..3) {
|
||||
var q = List.filled(r, null)
|
||||
for (i in p[k][0]) {
|
||||
q[i - p[k][2]] = List.filled(c, 0)
|
||||
for (j in p[k][1]) q[i - p[k][2]][j - p[k][3]] = m[i, j]
|
||||
}
|
||||
quarters.add(Matrix.new(q))
|
||||
}
|
||||
return quarters
|
||||
}
|
||||
|
||||
var fromQuarters = Fn.new { |q|
|
||||
var r = q[0].numRows
|
||||
var c = q[0].numCols
|
||||
var p = params.call(r, c)
|
||||
r = r * 2
|
||||
c = c * 2
|
||||
var m = List.filled(r, null)
|
||||
for (i in 0...c) m[i] = List.filled(c, 0)
|
||||
for (k in 0..3) {
|
||||
for (i in p[k][0]) {
|
||||
for (j in p[k][1]) m[i][j] = q[k][i - p[k][2], j - p[k][3]]
|
||||
}
|
||||
}
|
||||
return Matrix.new(m)
|
||||
}
|
||||
|
||||
var strassen // recursive
|
||||
strassen = Fn.new { |a, b|
|
||||
if (!a.isSquare || !b.isSquare || !a.sameSize(b)) {
|
||||
Fiber.abort("Matrices must be square and of equal size.")
|
||||
}
|
||||
if (a.numRows == 0 || (a.numRows & (a.numRows - 1)) != 0) {
|
||||
Fiber.abort("Size of matrices must be a power of two.")
|
||||
}
|
||||
if (a.numRows == 1) return a * b
|
||||
var qa = toQuarters.call(a)
|
||||
var qb = toQuarters.call(b)
|
||||
var p1 = strassen.call(qa[1] - qa[3], qb[2] + qb[3])
|
||||
var p2 = strassen.call(qa[0] + qa[3], qb[0] + qb[3])
|
||||
var p3 = strassen.call(qa[0] - qa[2], qb[0] + qb[1])
|
||||
var p4 = strassen.call(qa[0] + qa[1], qb[3])
|
||||
var p5 = strassen.call(qa[0], qb[1] - qb[3])
|
||||
var p6 = strassen.call(qa[3], qb[2] - qb[0])
|
||||
var p7 = strassen.call(qa[2] + qa[3], qb[0])
|
||||
var q = List.filled(4, null)
|
||||
q[0] = p1 + p2 - p4 + p6
|
||||
q[1] = p4 + p5
|
||||
q[2] = p6 + p7
|
||||
q[3] = p2 - p3 + p5 - p7
|
||||
return fromQuarters.call(q)
|
||||
}
|
||||
|
||||
var a = Matrix.new([ [1,2], [3, 4] ])
|
||||
var b = Matrix.new([ [5,6], [7, 8] ])
|
||||
var c = Matrix.new([ [1, 1, 1, 1], [2, 4, 8, 16], [3, 9, 27, 81], [4, 16, 64, 256] ])
|
||||
var d = Matrix.new([ [4, -3, 4/3, -1/4], [-13/3, 19/4, -7/3, 11/24],
|
||||
[3/2, -2, 7/6, -1/4], [-1/6, 1/4, -1/6, 1/24] ])
|
||||
var e = Matrix.new([ [1, 2, 3, 4], [5, 6, 7, 8], [9,10,11,12], [13,14,15,16] ])
|
||||
var f = Matrix.new([ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1] ])
|
||||
System.print("Using 'normal' matrix multiplication:")
|
||||
System.print(" a * b = %(a * b)")
|
||||
System.print(" c * d = %((c * d).toString(6))")
|
||||
System.print(" e * f = %(e * f)")
|
||||
System.print("\nUsing 'Strassen' matrix multiplication:")
|
||||
System.print(" a * b = %(strassen.call(a, b))")
|
||||
System.print(" c * d = %(strassen.call(c, d).toString(6))")
|
||||
System.print(" e * f = %(strassen.call(e, f))")
|
||||
Loading…
Add table
Add a link
Reference in a new issue