划分和征服矩阵乘法

时间:2011-01-31 01:40:22

标签: algorithm math matrix multiplication

我遇到分歧并征服矩阵乘法工作。根据我的理解,你将大小为nxn的矩阵分成象限(每个象限是n / 2),然后你做:

C11 = A11⋅ B11 + A12 ⋅ B21   
C12 = A11⋅ B12 + A12 ⋅ B22  
C21 = A21 ⋅ B11 + A22 ⋅ B21  
C22 = A21 ⋅ B12 + A22 ⋅ B22  

我的分而治之的输出真的很大,我在找出问题时遇到了麻烦,因为我对递归并不是很好。

示例输出:

原始矩阵A:

4 0 4 3   
5 4 0 4   
4 0 4 0  
4 1 1 1 

A x A

古典:

44 3 35 15  
56 20 24 35  
32 0 32 12  
29 5 21 17  

分而治之:

992 24 632 408  
1600 272 720 1232   
512 0 512 384  
460 17 405 497  

有人可以告诉我,我为分而治之做错了吗?我的所有矩阵都是int[][],经典方法是传统的3循环矩阵乘法

4 个答案:

答案 0 :(得分:5)

您以错误的方式递归调用divideAndConquer。你的函数做的是对矩阵进行平方。为了使分割和征服矩阵乘法起作用,它需要能够将两个可能不同的矩阵相乘。

看起来应该是这样的:

private static int[][] divideAndConquer(int[][] matrixA, int[][] matrixB){
    if (matrixA.length == 2){
         //calculate and return base case
    }
    else {
        //make a11, b11, a12, b12 etc. by dividing a and b into quarters      
        int[][] c11 = addMatrix(divideAndConquer(a11,b11),divideAndConquer(a12,b21));
        int[][] c12 = addMatrix(divideAndConquer(a11,b12),divideAndConquer(a12,b22));
        int[][] c21 = addMatrix(divideAndConquer(a21,b11),divideAndConquer(a22,b21));
        int[][] c22 = addMatrix(divideAndConquer(a21,b12),divideAndConquer(a22,b22));
        //combine result quarters into one result matrix and return
    }
}

答案 1 :(得分:2)

尝试一些调试方法:

  • 尝试一些非常简单的测试矩阵作为输入(例如全零,具有一个或几个战略矩阵)。您可能会在“失败”中看到一个模式,它会显示您的错误所在。

  • 确保您的“经典”方法能够为您提供正确的答案。对于小型矩阵,您可以在线使用Woflram Alpha来测试答案:http://www.wolframalpha.com/examples/Matrices.html

  • 调试递归:在函数的入口和出口添加printf()语句,包括调用参数。运行测试矩阵,将输出写入日志文件,然后使用文本编辑器打开日志文件。逐步完成每个案例,在编辑器中编写注释,确保它在每一步都正常工作。添加更多printf()语句,并在需要时再次运行。

祝你好运!

答案 2 :(得分:2)

  

有人能告诉我,我为分而治之做错了吗?

是:

   int[][] a = divideAndConquer(topLeft);
   int[][] b = divideAndConquer(topRight);
   int[][] c = divideAndConquer(bottomLeft);
   int[][] d = divideAndConquer(bottomRight);

   int[][] c11 = addMatrix(classical(a,a),classical(b,c));
   int[][] c12 = addMatrix(classical(a,b),classical(b,d));
   int[][] c21 = addMatrix(classical(c,a),classical(d,c));
   int[][] c22 = addMatrix(classical(c,b),classical(d,d));

您将在此处执行额外的乘法步骤:您不应同时调用divideAndConquer()classical()

你实际做的是:

C11 = (A11^2)⋅(B11^2) + (A12^2)⋅(B21^2)
C12 = (A11^2)⋅(B12^2) + (A12^2)⋅(B22^2)
C21 = (A21^2)⋅(B11^2) + (A22^2)⋅(B21^2)
C22 = (A21^2)⋅(B12^2) + (A22^2)⋅(B22^2)

这是不正确的。

  1. 首先,删除divideAndConquer()次来电,然后用topLeft / topRight / etc替换/ b / c / d。 看看它是否能给你正确的结果。

  2. 您的divideAndConquer()方法需要一对输入参数,因此您可以使用A * B.完成后,请拨打classical()的电话,然后使用divideAndConquer()。 (或将它们保存为长度不是2的倍数的矩阵。)

答案 3 :(得分:1)

您可能会发现Strassen's algorithm上的Wiki文章很有帮助。