一、目的
1.熟悉算法设计的基本思想
2.掌握Strassen算法的基本思想,并且能够分析算法性能
二、内容与设计思想
- 设计一个随机数矩阵生成器,输入参数包括N, s, t;可随机生成一个大小为N*N、数值范围在[s, t]之间的矩阵。
- 编程实现普通的矩阵乘法;
- 编程实现Strassen’s algorithm;
- 在不同数据规模情况下(数据规模N=2^4, 2^8, 2^9, 2^10, 2^11)下,两种算法的运行时间各是多少;
- 思考题:修改Strassen’s algorithm,使之适应矩阵规模N不是2的幂的情况;
- 改进后的算法与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、分别画出各个实验结果的折线图,运行时间用自然对数处理