strassen矩阵乘法各种情况详细解答

合集下载

三阶strassen矩阵乘法python

三阶strassen矩阵乘法python

一、介绍三阶Strassen矩阵乘法是一种优化的矩阵乘法算法,它可以在一定程度上减少乘法的次数,提高矩阵相乘的效率。

在本文中,我们将介绍三阶Strassen矩阵乘法的原理和实现方法,并使用Python语言进行编写和演示。

二、原理传统的矩阵乘法需要进行n^3次乘法操作,其中n为矩阵的维度。

而Strassen矩阵乘法可以将这一次数减少到n^(log2 7) ≈ n^2.81 次。

其基本原理是将两个矩阵分块,并通过一定的运算得到所需的乘积。

具体而言,设A、B为两个3阶矩阵:A = [[a1, a2, a3],[a4, a5, a6],[a7, a8, a9]]B = [[b1, b2, b3],[b4, b5, b6],[b7, b8, b9]]可以将矩阵A、B分块为四个2阶子矩阵:A11 = [[a1, a2],[a4, a5]],A12 = [[a3],[a6]],A21 = [[a7, a8]],A22 = [[a9]]B11 = [[b1, b2],[b4, b5]],B12 = [[b3],[b6]],B21 = [[b7, b8]],B22 = [[b9]]则矩阵乘积C可以表示为:C = [[c1, c2, c3],[c4, c5, c6],[c7, c8, c9]]其中,c1 = p1 + p4 - p5 + p7,c2 = p3 + p5,c3 = p2 + p4,c4 = p1 + p3 - p2 + p6,c5 = p1 + p4,c6 = p2 - p1 + p3 + p6,c7 = p3 - p5 + p7,c8 = p4 + p5,c9 = p1 - p3 + p2 + p7这里p1至p7的计算分别为:p1 = a1 * (b2 - b4),p2 = (a1 + a2) * b4,p3 = (a3 + a2) * b1,p4 = a2 * (b3 - b1),p5 = (a1 + a3) * b4,p6 = (a4 + a5) * b6,p7 = (a6 - a4) * (b5 + b6)三、Python实现接下来,我们将使用Python语言来实现三阶Strassen矩阵乘法。

strassen算法实现矩阵相乘,当输入为偶数,奇数,任意数的实现

strassen算法实现矩阵相乘,当输入为偶数,奇数,任意数的实现

strassen算法实现矩阵相乘,当输⼊为偶数,奇数,任意数的实现1.使⽤随机数⽣成两个矩阵,并实现输出⽅法。

public void makeMatrix(int[][] matrixA, int[][] matrixB, int length){ //⽣成矩阵Random random=new Random();for(int i=0;i<length;i++){for (int j=0;j<length;j++){matrixA[i][j]=random.nextInt(5);matrixB[i][j]=random.nextInt(5);}}}public void printMatrix(int[][] matrixA,int length){ //输出for(int i=0;i<length;i++){for (int j=0;j<length;j++){System.out.print(matrixA[i][j]+" ");if((j+1)%length==0)System.out.println();}}}2.使⽤Strassen算法需要涉及到矩阵的加减。

所以先准备好⽅法。

public void add(int[][] matrixA,int[][] matrixB,int[][] matrixC,int length){for(int i=0;i<length;i++) {for (int j = 0; j < length; j++) {matrixC[i][j]= matrixA[i][j]+ matrixB[i][j];}}}public void jian(int[][] matrixA,int[][] matrixB,int[][] matrixC,int length){for(int i=0;i<length;i++) {for (int j = 0; j < length; j++) {matrixC[i][j]= matrixA[i][j] - matrixB[i][j];}}}public void cheng(int[][] matrixA,int[][] matrixB,int[][] matrixC,int length){for(int i=0;i<length;i++) {for (int j = 0; j < length; j++) {matrixC[i][j]=0;for(int k=0;k<length;k++){matrixC[i][j] = matrixC[i][j]+ matrixA[i][k] * matrixB[k][j];}}}}3.当矩阵的阶数为 2的k次⽅//阶数为 2 的 K 次⽅的时候 Strassen算法public void strassen(int[][] matrixA,int[][] matrixB,int[][] matrixC,int N){int newsize=N/2;if(N==2){cheng(matrixA,matrixB,matrixC,N);return;}int[][] A11=new int[newsize][newsize];int[][] A12=new int[newsize][newsize];int[][] A21=new int[newsize][newsize];int[][] A22=new int[newsize][newsize];int[][] B11=new int[newsize][newsize];int[][] B12=new int[newsize][newsize];int[][] B21=new int[newsize][newsize];int[][] B22=new int[newsize][newsize];int[][] C11=new int[newsize][newsize];int[][] C12=new int[newsize][newsize];int[][] C21=new int[newsize][newsize];int[][] C22=new int[newsize][newsize];int[][] M1=new int[newsize][newsize];int[][] M2=new int[newsize][newsize];int[][] M3=new int[newsize][newsize];int[][] M4=new int[newsize][newsize];int[][] M5=new int[newsize][newsize];int[][] M6=new int[newsize][newsize];int[][] M7=new int[newsize][newsize];int[][] Aresult=new int[newsize][newsize];int[][] Bresult=new int[newsize][newsize];//分别给 A11 A12 A21 A22赋值for(int i=0;i<N/2;i++){for(int j=0;j<N/2;j++){A11[i][j]=matrixA[i][j];A12[i][j]=matrixA[i][j+N/2];A21[i][j]=matrixA[i+N/2][j];A22[i][j]=matrixA[i+N/2][j+N/2];B11[i][j]=matrixB[i][j];B12[i][j]=matrixB[i][j+N/2];B21[i][j]=matrixB[i+N/2][j];B22[i][j]=matrixB[i+N/2][j+N/2];}}//计算M1 到M7add(A11,A22,Aresult,newsize);add(B11,B22,Bresult,newsize);strassen(Aresult,Bresult,M1,newsize);//M2add(A21,A22,Aresult,newsize);strassen(Aresult,B11,M2,newsize);//M3jian(B12,B22,Bresult,newsize);strassen(A11,Bresult,M3,newsize);//M4jian(B21,B11,Bresult,newsize);strassen(A22,Bresult,M4,newsize);//M5add(A11,A12,Aresult,newsize);strassen(Aresult,B22,M5,newsize);//M6jian(A21,A11,Aresult,newsize);add(B11,B12,Bresult,newsize);strassen(Aresult,Bresult,M6,newsize);//M7jian(A12,A22,Aresult,newsize);add(B21,B22,Bresult,newsize);strassen(Aresult,Bresult,M7,newsize);//C11add(M1,M4,Aresult,newsize);jian(M5,M7,Bresult,newsize);jian(Aresult,Bresult,C11,newsize);//C12add(M3,M5,C12,newsize);//C21add(M2,M4,C21,newsize);//C22add(M1,M3,Aresult,newsize);jian(M2,M6,Bresult,newsize);jian(Aresult,Bresult,C22,newsize);//把C的值填充for(int i=0;i<N/2;i++){for(int j=0;j<N/2;j++){matrixC[i][j]=C11[i][j];matrixC[i][j+N/2]=C12[i][j];matrixC[i+N/2][j]=C21[i][j];matrixC[i+N/2][j+N/2]=C22[i][j];}}}4.当阶数为偶数的时候假设阶数为 n ,所以 n=m*2^k 。

strassen算法-现实2次幂,偶数奇数

strassen算法-现实2次幂,偶数奇数
按照分治的思想可以看出要想减少乘法运算次数关键在于计算2个2阶方阵的乘积时能否用少于8次的乘法运算
Strassen算法
姓名: 王军袖 学号: 31609059
1
目录
1
算法思想
2
3
算法代码
运行结果
2
算法思想
分治算法
其核心思想是将大的问题分解成若干小的子问题进行 处理,从而使复杂的问题变得简单。表现在算法中就 是递归算法。
m1 m2 m3 m4 m5 m6 m7 = = = = = = = (a11 + a22) * (b11 + b22); (a21 + a22) * b11; a11 * (b12 - b22); a22 * (b21 - b11); (a11 + a12) * b22; (a21 - a11) * (b11 + b12); (a12 - a22) * (b21 + b22); 再做若干次加、减法: c11 = m1 + m4 - m5 + m7 c12 = m3 + m5 c21 = m2 + m4 c22 = m1 +m3 -m2 + m6
16
Matrix **cr=new Matrix*[n];//初始化cr,储存ar*br结果 //阶为偶数矩阵想乘 for ( i=0;i<n;i++){ Matrix MutiEven(Matrix A,Matrix B){ cr[i]=new Matrix[n]; int n=A.n,m=1; for ( j=0;j<n;j++) int i,j; cr[i][j]=Matrix(m); //将矩阵阶拆分成m*n,n为奇数 } m为2的幂次 for( i=0;i<n;i++)//用传统方法将ar和br相乘,储存在cr中 while(!(n&1)){ for( j=0;j<n;j++) n>>=1; for(int k=0;k<n;k++) m<<=1; cr[i][j]=Plus(cr[i][j],Muti2n(ar[i][k],br[k][j])); Matrix C(m*n);//声明C } for( i=0;i<n;i++)//将cr合并成一个矩阵C //将A拆分为n^2个m阶矩阵,在ar中储存。 for( j=0;j<n;j++) Matrix **ar=new Matrix*[n]; for(int x=0;x<m;x++) for ( i=0;i<n;i++){ for(int y=0;y<m;y++) ar[i]=new Matrix[n]; for ( j=0;j<n;j++) C.m[i*m+x][j*m+y]=cr[i][j].m[x][y]; ar[i][j]=Split(A,i*m,j*m,m); return C;} } Matrix **br=new Matrix*[n];//同A for (i=0;i<n;i++){ br[i]=new Matrix[n]; for ( j=0;j<n;j++) 17 br[i][j]=Split(B,i*m,j*m,m);}

4-2.矩阵乘法的Strassen算法详解

4-2.矩阵乘法的Strassen算法详解

4-2.矩阵乘法的Strassen 算法详解题⽬描述请编程实现矩阵乘法,并考虑当矩阵规模较⼤时的优化⽅法。

思路分析根据wikipedia 上的介绍:两个矩阵的乘法仅当第⼀个矩阵B 的列数和另⼀个矩阵A 的⾏数相等时才能定义。

如A 是m×n 矩阵和B 是n×p 矩阵,它们的乘积AB 是⼀个m×p 矩阵,它的⼀个元素其中 1 ≤ i ≤ m,1 ≤ j ≤ p 。

值得⼀提的是,矩阵乘法满⾜结合律和分配率,但并不满⾜交换律,如下图所⽰的这个例⼦,两个矩阵交换相乘后,结果变了:下⾯咱们来具体解决这个矩阵相乘的问题。

解法⼀、暴⼒解法其实,通过前⾯的分析,我们已经很明显的看出,两个具有相同维数的矩阵相乘,其复杂度为O (n^3),参考代码如下:解法⼆、Strassen 算法在解法⼀中,我们⽤了3个for 循环搞定矩阵乘法,但当两个矩阵的维度变得很⼤时,O (n^3)的时间复杂度将会变得很⼤,于是,我们需要找到⼀种更优的解法。

⼀般说来,当数据量⼀⼤时,我们往往会把⼤的数据分割成⼩的数据,各个分别处理。

遵此思路,如果丢给我们⼀个很⼤的两个矩阵呢,是否可以考虑分治的⽅法循序渐进处理各个⼩矩阵的相乘,因为我们知道⼀个矩阵是可以分成更多⼩的矩阵的。

如下图,当给定⼀个两个⼆维矩阵A B 时:这两个矩阵A B 相乘时,我们发现在相乘的过程中,有8次乘法运算,4次加法运算:矩阵乘法的复杂度主要就是体现在相乘上,⽽多⼀两次的加法并不会让复杂度上升太多。

故此,我们思考,是否可以让矩阵乘法的运算过程中乘法的运算次数减少,从⽽达到降低矩阵乘法的复杂度呢?答案是肯定的。

1969年,德国的⼀位数学家Strassen 证明O (N^3)的解法并不是矩阵乘法的最优算法,他做了⼀系列⼯作使得最终的时间复杂度降低到了O(n^2.80)。

他是怎么做到的呢?还是⽤上⽂A B 两个矩阵相乘的例⼦,他定义了7个变量:如此,Strassen算法的流程如下:;表⾯上看,Strassen 算法仅仅⽐通⽤矩阵相乘算法好⼀点,因为通⽤矩阵相乘算法时间复杂度是,⽽Strassen 算法复杂度只是。

大整数乘法和strassen矩阵乘法

大整数乘法和strassen矩阵乘法

大整数乘法和strassen矩阵乘法大整数乘法和Strassen矩阵乘法是计算机科学中两个非常重要的算法。

在我们的日常生活中,我们经常需要比较大的数字,例如,考虑到我们的身份证号码或者信用卡号码中的位数就很大。

对于这些大数字的计算,实现乘法运算的标准方法导致了效率低下。

这就要依靠大整数乘法的算法来完成。

同样的,矩阵乘法是人们常用的数据分析和机器学习等领域的基础算法之一,Strassen矩阵乘法则是一种可以在更短时间内完成的矩阵乘法算法。

在接下来的文档中,我将详细讲解大整数乘法和Strassen矩阵乘法。

一、大整数乘法大整数乘法是指对于两个比较大的数字,我们如何快速且准确的计算它们的乘积。

在介绍大整数乘法的算法之前,先考虑乘法的基本方法。

在日常乘法中,乘法运算是通过对乘数和被乘数的每一位进行相乘并将结果相加而得到的。

例如,计算96 ×57,我们将乘数96 和被乘数57 的每一位相乘,去得到:``` 96 × 57 ------- 672 (6 x 7) 480 (9 x 5) <<1> +57600 (9 x 5 << 2> ) ------- 5472 ```我们在这个过程中需要进行至Less 2次的延时计算,6次的加法,这在数字比较小时的时候是可行的。

但是,如果数字的位数变得更大,传统的乘法算法就会非常不切实际,执行效率非常慢。

在大整数乘法中,我们需要考虑实现优化的算法以处理大量位数的数字,其中最流行和普遍使用的算法有以下两种:1.传统的分治算法2.卡拉茨巴乘法1.传统的分治算法传统的分治算法涉及将大的数字分解为更小的数字部分进行乘法运算,并且在计算此过程之间能够快速地进行组合。

该算法需要依靠递归算法的思想,在整个运算过程中采用分治策略。

如果给定两个长度为n的数字,我们可以将这些数字分成两个较小,长度为 n/2 的数字,然后将它们相乘。

在递归调用中,相同的方法会被重复递归调用。

用Strassen算法实现矩阵乘法

用Strassen算法实现矩阵乘法

用Strassen算法实现矩阵乘法#coding=utf-8'''第10题:用Strassen的思想实现两个n×n矩阵的乘法'''import mathfrom numpy import *#check函数用来检查num是否是2的整数次幂def check(num):i = 1;while (True):if (i > num):return Falseif (i == num):return Truei = i * 2#Multiply函数即为实现方法def Matrix_Multiply(A,B):#由于本题只考虑两个n×n矩阵的乘法,且n为2的整数次幂的情况,故做一些判断去掉不合法的输入if A.shape!=B.shape:print '本题只考虑两个n×n矩阵的乘法,且n为2的整数次幂的情况'return Noneif A.shape[0]!=A.shape[1]:print '本题只考虑两个n×n矩阵的乘法,且n为2的整数次幂的情况'return Noneif check(A.shape[0])==False:print '本题只考虑两个n×n矩阵的乘法,且n为2的整数次幂的情况'return Nonen = A.shape[0]result = zeros([n,n])if(n == 2):#最基本的情况A11=A[0,0]A12=A[0,1]A21=A[1,0]A22=A[1,1]B11=B[0,0]B12=B[0,1]B21=B[1,0]B22=B[1,1]P1 = A11*(B12-B22)P2 = (A11+A12)*B22P3 = (A21+A22)*B11P4 = A22*(B21-B11)P5 = (A11+A22)*(B11+B22)P6 = (A12-A22)*(B21+B22)P7 = (A11-A21)*(B11+B12)else:#输入复杂的情况就采取divide-and-conquer策略A11=A[:n/2,:n/2]A12=A[:n/2,n/2:]A21=A[n/2:,:n/2]A22=A[n/2:,n/2:]B11=B[:n/2,:n/2]B12=B[:n/2,n/2:]B21=B[n/2:,:n/2]B22=B[n/2:,n/2:]#combineP1 = Matrix_Multiply(A11,B12-B22)P2 = Matrix_Multiply(A11+A12,B22)P3 = Matrix_Multiply(A21+A22,B11)P4 = Matrix_Multiply(A22,B21-B11)P5 = Matrix_Multiply(A11+A22,B11+B22)P6 = Matrix_Multiply(A12-A22,B21+B22)P7 = Matrix_Multiply(A11-A21,B11+B12)result[:n/2,:n/2] = P4 + P5 + P6 - P2 #C11result[:n/2,n/2:] = P1 + P2 #C12result[n/2:,:n/2] = P3 + P4 #C21result[n/2:,n/2:] = P1 + P5 - P3 - P7 #C22return result'''demo'''print '矩阵A='a = array([[1.1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]) print aprint '计算A×A'print ''result = Matrix_Multiply(a,a)print '本题所实现的方法结果是:' print resultprint '正确结果应为:'print dot(a,a)。

实验二Strassen矩阵乘法

实验二Strassen矩阵乘法

实验2 Strassen矩阵乘法一、 实验目的1.理解Strassen矩阵乘法的分治思想Strassen矩阵乘法的分治法设计模式是:半分+混合2.改进Strassen矩阵乘法对内存的需求若按Strassen矩阵乘法的直接表述实现,则空间复杂度将是O(3n2),本实验将试图改进这个方面。

3.Strassen矩阵乘法的性能问题改进Strassen矩阵乘法的内存需求,并不一定能改进Strassen矩阵乘法的效率,本实验将试图测试一些较大规模(n>=1024)的n阶方阵的Strassen矩阵乘,探讨其效率问题。

二、 实验环境C/C++编程环境或任何编程语言环境三、 实验内容1. Strassen矩阵乘法描述尽管Strassen矩阵乘法的实用价值在当今的多核计算环境下可能不是那么显著,但其理论价值仍值得我们研究。

Strassen矩阵乘法体现了一类重要的分治算法设计模式,即半分+混合,同样具有这种算法设计模式的是FFT(Fast Fourier Transform)-“由于FFT这个卓越算法在实践上的重要意义,有些人把它看作是有史以来人们发明的最重要的算法之一。

”[1]Strassen 矩阵乘法的基本思想,可由下述矩阵乘法概括:输入:两个n=2k 维方阵A 和B (若A 和B 的维度不是2k ,则通过增加元素为0的行和列,以使A 和B 均为2k 维的方阵)输出:n 维方阵C(1)1+41+443-11+24134.12-43+4113.123-11+224.3424.1314.11.2412.4-4344+=A B =A B =A B =A B =A B M =A B M =A M M B M M M(2)为方便表示,这里采用与书本不同的下标表示法,如对于1个n/2维矩阵14.14M ,下标14.14表示其由两个矩阵A 1+4和B 1+4乘积而成,A 1+4表示A1+A4,同理B 1+4表示B1+B4,同理12.4M 表示A1+2与B4的乘积。

Strassen矩阵乘法

Strassen矩阵乘法

A11 C A 21
A12 A 22
B 11 B 21
B 12 B 22
• M1 = A11(B12 - B12) M2 = (A11 + A12)B22 M3 = (A21 + A22)B11 M4 = A22(B21 - B11) M5 = (A11 + A22)(B11 + B22) M6 = (A12 - A22)(B21 + B22) M7 = (A11 - A21)(B11 + B12) 完成了7次乘法,再做如下加法: C11 = M5 + M4 - M2 + M6 C12 = M1 + M2 C21 = M3 + M4 C22 = M5 + M1 - M3 - M7
• 全部计算使用了7次乘法和18次加减法, 计算时间降低到O(nE2.81)。计算复杂性得 到较大改进。 • STRASSEN矩阵乘法算法分析如下
• 1.先用普通矩阵乘法算出结果 • 2.递归调用strassen (1)void MATRIX_ADD(int n,int X[][N],int Y[][N],int Z[][N]) (2)void MATRIX_SUB(int n,int X[][N],int Y[][N],int Z[][N]) (3)void MATRIX_MULTIPLY(int A[][N],int B[][N],int C[][N]) (4)void STRASSEN(int n,int A[][N],int B[][N],int C[][N])
• Strassenபைடு நூலகம்阵乘法的不足 1
Strassen矩阵乘法
李辉 31209017

使用递归与分治法求解3.strassen矩阵乘法

使用递归与分治法求解3.strassen矩阵乘法

一、概述1.介绍矩阵乘法的概念和意义2.引出递归与分治法在矩阵乘法中的应用二、传统矩阵乘法算法1.介绍传统的矩阵乘法算法原理2.分析传统算法的时间复杂度和空间复杂度3.讨论传统算法在大规模矩阵计算中的局限性三、Strassen矩阵乘法算法原理1.介绍Strassen算法的基本思想和原理2.引出递归与分治法在Strassen算法中的运用3.分析Strassen算法的时间复杂度和空间复杂度四、递归与分治法在Strassen算法中的运用1.详细解释递归与分治法在Strassen算法中的具体应用过程2.分析递归与分治法对算法性能的影响3.讨论递归与分治法在其他算法中的推广应用五、实例分析1.通过具体实例演示Strassen算法和传统算法的计算过程2.对比分析两种算法的计算效率和精度3.总结实例分析结果,展示递归与分治法在Strassen算法中的优势六、改进和优化1.讨论现有Strassen算法的局限性和不足2.提出改进和优化的方案,探讨递归与分治法在算法优化中的作用3.展望递归与分治法在矩阵计算领域的未来发展方向七、结论1.总结文中讨论的内容,强调递归与分治法在Strassen算法中的重要性和价值2.展望递归与分治法在矩阵计算领域的广阔应用前景3.对读者提出建议,鼓励更多的研究者投身于这一领域的研究和探索。

六、改进和优化1. Strassen算法的局限性和不足尽管Strassen算法在理论上具有较低的时间复杂度,但实际应用中也存在一些局限性和不足。

Strassen算法中涉及到的矩阵分块操作会引入额外的运算开销和存储开销,使得在小规模矩阵计算中,并不能体现出明显的优势。

Strassen算法要求矩阵的维度必须为2的幂次方,而实际场景中的矩阵往往难以满足这一条件,限制了算法的适用范围。

另外,由于Strassen算法引入了额外的递归调用,对于小规模矩阵,递归调用会使得算法的性能反而不如传统的矩阵乘法算法。

2. 改进和优化的方案针对Strassen算法的局限性和不足,可以考虑一些改进和优化的方案。

矩阵连乘和strassen矩阵乘法

矩阵连乘和strassen矩阵乘法

矩阵连乘和strassen矩阵乘法矩阵连乘问题和 Strassen 矩阵乘法是计算机科学中的两个重要问题。

矩阵常常被用来表示线性算法问题,而矩阵的乘法则是表示两个矩阵之间运算的一种方法。

本文将对这两个问题分别进行介绍,以便更深入地了解矩阵的应用和计算方法。

矩阵连乘问题矩阵连乘问题是指给定一组矩阵,求其乘积的最小计算次数,并构造出相应的计算方法。

在算法中,我们通常采用递归的思想来解决这个问题。

递归过程中,我们根据矩阵的大小将矩阵划分成更小的子矩阵,然后再对这些子矩阵进行计算。

设矩阵连乘的矩阵序列为 A1, A2, A3, ..., An,其中矩阵 Ai 的行数和列数分别为 pi - 1 和 pi。

那么,计算这个矩阵序列的最小计算次数可以表示为递推式:m[i,j] = min{m[i,k] + m[k+1,j] + pi-1 * pk * pj} (i <= k < j)这个式子的意思是将矩阵序列Ai, Ai+1,...,Aj-1, Aj划分为两个子序列Ai, Ai+1,...,Ak和Ak+1,...,Aj,然后在这两个子序列中分别计算矩阵乘积所需的最小计算次数,其中pi-1 * pk * pj表示计算Ai到Aj乘积时需要的乘法次数。

由此,我们可以得出矩阵连乘的递归算法:Matrix Chain Multiply(A, p, i, j)if i == jreturn A[i]elsek = iM = Matrix Chain Multiply(A, p, i, k)N = Matrix Chain Multiply(A, p, k+1, j)return M * N其中,A是矩阵序列,p是矩阵的行列数,i和j表示矩阵序列的起止下标。

在递归过程中,我们用k将矩阵序列划分为两个部分,并分别计算左边和右边的矩阵乘积。

最后将两个部分的计算结果相乘即可。

这种算法的时间复杂度为O(n^3),在处理大规模的矩阵乘积时效率较低。

矩阵乘法之 strassen算法

矩阵乘法之 strassen算法

矩阵乘法之strassen 算法一般情况下矩阵乘法需要三个for循环,时间复杂度为O(n^3),现在我们将矩阵分块如图:( 来自MIT算法导论)一般算法需要八次乘法r = a * e + b * g ;s = a * f + b * h ;t = c * e + d * g;u = c * f + d * h;strassen将其变成7次乘法,因为大家都知道乘法比加减法消耗更多,所有时间复杂更高!strassen的处理是:令:p1 = a * ( f - h )p2 = ( a + b ) * hp3 = ( c +d ) * ep4 = d * ( g - e )p5 = ( a + d ) * ( e + h )p6 = ( b - d ) * ( g + h )p7 = ( a - c ) * ( e + f )那么我们可以知道:r = p5 + p4 + p6 - p2s = p1 + p2t = p3 + p4u = p5 + p1 - p3 - p7我们可以看到上面只有7次乘法和多次加减法,最终达到降低复杂度为O( n^lg7 ) ~= O( n^2.81 );代码实现如下:[cpp] view plaincopyprint?// strassen 算法:将矩阵相乘的复杂度降到O(n^lg7) ~= O(n^2.81)// 原理是将8次乘法减少到7次的处理// 现在理论上的最好的算法是O(n^2,367),仅仅是理论上的而已////// 下面的代码仅仅是简单的实例而已,不必较真哦,呵呵~// 下面的空间可以优化的,此处就不麻烦了~#include <stdio.h>#define N 10//matrix + matrixvoid plus( int t[N/2][N/2], int r[N/2][N/2], int s[N/2][N/2] ) {int i, j;for( i = 0; i < N / 2; i++ ){for( j = 0; j < N / 2; j++ ){t[i][j] = r[i][j] + s[i][j];}}}//matrix - matrixvoid minus( int t[N/2][N/2], int r[N/2][N/2], int s[N/2][N/2] ) {int i, j;for( i = 0; i < N / 2; i++ ){for( j = 0; j < N / 2; j++ ){t[i][j] = r[i][j] - s[i][j];}}}//matrix * matrixvoid mul( int t[N/2][N/2], int r[N/2][N/2], int s[N/2][N/2] ) {int i, j, k;for( i = 0; i < N / 2; i++ ){for( j = 0; j < N / 2; j++ ){t[i][j] = 0;for( k = 0; k < N / 2; k++ ){t[i][j] += r[i][k] * s[k][j];}}}}int main(){int i, j, k;int mat[N][N];int m1[N][N];int m2[N][N];int a[N/2][N/2],b[N/2][N/2],c[N/2][N/2],d[N/2][N/2];int e[N/2][N/2],f[N/2][N/2],g[N/2][N/2],h[N/2][N/2];int p1[N/2][N/2],p2[N/2][N/2],p3[N/2][N/2],p4[N/2][N/2];int p5[N/2][N/2],p6[N/2][N/2],p7[N/2][N/2];int r[N/2][N/2], s[N/2][N/2], t[N/2][N/2], u[N/2][N/2], t1[N/2][N/2], t2[N/2][N/2];printf("\nInput the first matrix...:\n");for( i = 0; i < N; i++ ){for( j = 0; j < N; j++ ){scanf("%d", &m1[i][j]);}}printf("\nInput the second matrix...:\n");for( i = 0; i < N; i++ ){for( j = 0; j < N; j++ ){scanf("%d", &m2[i][j]);}}// a b c d e f g hfor( i = 0; i < N / 2; i++ ){for( j = 0; j < N / 2; j++ ){a[i][j] = m1[i][j];b[i][j] = m1[i][j + N / 2];c[i][j] = m1[i + N / 2][j];d[i][j] = m1[i + N / 2][j + N / 2];e[i][j] = m2[i][j];f[i][j] = m2[i][j + N / 2];g[i][j] = m2[i + N / 2][j];h[i][j] = m2[i + N / 2][j + N / 2];}}//p1minus( r, f, h );mul( p1, a, r );//p2plus( r, a, b );mul( p2, r, h );//p3plus( r, c, d );mul( p3, r, e );//p4minus( r, g, e );mul( p4, d, r );//p5plus( r, a, d );plus( s, e, f );mul( p5, r, s );//p6minus( r, b, d );plus( s, g, h );mul( p6, r, s );//p7minus( r, a, c );plus( s, e, f );mul( p7, r, s );//r = p5 + p4 - p2 + p6plus( t1, p5, p4 );minus( t2, t1, p2 );plus( r, t2, p6 );//s = p1 + p2plus( s, p1, p2 );//t = p3 + p4plus( t, p3, p4 );//u = p5 + p1 - p3 - p7 = p5 + p1 - ( p3 + p7 )plus( t1, p5, p1 );plus( t2, p3, p7 );minus( u, t1, t2 );for( i = 0; i < N / 2; i++ ){for( j = 0; j < N / 2; j++ ){mat[i][j] = r[i][j];mat[i][j + N / 2] = s[i][j];mat[i + N / 2][j] = t[i][j];mat[i + N / 2][j + N / 2] = u[i][j];}}printf("\n下面是strassen算法处理结果:\n"); for( i = 0; i < N; i++ ){for( j = 0; j < N; j++ ){printf("%d ", mat[i][j]);}printf("\n");}//下面是朴素算法处理printf("\n下面是朴素算法处理结果:\n");for( i = 0; i < N; i++ ){for( j = 0; j < N; j++ ){mat[i][j] = 0;for( k = 0; k < N; k++ ){mat[i][j] += m1[i][j] * m2[i][j];}}}for( i = 0; i < N; i++ ){for( j = 0; j < N; j++ ){printf("%d ", mat[i][j]);}printf("\n");}return 0;}现在最好的计算矩阵乘法的复杂度是O( n^2.376 ),不过只是理论上的结果。

斯特拉森算法

斯特拉森算法

斯特拉森算法斯特拉森算法(Strassen algorithm)是一种矩阵乘法算法,由德国数学家弗莱戈·斯特拉森(Frigyes Riesz)和德国计算机科学家赫尔曼·斯特拉森(Hermann Strassen)在1969年提出。

传统的矩阵乘法的时间复杂度为 $O(n^3)$,但是斯特拉森算法只需要 $O(n^{log_2 7})$ 的时间复杂度,其中 $n$ 表示矩阵的尺寸。

斯特拉森算法的优点是,对于大矩阵的乘法,它的计算速度比传统的矩阵乘法要快很多。

斯特拉森算法的核心思想是将两个 $n\times n$ 的矩阵 $A$ 和 $B$ 分别划分为四个$\frac{n}{2}\times\frac{n}{2}$ 的子矩阵,即:$$A = \begin{bmatrix} A_{11} & A_{12} \\ A_{21} & A_{22} \end{bmatrix}, \quad B = \begin{bmatrix} B_{11} & B_{12} \\ B_{21} & B_{22} \end{bmatrix}$$然后,按照下面的公式计算出 $C = AB$:$$\begin{aligned} P_1 &= A_{11}(B_{12}-B_{22}) \\ P_2 &= (A_{11}+A_{12})B_{22} \\ P_3 &= (A_{21}+A_{22})B_{11} \\ P_4 &= A_{22}(B_{21}-B_{11}) \\ P_5 &=(A_{11}+A_{22})(B_{11}+B_{22}) \\ P_6 &= (A_{12}-A_{22})(B_{21}+B_{22}) \\ P_7 &= (A_{11}-A_{21})(B_{11}+B_{12}) \end{aligned}$$这个公式看起来很神秘,但是在具体实现时,可以递归应用斯特拉森算法来计算$P_1$ 到 $P_7$,直到遇到 $1\times 1$ 的矩阵,或者达到某个设定的阈值。

strassen矩阵乘法的分治算法

strassen矩阵乘法的分治算法

strassen矩阵乘法的分治算法Strassen矩阵乘法的分治算法引言矩阵乘法是计算机科学中非常常见的操作,它在各个领域中都有广泛的应用,如图像处理、人工智能等。

然而,传统的矩阵乘法算法的时间复杂度较高,限制了其在大规模矩阵计算中的应用。

为了提高矩阵乘法的效率,Strassen矩阵乘法算法被提出,它是一种基于分治策略的算法,能够显著降低矩阵乘法的时间复杂度。

算法原理Strassen矩阵乘法算法的核心思想是将两个n×n的矩阵A和B分解为四个n/2×n/2的子矩阵,然后通过一系列的加减运算得到矩阵C的四个n/2×n/2的子矩阵。

具体的算法步骤如下:1. 将矩阵A和B分别分解为四个n/2×n/2的子矩阵:A = | A11 A12 |B = | B11 B12 || | | || A21 A22 | | B21 B22 |其中A11、A12、A21、A22和B11、B12、B21、B22分别是n/2×n/2的子矩阵。

2. 计算七个中间矩阵M1、M2、M3、M4、M5、M6、M7:M1 = (A11 + A22) × (B11 + B22)M2 = (A21 + A22) × B11M3 = A11 × (B12 - B22)M4 = A22 × (B21 - B11)M5 = (A11 + A12) × B22M6 = (A21 - A11) × (B11 + B12)M7 = (A12 - A22) × (B21 + B22)3. 根据中间矩阵M1、M2、M3、M4、M5、M6、M7计算矩阵C的四个n/2×n/2的子矩阵:C11 = M1 + M4 - M5 + M7C12 = M3 + M5C21 = M2 + M4C22 = M1 - M2 + M3 + M64. 将矩阵C的四个n/2×n/2的子矩阵合并得到最终的矩阵C:C = | C11 C12 || || C21 C22 |算法分析Strassen矩阵乘法算法的时间复杂度为O(n^log2(7)),相比传统的矩阵乘法算法的时间复杂度O(n^3),显著降低了计算的复杂度。

strassen矩阵乘法各种情况详细解答

strassen矩阵乘法各种情况详细解答
Page 3
下面用一个动画来展示分矩阵 11b11 a12b21 a11 a12 b11 b12 a 的过程 A11 * B11
C11=A11*B11+A12*B21
a21 a22 b21 b22 a 21b11 a 22b21
a11b12 a12b22 a 21b12 a 22b22
分治法的设计思想:将一个难以直接解决的大问 题,分割成一些规模较小的相同问题,以便各个 击破,分而治之。 用分治法解决矩阵的乘法问题,先假定n是2的k 次幂,即n=2k。 1)第一步:递归维度半分。 如果n=2,则递归结束。 如果n>2,将A 和B 两个n 维方阵各分解为4 份,每份n/2 维。当子矩阵的阶还是大于2时, 继续将子矩阵分块,直到子矩阵的阶降为2。 第一步将会产出很多个2阶的方阵!
C (i, j ) A(i, k ) * B ( k , j )
k 1
n
1 i, j n
(n 2 ) 矩阵加法运算的时间复杂度是: 3 而矩阵乘法的时间复杂度是: (n )
求每个元素C(i,j)都需要n次乘法和n-1次加法 运算,且C共有n2个元素。源自Page 2二、分治法的思想
b T ( n) 7T (n / 2) an2
Page 9
n2 n2
直接推导可得: T (n) an2 (1 7 / 4 (7 / 4) 2 (7 / 4) k 2 ) 7 k 1 T (2)
16 7 log n 4 b log n an2 7 21 4 3 7 7 log 2 16 n 4 4 b n log 7 an 3 7 21 16 a b log 7 4a 2 n n 3 21 7 n 2.81

手算证明斯特拉森矩阵乘法

手算证明斯特拉森矩阵乘法

手算证明斯特拉森矩阵乘法斯特拉森矩阵乘法是一种优化矩阵乘法的算法,它通过将原始矩阵划分成四个子矩阵,并使用递归的方式进行计算,进而降低了时间复杂度。

接下来,我将手算证明斯特拉森矩阵乘法的正确性。

假设我们有两个nxn的矩阵A和B,我们想要计算它们的乘积C。

根据传统的矩阵乘法定义,我们需要对每个元素进行计算和求和,其时间复杂度为O(n^3)。

斯特拉森矩阵乘法的核心思想是将两个矩阵划分成四个子矩阵。

我们将A和B分别划分为以下四个子矩阵:A=,A11A12,B=,B11B12,A21A22,,B21B2其中,A11、A12、A21和A22是n/2xn/2的子矩阵,B11、B12、B21和B22也是n/2xn/2的子矩阵。

现在,我们将C划分成四个子矩阵:C=,C11C12C21C2其中,C11、C12、C21和C22也是n/2xn/2的子矩阵。

根据矩阵乘法的定义,我们可以得出以下递归公式:C11=A11*B11+A12*B21C12=A11*B12+A12*B22C21=A21*B11+A22*B21C22=A21*B12+A22*B22现在,我们需要证明这个递归公式的正确性。

我们将通过展开每个子矩阵的乘积来证明。

首先,我们展开C11的计算:C11=A11*B11+A12*B21根据斯特拉森矩阵乘法的定义,我们可以推断出A11乘以B11的结果可以通过以下方式计算得出:P1=A11*(B12-B22)同样地,A22乘以B21的结果可以通过以下方式计算得出:P2=(A21+A22)*B11C11的结果可以通过以下方式计算得出:C11=P1+P2+A22*B22同样的,我们可以展开C12、C21和C22的计算。

C12=A11*B12+A12*B22根据斯特拉森矩阵乘法的定义,我们可以推断出A11乘以B12的结果可以通过以下方式计算得出:P3=A12*(B21-B11)同样地,A22乘以B22的结果可以通过以下方式计算得出:P4=(A21+A22)*B22C12的结果可以通过以下方式计算得出:C12=A11*B12+P3+P4同样的,我们可以展开C21和C22的计算。

矩阵strassen算法

矩阵strassen算法

矩阵strassen算法
矩阵Strassen算法是一种用于快速计算矩阵乘法的算法。

它是由Volker Strassen在1969年提出的。

矩阵乘法是一种常见的数学运算,但是传统的矩阵乘法算法在处理大型矩阵时会消耗大量的时间和资源。

Strassen算法通过将矩阵乘法分解成更小的子问题,并利用这些子问题之间的关系来减少乘法的次数,从而实现了更高效的计算。

具体来说,Strassen算法将两个n×n的矩阵A和B分别划分成四个n/2×n/2的子矩阵,并通过一系列加法和减法操作来计算出所需的乘积矩阵C。

这种分治的策略使得算法的时间复杂度降低到O(n^log7)(约等于O(n^2.81)),比传统的矩阵乘法算法的时间复杂度O(n^3)更低。

然而,尽管Strassen算法在理论上具有更好的时间复杂度,但在实际应用中却并不总是比传统算法更快。

这是因为Strassen算法虽然减少了乘法的次数,但引入了更多的加法和减法操作,而且在实际计算机中,矩阵乘法的常数项对于算法的效率也有很大影响。

此外,由于Strassen算法涉及到矩阵的分解和递归计算,对于
小规模矩阵来说,并不能带来明显的性能提升。

因此,在实际应用中,需要根据具体情况权衡选择使用传统的矩阵乘法算法还是Strassen算法。

总的来说,矩阵Strassen算法是一种重要的矩阵乘法算法,它
通过分治和递归的思想,实现了对传统矩阵乘法算法的优化。

然而,在实际应用中需要综合考虑算法的时间复杂度、常数项影响以及实
际问题的规模等因素,来选择合适的算法。

Stranssen矩阵乘法

Stranssen矩阵乘法

Strassen矩阵乘法A和B都是n*n的方阵,计算C=A* B。

这个通常做法的乘法计算量是0(exp(n,3)),为了把这个计算数量级从3降到 log2(7),log2(7)略小于2.81。

我们使用Strassen乘法,方法如下:输入方阵的阶,和方阵A,B,输出C。

测试数据:Sample In (in.txt)91 32 5 8 93 8 35 3 2 7 7 3 2 2 65 6 7 8 4 2 1 7 32 5 4 7 4 8 1 5 78 3 2 6 3 8 6 5 82 6 4 83 2 1 8 93 54 75 46 3 02 5 8 5 93 1 6 83 5 2 1 6 7 5 8 311 13 12 25 38 49 33 28 335 3 2 7 7 3 2 2 2352 6 7 8 43 2 1 47 4424 5 4 7 4 8 1 5 281 3 24 6 36 8 36 5 02 62 34 83 2 1 8 23 5 34 75 456 3 212 35 8 5 943 15 6 10 34 33 23 22 1 2 5 3Sample Out (out.txt)1031 1038 815 347 1313 346 487 337 2681015 612 660 439 916 478 489 382 2541166 653 506 430 1444 446 455 617 518926 1026 763 447 1108 292 334 441 374728 1137 992 612 1243 786 521 521 364898 832 631 468 1391 294 344 423 3961021 511 586 310 853 553 385 410 4511483 814 774 483 1553 318 528 615 540867 930 779 369 1319 488 491 357 350Code:(strassen.cpp)#include<iostream>#include<fstream>#define N 65using namespace std;void show(int n,int array[][N]){for(int i=0;i<n;i++){for(int j=0;j<n;j++){cout<<array[i][j]<<" ";}cout<<endl;}cout<<endl;}/*strassen矩?阵¨®计?算?函¡¥数ºy,ê?申¦¨º明¡Â不?定¡§义°?*/ void strassen(int n,int A[][N],int B[][N],int C[][N]);/*矩?阵¨®加¨®法¤¡§*/void matMin(int a[][N],int b[][N],int c[][N],int n){for(int i=0;i<n;i++){for(int j=0;j<n;j++){c[i][j]=a[i][j]-b[i][j];}}}/*方¤?阵¨®减?法¤¡§*/void matPlu(int a[][N],int b[][N],int c[][N],int n){for(int i=0;i<n;i++){for(int j=0;j<n;j++){c[i][j]=a[i][j]+b[i][j];}}}/*m函¡¥数ºy的Ì?计?算?*/void funcM1(int m1[][N],int n,int a11[][N],int a12[][N],int a21[][N],int a22[][N],int b11[][N],int b12[][N],int b21[][N],int b22[][N]){int temp1[N][N];matPlu(a21,a22,temp1,n);matMin(temp1,a11,temp1,n);int temp2[N][N];matMin(b22,b12,temp2,n);matPlu(temp2,b11,temp2,n);strassen(n,temp1,temp2,m1);}void funcM2(int m2[][N],int n,int a11[][N],int a12[][N],int a21[][N],int a22[][N],int b11[][N],int b12[][N],int b21[][N],int b22[][N]){strassen(n,a11,b11,m2);}void funcM3(int m3[][N],int n,int a11[][N],int a12[][N],int a21[][N],int a22[][N],int b11[][N],int b12[][N],int b21[][N],int b22[][N]){strassen(n,a12,b21,m3);}void funcM4(int m4[][N],int n,int a11[][N],int a12[][N],int a21[][N],int a22[][N],int b11[][N],int b12[][N],int b21[][N],int b22[][N]){int temp1[N][N];matMin(a11,a21,temp1,n);int temp2[N][N];matMin(b22,b12,temp2,n);strassen(n,temp1,temp2,m4);}void funcM5(int m5[][N],int n,int a11[][N],int a12[][N],int a21[][N],int a22[][N],int b11[][N],int b12[][N],int b21[][N],int b22[][N]){int temp1[N][N];matPlu(a21,a22,temp1,n);int temp2[N][N];matMin(b12,b11,temp2,n);strassen(n,temp1,temp2,m5);}void funcM6(int m6[][N],int n,int a11[][N],int a12[][N],int a21[][N],int a22[][N],int b11[][N],int b12[][N],int b21[][N],int b22[][N]){int temp1[N][N];matMin(a12,a21,temp1,n);matPlu(temp1,a11,temp1,n);matMin(temp1,a22,temp1,n);strassen(n,temp1,b22,m6);}void funcM7(int m7[][N],int n,int a11[][N],int a12[][N],int a21[][N],int a22[][N],int b11[][N],int b12[][N],int b21[][N],int b22[][N]){int temp1[N][N];matPlu(b11,b22,temp1,n);matMin(temp1,b12,temp1,n);matMin(temp1,b21,temp1,n);strassen(n,a22,temp1,m7);}/*把ã?A【?】?B【?】?方¤?阵¨®分¤?别Àe拆e开a为aa11,a12,a21,a22和¨ªb11,b12,b21,b22*/ void part(int n,int A[][N],int B[][N],int a11[][N],int a12[][N],int a21[][N],inta22[][N],int b11[][N],int b12[][N],int b21[][N],int b22[][N]){int i,j;for(i=0;i<n/2;i++)for(j=0;j<n/2;j++){a11[i][j]=A[i][j];a12[i][j]=A[i][j+n/2];a21[i][j]=A[i+n/2][j];a22[i][j]=A[i+n/2][j+n/2];b11[i][j]=B[i][j];b12[i][j]=B[i][j+n/2];b21[i][j]=B[i+n/2][j];b22[i][j]=B[i+n/2][j+n/2];}}/*用®?mi组Á¨¦建¡§方¤?阵¨®乘?积yC*/void comb(int n,int C[][N],int m[][N][N]){int c[2][2][N][N];//c00matPlu(m[2],m[3],c[0][0],n/2);//c01matPlu(m[1],m[2],c[0][1],n/2);matPlu(c[0][1],m[5],c[0][1],n/2);matPlu(c[0][1],m[6],c[0][1],n/2);//c10matPlu(m[1],m[2],c[1][0],n);matPlu(c[1][0],m[4],c[1][0],n/2);matMin(c[1][0],m[7],c[1][0],n/2);//c11matPlu(m[1],m[2],c[1][1],n/2);matPlu(c[1][1],m[4],c[1][1],n/2);matPlu(c[1][1],m[5],c[1][1],n/2);//combfor(int i=0;i<n/2;i++)for(int j=0;j<n/2;j++){C[i][j]=c[0][0][i][j];C[i][j+n/2]=c[0][1][i][j];C[i+n/2][j]=c[1][0][i][j];C[i+n/2][j+n/2]=c[1][1][i][j];}}void strassen(int n,int A[][N],int B[][N],int C[][N]) {if(n==1){C[0][0]=A[0][0]*B[0][0];}else{int a11[N][N],a12[N][N],a21[N][N],a22[N][N];int b11[N][N],b12[N][N],b21[N][N],b22[N][N];int m[8][N][N];part(n,A,B,a11,a12,a21,a22,b11,b12,b21,b22);funcM1(m[1],n/2,a11,a12,a21,a22,b11,b12,b21,b22); funcM2(m[2],n/2,a11,a12,a21,a22,b11,b12,b21,b22); funcM3(m[3],n/2,a11,a12,a21,a22,b11,b12,b21,b22);funcM4(m[4],n/2,a11,a12,a21,a22,b11,b12,b21,b22); funcM5(m[5],n/2,a11,a12,a21,a22,b11,b12,b21,b22); funcM6(m[6],n/2,a11,a12,a21,a22,b11,b12,b21,b22); funcM7(m[7],n/2,a11,a12,a21,a22,b11,b12,b21,b22);comb(n,C,m);}}int main(){int i,j,n;int A[N][N];int B[N][N];int C[N][N];ifstream fin("in2.txt");ofstream fout("out22.txt");//输º?入¨?数ºy据Yfin>>n;for(i=0;i<n;i++)for(j=0;j<n;j++)fin>>A[i][j];for(i=0;i<n;i++)for(j=0;j<n;j++)fin>>B[i][j];//填¬?充?int m=1;while(m<n){m=m<<1;}fout<<m<<endl;for(i=n;i<m;i++)for(j=n;j<m;j++)A[i][j]=B[i][j]=0;//strassen矩?阵¨®乘?法¤¡§计?算?strassen(m,A,B,C);//结¨¢果?显?示º?for(i=0;i<n;i++){for(j=0;j<n;j++){fout<<C[i][j]<<" ";}fout<<endl; }}仅供个人用于学习、研究;不得用于商业用途。

n阶方阵乘法straseen

n阶方阵乘法straseen
分块矩阵乘法进行8次矩阵乘法时间复杂度为thetan3thetanlg8改进后仅需要7次乘法时间复杂度为thetanlg7
n阶方阵乘法straseen
原理:分块矩阵乘法,进行8次矩阵乘法,时间复杂度为 $\theta(n^3) = \theta(n^{\lg{8}}) $ , 改进后仅需要7次乘法, 时间复杂度为 $\theta(n^{\lg{7}})$
def matrix_add(A, B): rows = len(A) C = [[0]*rows for _ in range(rows)] for i in range(rows): for j in range(rows): C[i][j] = A[i][j] + B[i][j] return C
def strassen(A, B): n = len(A) C = [[0] for _ in range(n)] if n == 1: C[0][0] = A[0][0]*B[0][0] return C A11, A12, A21, A22 = matrix_divide(A) B11, B12, B21, B22 = matrix_divide(B)
def matrix_merge(C11, C12, C21, C22): rows = len(C11) n = rows * 2 C = [[0]*n for _ in range(n)] for i in range(rows): for j in range(rows): C[i][j] = C11[i][j] C[i][rows+j] = C12[i][j] C[rows+i][j] = C21[i][j] C[rows+i][Байду номын сангаасows+j] = C22[i][j] return C

strassen矩阵乘法 用于非方阵

strassen矩阵乘法 用于非方阵

strassen矩阵乘法用于非方阵Strassen矩阵乘法算法是一种高效的矩阵乘法算法,它通过减少乘法和加法的次数来提高计算效率。

而且,Strassen矩阵乘法算法也可以应用于非方阵的情况。

在传统的矩阵乘法中,两个矩阵相乘的时间复杂度为O(n^3),其中n是矩阵的维度。

而Strassen矩阵乘法的时间复杂度为O(n^log2(7)),这在n较大时会比传统的算法更加高效。

对于非方阵的情况,我们首先需要考虑矩阵的维度。

假设我们有一个m×n的矩阵A和一个n×l的矩阵B,为了进行矩阵乘法运算,我们需要保证矩阵A的列数和矩阵B的行数相等。

当然,可以根据需要对矩阵进行维度调整,使得矩阵满足要求。

在使用Strassen矩阵乘法算法时,我们需要将矩阵按照一定的规则进行划分。

通常情况下,我们会将矩阵等分为四个相等的子矩阵,然后对这些子矩阵进行递归的乘法运算。

在非方阵的情况下,我们需要考虑矩阵划分的方式。

一种常见的方法是通过填充零元素来将矩阵转变为方阵。

例如,如果矩阵A的维度为m×n,我们可以将其进行零元素填充,使得其变为一个m×m的方阵。

同样地,我们也可以将矩阵B填充为一个n×n的方阵。

然后,我们可以利用Strassen矩阵乘法算法对这两个方阵进行相乘运算。

最后,再根据目标结果的维度,将得到的方阵进行截取,得到非方阵的乘积结果。

需要注意的是,在进行Strassen矩阵乘法时,我们需要考虑矩阵的维度是否满足要求以及矩阵的规模是否适合使用此算法。

因为Strassen矩阵乘法在某些情况下可能会比传统的矩阵乘法更加低效,当矩阵的规模较小时,传统的算法可能更加合适。

总之,Strassen矩阵乘法算法可以应用于非方阵的情况。

我们只需要对矩阵进行维度调整和零元素填充,然后按照算法规定的方式进行矩阵的划分和递归乘法运算。

这样,我们就可以得到非方阵的乘积结果。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。



由此可见,Strassen矩阵乘法的计算时间复杂性 比普通矩阵乘法有所改进。
Page 10
由下图可以看出Strassen的算法与蛮力算法的差距。
Page 11
五、具体算法
递归维度分半算法: procedure STRASSEN(n,A,B,C); begin if n=2 then MATRIX-MULTIPLY(A,B,C)//结束循环,计算 两个2阶方阵的乘法 else begin 将矩阵A和B分块; STRASSEN(n/2,A11,B12-B22,M1); STRASSEN(n/2,A11+A12,B22,M2); STRASSEN(n/2,A21+A22,B11,M3); STRASSEN(n/2,A22,B21-B11,M4); STRASSEN(n/2,A11+A22,B11+B22,M5); STRASSEN(n/2,A12-A22,B21+B22,M6); STRASSEN(n/2,A11-A21,B11+B12,M7);
b T ( n) 7T (n / 2) an2
Page 9
n2 n2
直接推导可得: T (n) an2 (1 7 / 4 (7 / 4) 2 (7 / 4) k 2 ) 7 k 1 T (2)
16 7 log n 4 b log n an2 7 21 4 3 7 7 log 2 16 n 4 4 b n log 7 an 3 7 21 16 a b log 7 4a 2 n n 3 21 7 n 2.81
Strassen矩阵乘法
计科7班
Page 1
一、n阶方阵的传统算法(蛮力法,教 材49页例3)
假定A, B都是n×n矩阵,它们的i行j列元素分 别记为A(i,j)和B(i,j)。如果用S和C分别记A+B 和A*B, 则有: S (i, j ) A(i, j ) B(i, j ) 1 i, j n
Page 7
三、Strassen矩阵乘法
Strassen提出了一种新的算法来计算2个2阶方 阵的乘积。他的算法只用了7次乘法运算,但 增加了加、减法的运算次数。这7次乘法是: M1=A11(B12-B22) M2=(A11+A12)B22 M3=(A21+A22)B11 M4=A22(B21-B11) M5=(A11+A22)(B11+B22) M6=(A12-A22)(B21+B22) M7=(A11A21)(B11+B12)
A矩阵
a11 a12 b11
B矩阵
b12
A11
a13 a14
A12
B11
b13 b14
B12
A21
A22
Page 4
B21
B22
2)第二步:计算两个2阶方阵的乘积之后再合并。 假如A,B两个矩阵是由第一步得出的维 数为2的方阵,则:
A11 A12 B11 B12 C11 C12 A* B B C A21 A22 21 B22 21 C22 C11 A11B11 A12 B21 C12 A11B12 A12 B22 C21 A21B11 A22 B21 C22 A21B12 A22 B22
Page 8
做了7次乘法后,再做若干次加、减法: C11=M5+M4-M2+M6 C12=M1+M2 C21=M3+M4 C22=M5+M1-M3-M7
四、Strassen算法效率分析
Strassen矩阵乘积分治算法中,用了7次对于 n/2阶矩阵乘积的递归调用和18次n/2阶矩阵的加减 运算。由此可知,该算法的所需的计算时间T(n)满 足如下的递归方程:
Page 3
下面用一个动画来展示分矩阵 11b11 a12b21 a11 a12 b11 b12 a 的过程 A11 * B11
C11=A11*B11+A12*B21
a21 a22 b21 b22 a 21b11 a 22b21
a11b12 a12b22 a 21b12 a 22b22
Page 13
2.当n的值不是2k,A,B也不是方阵时 A矩阵 1 1 1 1 1 1 1 1 X 1 1 B矩阵 1 1 1 1 0 0
1
0
1
0
1
0
1
0
1
1
11Leabharlann 1100
可以用为0的行或者列来填充,使A和B变成 维数为2k的方阵,再用strassen算法计算。
Page 14
end; end;
Page 12
六、其他情况的讨论
1.当n的值不是2k,但A,B是方阵时 A矩阵 1 1 1 1 1 1 1 1 1 X B矩阵 C矩阵
1
1 1
1
1 1
1
1 1 =
3
3
3
3
3
3
3
3
3
则找最近的k,2k< n < 2k+1,将A,B矩阵的行和列分为 1...2k , 2k + 1 ...n 两部分,阶为2k的方阵就可以采用 strassen算法,其他元素就采用蛮力法来求。
分治法的设计思想:将一个难以直接解决的大问 题,分割成一些规模较小的相同问题,以便各个 击破,分而治之。 用分治法解决矩阵的乘法问题,先假定n是2的k 次幂,即n=2k。 1)第一步:递归维度半分。 如果n=2,则递归结束。 如果n>2,将A 和B 两个n 维方阵各分解为4 份,每份n/2 维。当子矩阵的阶还是大于2时, 继续将子矩阵分块,直到子矩阵的阶降为2。 第一步将会产出很多个2阶的方阵!
通过上面4条式可以将A*B的值存到C矩阵中。
Page 5
三、分治法求矩阵乘法的效率分析
如果用T(n)记两个n阶矩阵相乘所用的时间, 则有如下递归关系式:
b T ( n) 8T (n / 2) dn2
n2 n2
依此算法,计算2个n阶方阵的乘积转化为计 算8个n/2阶方阵的乘积和4个n/2阶方阵的加 法。因此可得:
T (n) bn / 8 4d (n 16) / 3
3 2
3 T b 0 所以: (n) (n ) 因为
Page 6
综上所述可知:分治法的运用,方阵的乘法 的算法效率并没有提高!该方法并不比用原始定 义直接计算更有效。究其原因,是因为没有减少 矩阵的乘法次数。 传统方法2个2阶方阵相乘需要8次乘法。要 想减少乘法运算次数,关键在于计算2个2阶方 阵的乘积时,乘法的次数能不能少于8次。
C (i, j ) A(i, k ) * B ( k , j )
k 1
n
1 i, j n
(n 2 ) 矩阵加法运算的时间复杂度是: 3 而矩阵乘法的时间复杂度是: (n )
求每个元素C(i,j)都需要n次乘法和n-1次加法 运算,且C共有n2个元素。
Page 2
二、分治法的思想
相关文档
最新文档