算法导论02--矩阵乘法

本文探讨了Strassen算法在矩阵乘法中的应用,通过编程实现了普通矩阵乘法和Strassen算法,并在不同数据规模下比较了两者的运行时间。实验显示,Strassen算法在大尺寸矩阵中可能提供更快的计算速度。此外,还提出了针对非2的幂次矩阵的Strassen算法改进方案,并进行了性能分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、目的

1.熟悉算法设计的基本思想
2.掌握Strassen算法的基本思想,并且能够分析算法性能

二、内容与设计思想

  1. 设计一个随机数矩阵生成器,输入参数包括N, s, t;可随机生成一个大小为N*N、数值范围在[s, t]之间的矩阵。
  2. 编程实现普通的矩阵乘法;
  3. 编程实现Strassen’s algorithm;
  4. 在不同数据规模情况下(数据规模N=2^4, 2^8, 2^9, 2^10, 2^11)下,两种算法的运行时间各是多少;
  5. 思考题:修改Strassen’s algorithm,使之适应矩阵规模N不是2的幂的情况;
  6. 改进后的算法与2中的算法在相同数据规模下进行比较。

三、使用环境

推荐使用C/C++集成编译环境。

四、实验过程

1、写出矩阵生成器和算法的源代码;

//(1)
#include<bits/stdc++.h>
using namespace std;
 
int Strassen(int n, int** MatrixA, int ** MatrixB, int ** MatrixC);
int ADD(int** MatrixA, int** MatrixB, int** MatrixResult, int length );
int SUB(int** MatrixA, int** MatrixB, int** MatrixResult, int length );
int MUL(int** MatrixA, int** MatrixB, int** MatrixResult, int length );
void FillMatrix( int** matrix1, int** matrix2, int length);
int main()
{
 
    int MatrixSize = 0;
 
    int** MatrixA;
    int** MatrixB;
    int** MatrixC;
 
    srand(time(0));

	cout<<"Please Enter your Matrix Size: ";
    cin>>MatrixSize;
 
    int N = MatrixSize;
 
 
    MatrixA = new int *[MatrixSize];
    MatrixB = new int *[MatrixSize];
    MatrixC = new int *[MatrixSize];
 
    for (int i = 0; i < MatrixSize; i++)
    {
        MatrixA[i] = new int [MatrixSize];
        MatrixB[i] = new int [MatrixSize];
        MatrixC[i] = new int [MatrixSize];
    }
 
    FillMatrix(MatrixA,MatrixB,MatrixSize);
 
    clock_t startTime2,endTime2;
	startTime2 = clock();
    
    Strassen( N, MatrixA, MatrixB, MatrixC );
    
    endTime2 = clock();
    cout << "The run time is:" <<(double)(1000*(endTime2 - startTime2) / CLOCKS_PER_SEC) << "ms" << endl; 

    return 0;
 
}

int Strassen(int N, int **MatrixA, int **MatrixB, int **MatrixC)
{
 
    int HalfSize = N/2;
    int newSize = N/2;

    if ( N <= 32 )
    {
        MUL(MatrixA,MatrixB,MatrixC,N);
    }
    else
    {
		int** A11;
		int** A12;
		int** A21;
		int** A22;
	
		int** B11;
		int** B12;
		int** B21;
		int** B22;
	
		int** C11;
		int** C12;
		int** C21;
		int** C22;
	
		int** M1;
		int** M2;
		int** M3;
		int** M4;
		int** M5;
		int** M6;
		int** M7;
		int** AResult;
		int** BResult;

		A11 = new int *[newSize];
		A12 = new int *[newSize];
		A21 = new int *[newSize];
		A22 = new int *[newSize];
	
		B11 = new int *[newSize];
		B12 = new int *[newSize];
		B21 = new int *[newSize];
		B22 = new int *[newSize];
	
		C11 = new int *[newSize];
		C12 = new int *[newSize];
		C21 = new int *[newSize];
		C22 = new int *[newSize];
	
		M1 = new int *[newSize];
		M2 = new int *[newSize];
		M3 = new int *[newSize];
		M4 = new int *[newSize];
		M5 = new int *[newSize];
		M6 = new int *[newSize];
		M7 = new int *[newSize];
	
		AResult = new int *[newSize];
		BResult = new int *[newSize];
	
		int newLength = newSize;

		for ( int i = 0; i < newSize; i++)
		{
			A11[i] = new int[newLength];
			A12[i] = new int[newLength];
			A21[i] = new int[newLength];
			A22[i] = new int[newLength];
	
			B11[i] = new int[newLength];
			B12[i] = new int[newLength];
			B21[i] = new int[newLength];
			B22[i] = new int[newLength];
	
			C11[i] = new int[newLength];
			C12[i] = new int[newLength];
			C21[i] = new int[newLength];
			C22[i] = new int[newLength];
	
			M1[i] = new int[newLength];
			M2[i] = new int[newLength];
			M3[i] = new int[newLength];
			M4[i] = new int[newLength];
			M5[i] = new int[newLength];
			M6[i] = new int[newLength];
			M7[i] = new int[newLength];
	
			AResult[i] = new int[newLength];
			BResult[i] = new int[newLength];
	
	
		}

	    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];
	
	        }
	    }

	    ADD( A11,A22,AResult, HalfSize);
	    ADD( B11,B22,BResult, HalfSize);
	    Strassen( HalfSize, AResult, BResult, M1 ); 

	    ADD( A21,A22,AResult, HalfSize);       
	    Strassen(HalfSize, AResult, B11, M2);      

	    SUB( B12,B22,BResult, HalfSize);        
	    Strassen(HalfSize, A11, BResult, M3);     

	    SUB( B21, B11, BResult, HalfSize);      
	    Strassen(HalfSize, A22, BResult, M4);       

	    ADD( A11, A12, AResult, HalfSize);         
	    Strassen(HalfSize, AResult, B22, M5);       

	    SUB( A21, A11, AResult, HalfSize);
	    ADD( B11, B12, BResult, HalfSize);           
	    Strassen( HalfSize, AResult, BResult, M6);   

	    SUB(A12, A22, AResult, HalfSize);
	    ADD(B21, B22, BResult, HalfSize);           
	    Strassen(HalfSize, AResult, BResult, M7);     

	    ADD( M1, M4, AResult, HalfSize);
	    SUB( M7, M5, BResult, HalfSize);
	    ADD( AResult, BResult, C11, HalfSize);

	    ADD( M3, M5, C12, HalfSize);

	    ADD( M2, M4, C21, HalfSize);

	    ADD( M1, M3, AResult, HalfSize);
	    SUB( M6, M2, BResult, HalfSize);
	    ADD( AResult, BResult, C22, HalfSize);
	
	    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];
	        }
	    }
	
		for (int i = 0; i < newLength; i++)
		{
			delete[] A11[i];delete[] A12[i];delete[] A21[i];
			delete[] A22[i];
	
			delete[] B11[i];delete[] B12[i];delete[] B21[i];
			delete[] B22[i];
			delete[] C11[i];delete[] C12[i];delete[] C21[i];
			delete[] C22[i];
			delete[] M1[i];delete[] M2[i];delete[] M3[i];delete[] M4[i];
			delete[] M5[i];delete[] M6[i];delete[] M7[i];
			delete[] AResult[i];delete[] BResult[i] ;
		}
			delete[] A11;delete[] A12;delete[] A21;delete[] A22;
			delete[] B11;delete[] B12;delete[] B21;delete[] B22;
			delete[] C11;delete[] C12;delete[] C21;delete[] C22;
			delete[] M1;delete[] M2;delete[] M3;delete[] M4;delete[] M5;
			delete[] M6;delete[] M7;
			delete[] AResult;
			delete[] BResult ;
 	}

	return 0;
}
 
int ADD(int** MatrixA, int** MatrixB, int** MatrixResult, int MatrixSize )
{
    for ( int i = 0; i < MatrixSize; i++)
    {
        for ( int j = 0; j < MatrixSize; j++)
        {
            MatrixResult[i][j] =  MatrixA[i][j] + MatrixB[i][j];
        }
    }
	return 0;
}
 
int SUB(int** MatrixA, int** MatrixB, int** MatrixResult, int MatrixSize )
{
    for ( int i = 0; i < MatrixSize; i++)
    {
        for ( int j = 0; j < MatrixSize; j++)
        {
            MatrixResult[i][j] =  MatrixA[i][j] - MatrixB[i][j];
        }
    }
	return 0;
}

int MUL( int** MatrixA, int** MatrixB, int** MatrixResult, int MatrixSize )
{
    for (int i=0;i<MatrixSize ;i++)
    {
          for (int j=0;j<MatrixSize ;j++)
          {
               MatrixResult[i][j]=0;
               for (int k=0;k<MatrixSize ;k++)
               {
                      MatrixResult[i][j]=MatrixResult[i][j]+MatrixA[i][k]*MatrixB[k][j];
               }
          }
    }
	return 0;
}
 
void FillMatrix( int** MatrixA, int** MatrixB, int length)
{
    for(int row = 0; row<length; row++)
    {
        for(int column = 0; column<length; column++)
        {
 
           MatrixB[row][column] = (MatrixA[row][column] = rand() %5);
        }
 
    }
}

//(2)
#include<bits/stdc++.h>
using namespace std;
 
int Strassen(int n, int** MatrixA, int ** MatrixB, int ** MatrixC);
int ADD(int** MatrixA, int** MatrixB, int** MatrixResult, int length );
int SUB(int** MatrixA, int** MatrixB, int** MatrixResult, int length );
int MUL(int** MatrixA, int** MatrixB, int** MatrixResult, int length );
void FillMatrix( int** matrix1, int** matrix2, int length, int t);
int main()
{
 
    int MatrixSize = 0;
    int t,MatrixSize0;
 
    int** MatrixA;
    int** MatrixB;
    int** MatrixC;
 
    srand(time(0));

	cout<<"Please Enter your Matrix Size: ";
    cin>>MatrixSize0;
    if (MatrixSize0%2==0)
    {
    	MatrixSize=MatrixSize0;
    	t=0;
	}
	else
	{
		MatrixSize = (MatrixSize0/2+1)*2;
		t = MatrixSize - MatrixSize0;
	}
 
    int N = MatrixSize;
 
 
    MatrixA = new int *[MatrixSize];
    MatrixB = new int *[MatrixSize];
    MatrixC = new int *[MatrixSize];
 
    for (int i = 0; i < MatrixSize; i++)
    {
        MatrixA[i] = new int [MatrixSize];
        MatrixB[i] = new int [MatrixSize];
        MatrixC[i] = new int [MatrixSize];
    }
 
    FillMatrix(MatrixA,MatrixB,MatrixSize,t);
 
    clock_t startTime,endTime;
	startTime = clock();
    
    Strassen( N, MatrixA, MatrixB, MatrixC );
    
    endTime = clock();
    cout << "The run time is:" <<(double)(1000*(endTime - startTime) / CLOCKS_PER_SEC) << "ms" << endl; 

    return 0;
 
}

int Strassen(int N, int **MatrixA, int **MatrixB, int **MatrixC)
{
 
    int HalfSize = N/2;
    int newSize = N/2;

    if ( N <= 32 )
    {
        MUL(MatrixA,MatrixB,MatrixC,N);
    }
    else
    {
		int** A11;
		int** A12;
		int** A21;
		int** A22;
	
		int** B11;
		int** B12;
		int** B21;
		int** B22;
	
		int** C11;
		int** C12;
		int** C21;
		int** C22;
	
		int** M1;
		int** M2;
		int** M3;
		int** M4;
		int** M5;
		int** M6;
		int** M7;
		int** AResult;
		int** BResult;

		A11 = new int *[newSize];
		A12 = new int *[newSize];
		A21 = new int *[newSize];
		A22 = new int *[newSize];
	
		B11 = new int *[newSize];
		B12 = new int *[newSize];
		B21 = new int *[newSize];
		B22 = new int *[newSize];
	
		C11 = new int *[newSize];
		C12 = new int *[newSize];
		C21 = new int *[newSize];
		C22 = new int *[newSize];
	
		M1 = new int *[newSize];
		M2 = new int *[newSize];
		M3 = new int *[newSize];
		M4 = new int *[newSize];
		M5 = new int *[newSize];
		M6 = new int *[newSize];
		M7 = new int *[newSize];
	
		AResult = new int *[newSize];
		BResult = new int *[newSize];
	
		int newLength = newSize;

		for ( int i = 0; i < newSize; i++)
		{
			A11[i] = new int[newLength];
			A12[i] = new int[newLength];
			A21[i] = new int[newLength];
			A22[i] = new int[newLength];
	
			B11[i] = new int[newLength];
			B12[i] = new int[newLength];
			B21[i] = new int[newLength];
			B22[i] = new int[newLength];
	
			C11[i] = new int[newLength];
			C12[i] = new int[newLength];
			C21[i] = new int[newLength];
			C22[i] = new int[newLength];
	
			M1[i] = new int[newLength];
			M2[i] = new int[newLength];
			M3[i] = new int[newLength];
			M4[i] = new int[newLength];
			M5[i] = new int[newLength];
			M6[i] = new int[newLength];
			M7[i] = new int[newLength];
	
			AResult[i] = new int[newLength];
			BResult[i] = new int[newLength];
	
	
		}

	    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];
	
	        }
	    }

	    ADD( A11,A22,AResult, HalfSize);
	    ADD( B11,B22,BResult, HalfSize);
	    Strassen( HalfSize, AResult, BResult, M1 ); 

	    ADD( A21,A22,AResult, HalfSize);       
	    Strassen(HalfSize, AResult, B11, M2);      

	    SUB( B12,B22,BResult, HalfSize);        
	    Strassen(HalfSize, A11, BResult, M3);     

	    SUB( B21, B11, BResult, HalfSize);      
	    Strassen(HalfSize, A22, BResult, M4);       

	    ADD( A11, A12, AResult, HalfSize);         
	    Strassen(HalfSize, AResult, B22, M5);       

	    SUB( A21, A11, AResult, HalfSize);
	    ADD( B11, B12, BResult, HalfSize);           
	    Strassen( HalfSize, AResult, BResult, M6);   

	    SUB(A12, A22, AResult, HalfSize);
	    ADD(B21, B22, BResult, HalfSize);           
	    Strassen(HalfSize, AResult, BResult, M7);     

	    ADD( M1, M4, AResult, HalfSize);
	    SUB( M7, M5, BResult, HalfSize);
	    ADD( AResult, BResult, C11, HalfSize);

	    ADD( M3, M5, C12, HalfSize);

	    ADD( M2, M4, C21, HalfSize);

	    ADD( M1, M3, AResult, HalfSize);
	    SUB( M6, M2, BResult, HalfSize);
	    ADD( AResult, BResult, C22, HalfSize);
	
	    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];
	        }
	    }
	
		for (int i = 0; i < newLength; i++)
		{
			delete[] A11[i];delete[] A12[i];delete[] A21[i];
			delete[] A22[i];
	
			delete[] B11[i];delete[] B12[i];delete[] B21[i];
			delete[] B22[i];
			delete[] C11[i];delete[] C12[i];delete[] C21[i];
			delete[] C22[i];
			delete[] M1[i];delete[] M2[i];delete[] M3[i];delete[] M4[i];
			delete[] M5[i];delete[] M6[i];delete[] M7[i];
			delete[] AResult[i];delete[] BResult[i] ;
		}
			delete[] A11;delete[] A12;delete[] A21;delete[] A22;
			delete[] B11;delete[] B12;delete[] B21;delete[] B22;
			delete[] C11;delete[] C12;delete[] C21;delete[] C22;
			delete[] M1;delete[] M2;delete[] M3;delete[] M4;delete[] M5;
			delete[] M6;delete[] M7;
			delete[] AResult;
			delete[] BResult ;
 	}

	return 0;
}
 
int ADD(int** MatrixA, int** MatrixB, int** MatrixResult, int MatrixSize )
{
    for ( int i = 0; i < MatrixSize; i++)
    {
        for ( int j = 0; j < MatrixSize; j++)
        {
            MatrixResult[i][j] =  MatrixA[i][j] + MatrixB[i][j];
        }
    }
	return 0;
}
 
int SUB(int** MatrixA, int** MatrixB, int** MatrixResult, int MatrixSize )
{
    for ( int i = 0; i < MatrixSize; i++)
    {
        for ( int j = 0; j < MatrixSize; j++)
        {
            MatrixResult[i][j] =  MatrixA[i][j] - MatrixB[i][j];
        }
    }
	return 0;
}

int MUL( int** MatrixA, int** MatrixB, int** MatrixResult, int MatrixSize )
{
    for (int i=0;i<MatrixSize ;i++)
    {
          for (int j=0;j<MatrixSize ;j++)
          {
               MatrixResult[i][j]=0;
               for (int k=0;k<MatrixSize ;k++)
               {
                      MatrixResult[i][j]=MatrixResult[i][j]+MatrixA[i][k]*MatrixB[k][j];
               }
          }
    }
	return 0;
}
void FillMatrix( int** MatrixA, int** MatrixB, int length, int t)
{
	for(int row = 0; row<length-t; row++)
    {
        for(int column = 0; column<length-t; column++)
        {
           MatrixA[row][column] = rand() %5;
        }
    }
    
    for (int row = length-t; row<length; row++)
    {
    	for (int column = length-t; column<length; column++)
    	{
    		MatrixA[row][column] = 0;
		}
	}
}

2、分别画出各个实验结果的折线图,运行时间用自然对数处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值