1. Introduction
This post first introduces the Strassen algorithm of matrix multiplication based on divide-and-conquer strategy, and then gives several methods for solving recursion.
2. Strassen Algorithm for matrix multiplication
(1) Common matrix multiplication algorithm
The basic algorithm for matrix multiplication is calculated as follows:
If A= (AIJ) and b= (bij) are the square of the nxn (I,j = ...), then C = A. The element Cij in B is:
The Java implementation code is given below:
Public Static voidMain (string[] args) {int[] A =New int[][] {//{1, 0, 1, 2},//{1, 2, 0, 2},//{0, 2, 1, 0},//{0, 0, 1, 2},//};int[] B =New int[][] {//{1, 0, 1, 2},//{1, 2, 0, 2},//{0, 2, 1, 0},//{0, 0, 1, 2},//};p Rintmatrix (Squarematrixmutiply (A, b));}/** * Basic matrix multiplication (assuming that both matrices A and B are nxn matrices, and N is a power of 2) * @param a matrix A * @param b Matrix B * @return */Private Static int[] Squarematrixmutiply (int[] A,int[] b) {int[] C =New int[A.length] [A.length]; for(inti = 0; i < c.length; i++) { for(intj = 0; J < C.length; J + +) {C[i][j] = 0; for(intk = 0; K < C.length; k++) {C[i][j] + = a[i][k] * b[k][j];}}}returnC;}/** * Print Matrix * * @param Matrix * *Private Static voidPrintmatrix (int[] matrix) { for(int[] Is:matrix) { for(intI:is) {System.out.print (i + ")\ t");} System.out.println ();}}
Results:
(2) A simple divide-and-conquer algorithm
For simplicity, when the matrix C=a*b is computed using the divide-and- Divide (Conquer) method , the three matrices are assumed to be nxn matrices, and N is a power of 2. Divide and Conquer (Divide and Conquer) or the three steps mentioned in the previous article, the core of the algorithm is this formula:
Among them, AIJ,BIJ,CIJ is the sub-matrix of the N/2 * N/2 of the a,b,c matrix, namely:
It is worth noting that we do not have to create sub-arrays, which will waste θ (N2) of time to copy array elements; It is wise to directly follow the subscript.
is the pseudo-code of the original book (which says "(4.9)" is the three equations given):
The Java implementation code is given below:
Public Static voidMain (string[] args) {int[] A =New int[][] {//{1, 0, 1, 2},//{1, 2, 0, 2},//{0, 2, 1, 0},//{0, 0, 1, 2},//};int[] B =New int[][] {//{1, 0, 1, 2},//{1, 2, 0, 2},//{0, 2, 1, 0},//{0, 0, 1, 2},//};p Rintmatrix (Squarematrixmutiplybyrecursive (NewChildmatrix (A, 0, 0, a.length),NewChildmatrix (b, 0, 0, b.length), 0, 0, 0, 0));}/** * Print Matrix * * @param Matrix * *Private Static voidPrintmatrix (int[] matrix) { for(int[] Is:matrix) { for(intI:is) {System.out.print (i + ")\ t");} System.out.println ();}}/** * Matrix multiplication based on divide-and-conquer method * * @param A * @param b * @return * *Private Static int[] squarematrixmutiplybyrecursive (Childmatrix Matrixa, Childmatrix Matrixb,intLaststartrowa,intLaststartcolumna,intLASTSTARTROWB,intLASTSTARTCOLUMNB) {int[] C =New int[Matrixa.length] [Matrixa.length];if(Matrixa.length = = 1) {C[0][0] = Matrixa.getfromparentmatrix (Matrixa.startrow, Matrixa.startcolumn) *//Matrixb.getfromparentmatrix (Matrixb.startrow, Matrixb.startcolumn);returnC;}intChildlength = MATRIXA.LENGTH/2;//First step: DecompositionChildmatrix childMatrixA11 =NewChildmatrix (Matrixa.parentmatrix, Laststartrowa, Laststartcolumna, childlength); Childmatrix childMatrixA12 =NewChildmatrix (Matrixa.parentmatrix, Laststartrowa, Laststartcolumna + childlength, childlength); Childmatrix childMatrixA21 =NewChildmatrix (Matrixa.parentmatrix, Laststartrowa + childlength, Laststartcolumna, childlength); Childmatrix childMatrixA22 =NewChildmatrix (Matrixa.parentmatrix, Laststartrowa + childlength, Laststartcolumna + childlength, childLength); Childmatrix childMatrixB11 =NewChildmatrix (Matrixb.parentmatrix, LASTSTARTROWB, LASTSTARTCOLUMNB, childlength); Childmatrix childMatrixB12 =NewChildmatrix (Matrixb.parentmatrix, LASTSTARTROWB, LASTSTARTCOLUMNB + childlength, childlength); Childmatrix childMatrixB21 =NewChildmatrix (Matrixb.parentmatrix, Laststartrowb + childlength, LASTSTARTCOLUMNB, childlength); Childmatrix childMatrixB22 =NewChildmatrix (Matrixb.parentmatrix, Laststartrowb + childlength, LASTSTARTCOLUMNB + childlength, childLength);///Step two: Resolveint[] Temp1 = Squarematrixmutiplybyrecursive (childMatrixA11, childMatrixB11, 0, 0, 0, 0);int[] Temp2 = Squarematrixmutiplybyrecursive (childMatrixA12, childMatrixB21, 0, Childlength, childlength, 0);int[] C11 = Summatrix (Temp1, TEMP2);int[] Temp3 = Squarematrixmutiplybyrecursive (childMatrixA11, childMatrixB12, 0, 0, 0, childlength);int[] Temp4 = Squarematrixmutiplybyrecursive (childMatrixA12, childMatrixB22, 0, Childlength, Childlength, childlength);int[] C12 = Summatrix (Temp3, Temp4);int[] Temp5 = Squarematrixmutiplybyrecursive (childMatrixA21, childMatrixB11, childlength, 0, 0, 0);int[] temp6 = Squarematrixmutiplybyrecursive (childMatrixA22, childMatrixB21, Childlength, Childlength, childlength, 0);int[] C21 = Summatrix (TEMP5, TEMP6);int[] TEMP7 = Squarematrixmutiplybyrecursive (childMatrixA21, childMatrixB12, childlength, 0, 0, childlength);int[] Temp8 = Squarematrixmutiplybyrecursive (childMatrixA22, childMatrixB22, Childlength, Childlength, Childlength, Childlength);int[] C22 = Summatrix (TEMP7, TEMP8);//Step three: Merging for(inti = 0; i < c.length; i++) { for(intj = 0; J < C.length; J + +) {if(I < Childlength && J < Childlength) {C[i][j] = c11[i][j];}Else if(I < Childlength && J < C.length) {int[] Child = c12;c[i][j] = Child[i][j-childlength];}Else if(I < C.length && J < Childlength) {int[] Child = c21;c[i][j] = child[i-childlength][j];}Else{int[] Child = c22;c[i][j] = Child[i-childlength][j-childlength];}}returnC;}Private Static int[] Summatrix (int[] A,int[] b) {int[] C =New int[A.length] [B.length]; for(inti = 0; i < a.length; i++) { for(intj = 0; J < A.length; J + +) {C[i][j] + = a[i][j];c[i][j] + = B[i][j];}}returnC;}/** * Childmatrix represents a sub-matrix of a matrix * * @author D.K * */Static classChildmatrix {/** * Parent Matrix * /int[] Parentmatrix;/** * The starting line coordinates of the sub-matrix in the parent matrix * /intStartRow;/** * The starting column coordinates of the sub-matrix in the parent matrix * /intStartColumn;/** * Sub-matrix length * /intLength PublicChildmatrix (int[] Parentmatrix,intStartRow,intStartColumn,intLength) {Super(); This. Parentmatrix = Parentmatrix; This. StartRow = StartRow; This. StartColumn = StartColumn; This. length = length;}/** * Gets the row row of the parent matrix, colum column element * * @param row * @param colum * @return * * Public intGetfromparentmatrix (intRowintColum) {returnParentmatrix[row][colum];}}
The result is:
(3) Strassen algorithm
The core idea of the Strassen algorithm is to make the recursive tree slightly less lush, and it only carries 7 recursion (the above divide-and-conquer recursively 8 times). The Strassen algorithm is described as follows:
The ① decomposition Matrix A,b,c
Also do not create sub-arrays but just subscript calculations.
② creates a matrix S1,s2,s3...,s10 of 10 n/2xn/2, which is calculated as follows:
The ③ calculates 7 matrices of P1 recursively, P2 ... P3,P7, the calculation formula is as follows:
④ calculates the CIJ and calculates the formula as follows:
The implementation code is not given, similar to the above.
3. Algorithm Analysis
(1) Common matrix multiplication
For normal matrix multiplication, 3 nested loops, each of which executes N times, takes a time of θ (N3);
(2) Simple divide and conquer algorithm
① Basic Condition:T (1) =θ (1);
② recursion: after decomposition, the matrix size becomes the original 1/2. Recursion eight times, Time 8T (N/2), 4 matrix addition, the number of elements in each matrix is N2/4, time θ (N2), and the remainder is θ (1). Therefore, the total time is 8T (N/2) +θ (n2).
solvable, T (n) =θ (n3). It can be seen that the divide and conquer algorithm is not superior to ordinary matrix multiplication
(3) Strassen algorithm
The Strassen algorithm analysis is basically consistent with the above, except that only 7 recursion is performed, and an additional number of additions to the N/2XN/2 matrix are made, but only a few times. The Strassen algorithm takes:
solvable, T (n) =θ (N^LG7);
Divide and Conquer strategy (2)--Introduction to Algorithms (4)