您的位置:首页 > 其它

矩阵相乘的三种实现

2013-02-13 18:30 471 查看
对于两个N阶矩阵的乘法,可以使用蛮力法,三层循环即可实现,也可以使用分治法实现。

原数据结构:

public class Matrix
{
public Matrix(int N)
{
this.n = N;
m = new int[n, n];
sx = 0;
sy = 0;
ex = N - 1;
ey = N - 1;
}
public int[,] m;
public int n;
//position.start and end coordinate
public int sx;
public int sy;
public int ex;
public int ey;

public void init()
{
Random r = new Random();
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
m[i, j] = r.Next(n);
}
}

}
}


三层循环:

public static Matrix SquareMatrixMultiply(Matrix a, Matrix b)
{
int tmp = 0, n;
n = a.n;
Matrix c = new Matrix(n);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
for (int k = 0; k < n; k++)
{
tmp += a.m[i,k] * b.m[k,j];
}
c.m[i,j] = tmp;
tmp = 0;
}
}

return c;
}


分治法:

public static Matrix SquareMatrixMultiplyRecursive(Matrix a, Matrix b)
{
int n = a.n;
Matrix c = new Matrix(n);
if (n == 1)
{
//c.m[a.sx, b.sy] += a.m[a.sx, a.sy] * b.m[b.sx, b.sy];
c.m[0, 0] = a.m[0, 0] * b.m[0, 0];
}
else
{
Matrix suba,subb;
int[] ta1 = new int[4] { 0, 0, 2, 2 };
int[] ta2 = new int[4] { 1, 1, 3, 3 };
int[] tb1 = new int[4] { 0, 1, 0, 1 };
int[] tb2 = new int[4] { 2, 3, 2, 3 };
for (int i = 0; i < 4; i++)
{
suba = partitionArray(ta1[i], a);
subb = partitionArray(tb1[i], b);

Matrix c1 = SquareMatrixMultiplyRecursive(suba, subb);
suba = partitionArray(ta2[i], a);
subb = partitionArray(tb2[i], b);
Matrix c2 = SquareMatrixMultiplyRecursive(suba, subb);
Plus(c, c1, c2, i);
}

}
return c;
}

Strassen

public static Matrix SquareMatrixMultiplyStrassen(Matrix a, Matrix b)
{
int N = a.n;
Matrix c = new Matrix(N);

if (N <= 1)
{
c.m[a.sx, b.sy] = a.m[a.sx, a.sy] * b.m[b.sx, b.sy];
//c.m[0, 0] = a.m[0, 0] * b.m[0, 0];
}
else
{
Dictionary<string, Matrix> ms = new Dictionary<string, Matrix>();
//s1~s10
string[] sa = { "S2", "S3", "S5", "S7", "S9" };
string[] sb = { "S1", "S4", "S6", "S8", "S10" };
int[] sa1 = { 0, 2, 0, 1, 0 };
int[] sa2 = { 1, 3, 3, 3, 2 };
bool[] sa3 = { true, true, true, false, false };

int[] sb1 = { 1, 2, 0, 2, 0 };
int[] sb2 = { 3, 0, 3, 3, 2 };
bool[] sb3 = { false, false, true, true, true };
Matrix tmp = null, sub1 = null, sub2 = null;
for (int i = 0; i < 5; i++)
{
sub1 = PartitionArrayByCalcuIndex(sa1[i], a);
sub2 = PartitionArrayByCalcuIndex(sa2[i], a);
tmp = AddMinus(sub1, sub2, sa3[i]);
ms.Add(sa[i], tmp);

sub1 = PartitionArrayByCalcuIndex(sb1[i], b);
sub2 = PartitionArrayByCalcuIndex(sb2[i], b);
tmp = AddMinus(sub1, sub2, sb3[i]);
ms.Add(sb[i], tmp);
}
string[] sp1 = { "A0", "S2", "S3", "A3", "S5", "S7", "S9" };
string[] sp2 = { "S1", "B3", "B0", "S4", "S6", "S8", "S10" };

for (int i = 0; i < sp1.Length; i++)
{
string name = "P" + (i+1);
sub1 = getMBy(sp1[i], a, b, ms);
sub2 = getMBy(sp2[i], a, b, ms);
ms.Add(name, SquareMatrixMultiplyStrassen(sub1, sub2));
}
sub1 = ms["P5"].Add(ms["P4"]).Minus(ms["P2"]).Add(ms["P6"]);
c.Add(sub1);
sub1 = ms["P1"].Minus(ms["P2"]);
c.Add(sub1);
sub1 = ms["P3"].Add(ms["P4"]);
c.Add(sub1);
sub1 = ms["P5"].Add(ms["P1"]).Minus(ms["P3"]).Minus(ms["P7"]);
c.Add(sub1);
}
return c;


主方法:

class Program
{
static void Main(string[] args)
{
const int N = 8;
//a
Matrix a = new Matrix(N);
a.init();

Operation.ShowMatrix(a,"a");
//b
Matrix b = new Matrix(N);
b.init();
Operation.ShowMatrix(b, "b");
//c
Matrix c = Operation.SquareMatrixMultiply(a, b);
Operation.ShowMatrix(c,"c brute-force method");
//d
Matrix d = Operation.SquareMatrixMultiplyRecursive(a, b);
Operation.ShowMatrix(d,"d divide and conquer");
//e
Matrix e = Operation.SquareMatrixMultiplyStrassen(a, b);
Operation.ShowMatrix(e, "e Strassen");
}
}


实现界面:



本次实现使用花费时间和空间较多的数组内容拷贝,并没有实现索引计算。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: