算法分析(4)——详解矩阵乘法中的Strassen算法

2,320 阅读2分钟

一、矩阵乘法

学过线性代数的都会接触到矩阵乘法这一概念,所谓矩阵乘法(matrix multiplication),就是A矩阵的行向量·B矩阵的列向量得到结果矩阵C的对应位置上的元素。

假设A为mp的矩阵,B为pn的矩阵,那么称m*n的矩阵C为A和B的乘积,记为C=AB。其中C的第i行第j列元素可以表示为:

假如在矩阵A和矩阵B中,m=p=n=N ,那么完成 C=AB需要多少次乘法呢?

这个算法的伪代码如下:

这样也可以清楚的看出这个算法的时间复杂度是Θ(n3)(三层循环)。

二、递归思想的引入

上述方法是最直接的算法,接下来分析一种递归算法(SQUARE-MATRIX-MULTIPLY-RECURSIVE),看一下时间复杂度会不会改进。

对于上面的过程,我们可以用一种递归算法计算,让我们来分析下:

假设A和B都是N*N的方矩阵,求C=AB,如下图:

其中:

伪代码如下(递归计算):

从上述公式我们可以得出,计算2个nn的矩阵需要4个(n/2)(n/2)的矩阵相乘8次,再相加4次。所以,时间复杂度T(n)可以得到:

O(n2)表示4次矩阵相加的时间复杂度及合并C的时间复杂度4O(n2)+O(n2)=5O(n2)

忽略常数因子,可视为O(n2),所以

可以看到,时间复杂度其实并没有优化。接下来就该说说Volker Strassen这个人的牛逼了

三、Strassen算法

1969年Volker Strassen这个人提出了一个非常牛逼的算法——Strassen算法,它将矩阵的时间复杂度从变为了。它证明了矩阵乘法存在时间复杂度低于O(n3)的算法。

Strassen算法的实现步骤(看着有点玄学,具体推导步骤太过复杂玄学):

  1. 按上述的递归思想,将A,B,C分解(因为是按照索引分解,所以时间复杂度为O(1))。
  2. 创建10个(n/2)×(n/2)的矩阵S1,S2,S3,…,S10(花费时间O(n2))。
  3. 递归计算7个矩阵积P1,P2,…,p7,每个矩阵都是(n/2)×(n/2)的。
  4. 通过Pi计算C11,C12,C21,C22,花费时间O(n2)

综合得出如下递归式:

所以,时间复杂度为: