Coppersmitha-Winograda algorytm mnożenia macierzy

0

Czy poniższy kod jest poprawny?
Na temat algorytmu Strassena jest bardzo dużo opracowań.
natomiast na temat CW ze względu, na to że nie praktyczny niewiele.

import numpy as np

def split(matrix):
    row, col=np.shape(matrix)
    row2, col2=row//2, col//2
    return matrix[:row2, :col2], matrix[:row2:, col2:], matrix[row2:, :col2], matrix[row2:, col2:]

def addmat(x,y):
    res=np.zeros((len(x),len(y)))
    for i in range(len(x)):
        for j in range(len(y[0])):
            res[i][j]= x[i][j]+y[i][j]
    return res
    
def submat(x,y):
    res=np.zeros((len(x),len(y)))
    for i in range(len(x)):
        for j in range(len(y[0])):
            res[i][j]= x[i][j]-y[i][j]
    return res 
    
def mulmat(x,y):
    res=np.zeros((len(x),len(y)))
    for i in range(len(x)):
        for j in range(len(y[0])):
            for k in range(len(y)):
                res[i][j]+= x[i][k]*y[k][j]
    return res    
    
    
def cw90(x,y):
    
    if len(x)==1:
        return x*y
    else:
    
        a11, a12, a21, a22 = split(x)
        b11, b12, b21, b22 = split(y)
        
        #s1=a21+a22
        s1=addmat(a21,a22)
        #s2= s1 - a11
        s2=submat(s1,a11)
        #s3=a11-a21
        s3=submat(a11,a21)
        #s4= a12 - s2
        s4=submat(a12,s2)
        
        
        #t1=b21-b11
        t1=submat(b21,b11)
        #t2=b22 -t1
        t2=submat(b22,t1)
        #t3=b22-b12
        t3=submat(b22,b12)
        #t4=t2-b21
        t4=submat(t2,b21)
        
        
        #m1=a11*b11
        m1=cw90(a11,b11)
        #m2=a12*b21
        m2=cw90(a12,b21)
        #m3=s4*b22
        m3=cw90(s4,b22)
        #m4=a22*t4
        m4=cw90(a22,t4)
        #m5=s1*t1
        m5=cw90(s1,t1)
        #m6=s2*t2
        m6=cw90(s2,t2)
        #m7=s3*t3
        m7=cw90(s3,t3)
        
        #u1=m1+m2
        u1=addmat(m1,m2)
        #u2=m1+m6
        u2=addmat(m1,m6)
        #u3=u2+m7
        u3=addmat(u2,m7)
        #u4=u2+m5
        u4=addmat(u2,m5)
        #u5=u4+m3
        u5=addmat(u4,m3)
        #u6=u3-m4
        u6=submat(u3,m4)
        #u7=u3+m5
        u7=addmat(u3,m5)
        
        #c11=u1
        c11=u1
        #c12=u5
        c12=u5
        #c21=u6
        c21=u6
        #c22=u7
        c22=u7
        res= np.hstack((np.vstack((c11,c12)), np.vstack((c21,c22))))
        return res
    

rows=4
m1=np.full((rows,rows),2.)
print(m1)
m2=np.full((rows,rows),3.)
print(m2)

res=cw90(m1,m2)
print(res)

2

Ale co, mamy poszukać Ci błędu? :(
Może po prostu napisz testy. Generuj losowe macierze, pomnóż cw, zapisz wynik, pomnóż te same macierze czymś co działa i porównaj.

1

jak wyżej, @nalik, poza tym:

Czy poniższy kod jest poprawny?

W jakim sensie, syntaktycznie poprawny pewnie jest, skoro się kompiluje.
Masz funkcję, O(n^3)), matmul, pewnie do testów, tylko ich nie widać:)
W przykrej fukcji, cw90 nie widzę inkryminowanego algorytmu, mógłbyś objaśnić?
EDIT: Rzeczywiście, jak się tej funkcji lepiej przyjrzeć to można się dopatrzyć tego algorytmu; ale wypadałoby jakoś to przeredagować.

0

@lion137:
Znalazłem jedną prezentację w necie na temat CW i zacząłem ja implementować.
Funkcja matmul była mi potrzebna tylko na początku. Wszystkie mnożenie przez nią wykonywałem.
Działać działa i daje poprawne wyniki ale nie wiem czy to nawet ten algorytm.

0

Podeślij tę prezentację, i cokolwiek co znalazłeś o tym algorytmie, i, najważniejsze, pokaż jak to testowałeś.

1 użytkowników online, w tym zalogowanych: 0, gości: 1