1、矩阵乘法分治法算法设计与分析实验报告实验名称: 矩阵乘法(分冶法) 一、问题陈述和分析: 1.实验目的:掌握分总冶策略的基本思想以及用分冶法解决问题的一般技巧运用编程工具,并运用分冶法来解决矩阵乘法问题;2.实验内容:设A 和 B 是两个n * n阶矩阵,求它们两的乘积矩阵C。这里,假设n是2的幂次方; 3.实验要求:编制程序并对其时间复杂度和空间复杂度进行分析.二、模型拟制、算法设计和正确性证明:设A和B是两个n*n阶矩阵,求他们两的成绩矩阵C。这里假设n是2的幂次方;A和B是两个n*n的矩阵,他们的乘积C=AB也是一个n*n的矩阵,矩阵C中的元素Cij定义为Cij= ,则每计算一个Cij,
2、需要做n次乘法和n-1次加法。因此计算C的n2个元素需要n3次乘法和n3- n2次加法。因此,所需的时间复杂度是O(n3)。 但是使用分治法可以改进算法的时间复杂度。这里,假设n是2的幂。将矩阵A,B,C中每一矩阵都分成4个大小相等的子矩阵,每个子矩阵是(n/2)*(n/2)的方阵。由此,可将方阵C=AB重写为 因此可得: C11=A11B11+A12B21 C12=A11B12+A12B22 C21=A21B11+A22B22 C22=A21B12+A22B22 这样就将2个n阶矩阵的乘积变成计算8个n/2阶矩阵的乘积和4个n/2阶矩阵的加法。当n=1时,2个1阶方阵的乘积可直接算出,只需要
3、做一次乘法。当子矩阵阶n1时,为求两个子矩阵的乘积,可继续对两个子矩阵分块,直到子矩阵的阶为1。由此,便产生了分治降阶的递归算法。但是这个算法并没有降低算法的时间复杂度。由strassen矩阵乘法,M1=A11(B12-B22)M2=(A11+A12)B22M3=(A21+A22)B11M4=A22(B21-B11)M5=(A11+A22)(B11+B22)M6=(A12-A22)(B21+B22)M7=(A11-A21)(B11+B12)C11=M5+M4-M2+M6C12=M1+M2C21=M3+M4C22=M5+M1-M3-M7算法共进行7次举证乘法,算法效率得到降低主要数据的定义: i
4、nt n;n是方阵A,B,C的阶 int *A=new int*n; /矩阵A,B,C的定义,并为它们分配空间。这里A,B是用/于相乘的矩阵,C用于存放AB的结果 int *B=new int*n; int *C=new int*n; int i,j; for(i=0;in;i+) Ai=new intn; Bi=new intn; Ci=new intn;程序中定义的函数:1.void Divide(int n,int *A,int *A11,int *A12,int *A21,int *A22)函数实现的功能是:将n*n的矩阵A分块成四个大小相等的(n/2)*(n/2)的子矩阵A11,A1
5、2,A21,A22。2.void Unit(int n,int *A,int *A11,int *A12,int *A21,int *A22)函数实现的功能是:将四个(n/2)*(n/2)的矩阵A11,A12,A21,A22合并成一个n*n的矩阵A。4. void Add(int n,int *A,int *B,int *C) 函数的功能是:实现C=A+B,A,B,C都是n*n矩阵。3.void Mul(int n,int *A,int *B,int *M) 函数的功能是:将n*n的矩阵A,B相乘,结果存放在n*n的矩阵M中。算法设计:整个算法的大致思想是:在函数Mul(int n,int *
6、A,int *B,int *M)中先判断n的值,若n=1,表示A,B,C均为一阶方阵。则M00=A00*B00;否则,调用Divide(n,A,A11,A12,A21,A22);和Divide(n,B,B11,B12,B21,B22);将A和B都分为四个(n/2)*(n/2)的子矩阵。然后递归调用 Sub(n,B12,B22,T1);T1=B12-B22 Mul(n, A11,T1 ,M1);M1=A11(B12-B22) Add(n,A11,A12,T2); Mul(n,T2,B22,M2);M2=(A11+A12)B22 Add(n,A21,A22,T1); Mul(n,T1,B11,M3
7、);M3=(A21+A22)B11 Sub(n,B21,B11,T1); Mul(n, A22,T1 ,M4);M4=A22(B21-B11) Add(n,A11,A22,T1); Add(n,B11,B22,T2); Mul(n,T1,T2,M5);M5=(A11+A22)(B11+B22) Sub(n,A12,A22,T1); Add(n,B21,B22,T2); Mul(n,T1,T2,M6);M6=(A12-A22)(B21+B22) Sub(n,A11,A21,T1); Sub(n,B11,B12,T2); Mul(n,T1,T2,M7);M7=(A11-A21)(B11+B12)
8、Add(n,M5,M4,T1); Sub(n,T1,M2,T2); Add(n,T2,M6,M11);M11=M5+M4-M2+M6 Add(n,M1,M2,M12);M12=M1+M2 Add(n,M3,M4,M21);M21=M3+M4 Add(n,M5,M1,T1); Sub(n,T1,M3,T2); Sub(n,T2,M7,M22);M22=M5+M1-M3-M7 Unit(n,M,M11,M12,M21,M22);将上面得到的四个矩阵组合成一个n*n矩阵。则这个n*n矩阵就是AB的结果C。正确性证明:由矩阵乘法的计算方法可知,上述计算方法显然正确三、时间和空间复杂性分析:时间复杂性:
9、Strassen矩阵乘法中,用了7次对于n/2阶矩阵乘法的递归调用和18次n/2阶矩阵的加减运算。由此可知,该算法所需的计算时间T(n)满足如下递归方程解此递归方程得 。由此可见,strassen矩阵乘法的计算时间复杂性比普通乘法有较大改进。空间复杂性: 程序中定义了一些整型变量和若干个二维数组。因此算法的时间复杂度是O(n*n)。四、程序实现和测试过程:程序测试过程(1)测试过程(2)五、总结:源程序:#include#include#includeusing namespace std;ifstream infile(123.txt,ios:in);void Input(int n,int
10、 *A) /infilen; for(int i=0;in;i+) for(int j=0;jAij;void Output(int n,int *A) for(int i=0;in;i+) for(int j=0;jn;j+) coutAijt; coutendl;coutendl;void Divide(int n,int *A,int *A11,int *A12,int *A21,int *A22) int i,j; for(i=0;in;i+) for(j=0;jn;j+) A11ij=Aij; A12ij=Aij+n; A21ij=Ai+nj; A22ij=Ai+nj+n; void
11、 Unit(int n,int *A,int *A11,int *A12,int *A21,int *A22) int i,j; for(i=0;in;i+) for(j=0;jn;j+) Aij=A11ij; Aij+n=A12ij; Ai+nj=A21ij; Ai+nj+n=A22ij; void Sub(int n,int *A,int *B,int *C) int i,j; for(i=0;in;i+) for(j=0;jn;j+) Cij=Aij-Bij;void Add(int n,int *A,int *B,int *C) int i,j; for(i=0;in;i+) for(
12、j=0;jn;j+) Cij=Aij+Bij;void Mul(int n,int *A,int *B,int *M) if(n=1) M00=A00*B00; else n=n/2; int *A11,*A12,*A21,*A22; int *B11,*B12,*B21,*B22; int *M11,*M12,*M21,*M22; int *M1,*M2,*M3,*M4,*M5,*M6,*M7; int *T1,*T2; A11=new int*n; A12=new int*n; A21=new int*n; A22=new int*n; B11=new int*n; B12=new int
13、*n; B21=new int*n; B22=new int*n; M11=new int*n; M12=new int*n; M21=new int*n; M22=new int*n; M1=new int*n; M2=new int*n; M3=new int*n; M4=new int*n; M5=new int*n; M6=new int*n; M7=new int*n; T1=new int*n; T2=new int*n; int i; for(i=0;in;i+) A11i=new intn; A12i=new intn; A21i=new intn; A22i=new intn
14、; B11i=new intn; B12i=new intn; B21i=new intn; B22i=new intn; M11i=new intn; M12i=new intn; M21i=new intn; M22i=new intn; M1i=new intn; M2i=new intn; M3i=new intn; M4i=new intn; M5i=new intn; M6i=new intn; M7i=new intn; T1i=new intn; T2i=new intn; Divide(n,A,A11,A12,A21,A22); Divide(n,B,B11,B12,B21,
15、B22); / coutA11,A12,A21,A22endl; / Output(n,A11);Output(n,A12);Output(n,A21);Output(n,A22); Sub(n,B12,B22,T1); / coutB12-B22endl; / Output(n,T1); Mul(n,A11,T1,M1); Add(n,A11,A12,T2); Mul(n,T2,B22,M2); Add(n,A21,A22,T1); Mul(n,T1,B11,M3); Sub(n,B21,B11,T1); Mul(n,A22,T1,M4); Add(n,A11,A22,T1); Add(n,
16、B11,B22,T2); Mul(n,T1,T2,M5); Sub(n,A12,A22,T1); Add(n,B21,B22,T2); Mul(n,T1,T2,M6); Sub(n,A11,A21,T1); Add(n,B11,B12,T2); Mul(n,T1,T2,M7); Add(n,M5,M4,T1); Sub(n,T1,M2,T2); Add(n,T2,M6,M11); Add(n,M1,M2,M12); Add(n,M3,M4,M21); Add(n,M5,M1,T1); Sub(n,T1,M3,T2); Sub(n,T2,M7,M22); Unit(n,M,M11,M12,M21
17、,M22); int main() int n; coutplease input number nn; int *A,*B,*C; A=new int*n; B=new int*n; C=new int*n; for(int i=0;in;i+) Ai=new intn; Bi=new intn; Ci=new intn; Input(n,A); coutA Matrix isendl; Output(n,A); Input(n,B); coutB Matrix isendl; Output(n,B); Input(n,C); /Output(n,C); Mul(n,A,B,C); coutThe Product of A and B isendl; Output(n,C); / coutnendl; infile.close(); return 0;
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1