En lineara algebro, **algoritmo de Strassen** estas algoritmo por matrica multipliko, pli rapida ol la norma matrica multiplika algoritmo.

Algoritmo de Strassen estas utila en praktiko por grandaj matricoj.

La norma matrica multiplika algoritmo uzas senperan kalkulon laŭ difino de matrica multipliko

*cik = Σaijbjk*
havas komplikecon *O(N3)* kie *N* estas amplekso de la matrico

Algoritmo de Strassen havas komplikecon *O(N2,807)*.

Tamen ekzistas asimptote ankoraŭ pli rapida algoritmo, la plej rapida sciata algoritmo, algoritmo de Coppersmith-Winograd, kiu havas komplikecon *O(N2,376)*

Algoritmo de Strassen estas ĝeneraligo de algoritmo de Karatsuba por multipliko de nombroj al multipliko de matricoj.

Algoritmo
---------

Estu *A* kaj *B* du *N×N* kvadrataj matricoj, kie *N = 2n*. La matricoj povas esti super reelaj nombroj, kompleksaj nombroj aŭ iu ringo *R*. Bezonatas kalkuli la produton *C=AB*.

Se la matricoj *A*, *B* estas ne de amplekso *2n×2n* oni aldonu nulajn liniojn kaj kolumnojn ĝis ĉi tiu amplekso. Post multiplikado, la produto havos nulajn liniojn kaj kolumnojn kiujn eblos forigi.

Disdividu *A*, *B* kaj *C* en blokajn matricojn de egala amplekso

{\displaystyle A={\begin{bmatrix}A\_{1,1}&A\_{1,2}\\A\_{2,1}&A\_{2,2}\end{bmatrix}}}
{\displaystyle B={\begin{bmatrix}B\_{1,1}&B\_{1,2}\\B\_{2,1}&B\_{2,2}\end{bmatrix}}}
{\displaystyle C={\begin{bmatrix}C\_{1,1}&C\_{1,2}\\C\_{2,1}&C\_{2,2}\end{bmatrix}}}
kun ĉiu al *Ai, j*, *Bi, j*, *Ci, j* de amplekso *2n-1×2n-1*.

Tiam

*C1, 1 = A1, 1 B1, 1 + A1, 2 B2, 1* 
*C1, 2 = A1, 1 B1, 2 + A1, 2 B2, 2* 
*C2, 1 = A2, 1 B1, 1 + A2, 2 B2, 1* 
*C2, 2 = A2, 1 B1, 2 + A2, 2 B2, 2* 
Kun ĉi tiu formuloj oni ne malpligrandigas la kvanton de multiplikoj. Ankoraŭ bezonatas 8 multiplikoj por kalkuli la ĉiujn *Ci, j* matricojn, la sama kvanto de multiplikoj bezonatas per la norma matrica multipliko.

Sed estas la alia, malrekta maniero kalkuli *Ci, j*. Estu novaj matricoj

*P1 = (A1, 1 + A2, 2) (B1, 1 + B2, 2)*
*P2 = (A2, 1 + A2, 2) B1, 1*
*P3 = A1, 1 (B1, 2 - B2, 2)*
*P4 = A2, 2 (B2, 1 - B1, 1)*
*P5 = (A1, 1 + A1, 2) B2, 2*
*P6 = (A2, 1 - A1, 1) (B1, 1 + B1, 2)*
*P7 = (A1, 2 - A2, 2) (B2, 1 + B2, 2)*
kaj

*C1, 1 = P1 + P4 - P5 + P7*
*C1, 2 = P3 + P5*
*C2, 1 = P2 + P4*
*C2, 2 = P1 - P2 + P3 + P6*
La elekto de *Pk* estas tia ke estas eliminita unu matrica multipliko kaj la kvanto de multiplikoj estas malpligrandigita al 7 (po unu multipliko por ĉiu *Pk*).

Necesas ripeti ĉi tiun disdividan procezon *n* fojojn ĝis kiam la submatricoj estas *1×1* kaj do degeneras en nombrojn (erojn de la ringo *R*).

Praktikaj realigoj de algoritmo de Strassen reŝaltiĝas al norma maniero de matrica multipliko por sufiĉe malgrandaj submatricoj, por kiuj la norma maniero estas pli rapida. La amplekso ekde kiu algoritmo de Strassen estas pli rapida dependas de la specifa realigo kaj aparataro. Estas pritaksoj ke algoritmo de Strassen estas pli rapida por matricoj de amplekso *N* ekde valoro inter 32 kaj 128 por optimumigitaj realigoj, kaj 60000 aŭ pli multe por bazaj realigoj.

### Ekzemplo de realigo

Jen estas ekzemplo de fontokodo de la algoritmo en Fortran por *N×N* matricoj kie *N=k2m* kie *k≤64*.

Funkcio *MUL* estas multipliko per algoritmo de Strassen, funkcio *MUL2* estas multipliko per la norma algoritmo. *V* estas la amplekso de matricoj.

Komputado de *P1* ... *P7* povas esti paralela, kio povas pligrandigi rapidon je multprocezilaj komputiloj.

Ĉi tiu versio kopias la submatricojn *Ai, j*, *Bi, j*, kio ne estas bezonata; eblas fari pli kompetentan realigon, kiu uzas la submatricojn tie kie ili jam kuŝas en la memoro.

```
MODULE STRASSEN\_MUL

CONTAINS
RECURSIVE SUBROUTINE MUL(A, B, V, C)

INTEGER, INTENT(IN) :: V
DOUBLE PRECISION, INTENT(IN) :: A( : , : ), B( : , : )
INTEGER :: H ! H = V/2
DOUBLE PRECISION, INTENT(OUT) :: C(V, V)
DOUBLE PRECISION, DIMENSION(:,:), ALLOCATABLE :: P1, P2, P3, P4, P5, P6, P7
DOUBLE PRECISION, DIMENSION(:,:), ALLOCATABLE :: A11, A12, A21, A22, B11, B12, B21, B22

IF (V <= 64) THEN
CALL MUL2 (A, B, V, C)
RETURN
ENDIF

H = V/2

ALLOCATE (P1(H,H), P2(H,H), P3(H,H), P4(H,H), P5(H,H), P6(H,H), P7(H,H))
ALLOCATE (A11(H,H), A12(H,H), A21(H,H), A22(H,H), B11(H,H), B12(H,H), B21(H,H), B22(H,H))

A11 (1:H, 1:H) = A (1:H, 1:H)
A12 (1:H, 1:H) = A (1:H, H+1:V)
A21 (1:H, 1:H) = A (H+1:V, 1:H)
A22 (1:H, 1:H) = A (H+1:V, H+1:V)

B11 (1:H, 1:H) = B (1:H, 1:H)
B12 (1:H, 1:H) = B (1:H, H+1:V)
B21 (1:H, 1:H) = B (H+1:V, 1:H)
B22 (1:H, 1:H) = B (H+1:V, H+1:V)

!$OMP PARALLEL
CALL MUL(A11 + A22, B11 + B22, H, P1) ! P1 = (A11 + A22) \* (B11 + B22)
CALL MUL(A21 + A22, B11, H, P2) ! ...
CALL MUL(A11, B12 - B22, H, P3)
CALL MUL(A22, B21 - B11, H, P4)
CALL MUL(A11 + A12, B22, H, P5)
CALL MUL(A21 - A11, B11 + B12, H, P6)
CALL MUL(A12 - A22, B21 + B22, H, P7)
!$OMP END PARALLEL

DEALLOCATE (B11, B12, B21, B22)
DEALLOCATE (A11, A12, A21, A22)

C (1:H, 1:H) = P1 + P4 + P7 - P5
C (1:H, H+1:V) = P3 + P5
C (H+1:V, 1:H) = P2 + P4
C (H+1:V, H+1:V) = P1 - P2 + P3 + P6

DEALLOCATE (P1, P2, P3, P4, P5, P6, P7)

RETURN
END SUBROUTINE MUL

SUBROUTINE MUL2 (A, B, V, X)
IMPLICIT NONE
INTEGER, INTENT(IN) :: V
DOUBLE PRECISION, INTENT(IN) :: A( : , : ), B( : , : )
DOUBLE PRECISION, INTENT(OUT), DIMENSION (:,:) :: X
INTEGER :: I, J, K
DO I = 1, V
DO J = 1, V
X (I, J) = 0
DO K = 1, V
X (I, J) = X (I, J) + A (I, K) \* B (K, J)
ENDDO
ENDDO
ENDDO
RETURN
END SUBROUTINE MUL2

END MODULE STRASSEN\_MUL

```

Algoritmo de Bodrato-Strassen
-----------------------------

Algoritmo de Bodrato-Strassen estas optimumigita simetria versio de algoritmo de Strassen. Ĝi bezonas 7 mutiplikojn kaj 15 adiciojn (anstataŭ 18 adicioj por algoritmo de Strassen) je ĉiu disdivido je submatricoj.

La matricoj *A*, *B*, *C* estas disdividataj je blokoj same kiel en algoritmo de Strassen.

Tiam oni kalkulu submatricojn *S1* ... *S4*, *T1* ... *T4*, *P1* ... *P7*, *U1*, *U2* kiel:

*S1 = A1, 2 + A2, 2*
*T1 = B1, 2 + B2, 2*
*S2 = A2, 2 - A2, 1*
*T2 = B2, 2 - B2, 1*
*S3 = S2 + A1, 2*
*T3 = T2 + B1, 2*
*S4 = S3 - A1, 1*
*T4 = T3 - B1, 1*
*P1 = S1 T1*
*P2 = S2 T2*
*P3 = S3 T3*
*P4 = A1, 1 B1, 1*
*P5 = A1, 2 B2, 1*
*P6 = S4 B1, 2*
*P7 = A2, 1 T4*
*U1 = P3 + P5*
*U2 = P1 - U1*
kaj

*C1, 1 = P4 + P5*
*C1, 2 = U1 - P2 - P6*
*C2, 1 = U2 - P7*
*C2, 2 = U2 + P2*
Por *2×2* nekomutaj matricoj, ne nur tiu versio atingas la plej malaltan kvanton da linearaj operacioj, sed ĝi ankaŭ bezonas eĉ malpli operaciojn por kvadratigi matricon: en tiu kaso *Si = Ti*; plue *P1, P2* kaj *P3* estas ne multiplikoj, sed kvadratigoj.

Tempodaŭro de ruligo
--------------------

La norma matrica multipliko bezonas proksimume *2N3* aritmetikajn operaciojn (adicioj kaj multiplikoj), do la asimptota komplikeco estas *O(N3)*.

La kvanto de adicioj kaj multiplikoj postulata per la algoritmo de Strassen povas esti kalkulita kiel sekvas. Estu *f(n)* la kvanto de operacioj por *2n×2n* matrico. Tiam konsiderante rikuran aplikon de la algoritmo de Strassen, *f(n) = 7f(n-1) + a4n*, por iu konstanto *a* kiu dependas de la kvanto de adicioj plenumataj je ĉiu apliko de la algoritmo. De ĉi tie *f(n) = (7 + o(1))n*. Tiel la asimptota komplikeco de multipliko de matricoj de amplekso *N = 2n* per la algoritmo de Strassen estas

{\displaystyle O((7+o(1))^{n})=O(N^{\log \_{2}7+o(1)})\approx O(N^{2,807})}
La malpligrandiĝo de la kvanto de aritmetikaj operacioj tamen rezultas je la prezo de ia malpligrandiĝo de la cifereca stabileco.

Historio
--------

La algoritmo de Strassen estas nomita post Volker Strassen, kiu publikigis la algoritmon en 1969. Kvankam la algoritmo estas nur malmulte pli rapida ol la norma algoritmo por matrica multipliko, ĝi estis la unua kiu montris ke la norma maniero estas ne optimala. Lia papero startis la serĉon por eĉ pli rapidaj algoritmoj kiel la pli komplika algoritmo de Coppersmith-Winograd.

Vidu ankaŭ
----------

* Z-ordo (kurbo)
* Z-orda matrica prezento
* Algoritmo de Coppersmith-Winograd

Eksteraj ligiloj
----------------

* Kakaradov, Boyko  (2004). Ultra-fast Matrix Multiplication: An Empirical Analysis of Highly Optimized Vector Algorithms - Ultra-rapida matrica multipliko: empiria analizo de alte optimumigitaj vektoraj algoritmoj. Stanford Undergraduate Research Journal **3** 33-36.
* Eric W. Weisstein, *Formuloj de Strassen* en MathWorld. (ankaŭ inkluzivas formulojn por rapida matrica inversigo)
* Tyler J. Earnest, *Algoritmo de Strassen sur la Ĉela Larĝbenda Motoro Arkivigite je 2010-06-12 per la retarkivo Wayback Machine*
* Analizo de la algoritmo de Strassen Arkivigite je 2004-11-20 per la retarkivo Wayback Machine de Thomas Visnius
* Gérard Sookahet, Algoritmo de V. Strassen por la rapida multipliko de matricoj Arkivigite je 2007-12-19 per la retarkivo Wayback Machine