分治

分(divide):递归解决较小的问题

治(conquer):从子问题的解构建原问题的解

一般认为正文中至少含有两个递归调用才叫分治,只包含一个递归的不叫分治。一般认为子问题是不相交的。

方程的解为:

整数相乘

求两个N位数X和Y的乘积,手算需要进行次乘法,即把两个个位数相乘看作基本操作的话,算法复杂度为。X=12345678,Y=87654321,求XY。XL=1234,XR=5678,YL=8765,YR=4321。X=XL104+XR,Y=YL104+YR

所以:

需要进行4次4位数的乘法,乘以108只是一些补0操作,再加上几次加法构成了

由(1)式得,此时算法没有得到改进。

注意到,所以在计算出后,只需要再进行一次乘法就能计算出

当两个数都是1位时可以通过查表进行乘法。

实际上上述方法在实际中很少用,对于小的N开销大,对于大的N还存在更好的一些算法,它们也广泛利用了分治算法。

矩阵乘法

一个N×N的矩阵乘法变成了8个N/2×N/2的矩阵乘法和4个N/2×N/2的矩阵加法,加法的复杂度为

由(1)式得

看来矩阵分块后再进行乘积并没带来复杂度的降低。

Strassen使用了类似于整数乘法的分治策略。

  计算7个N/2×N/2阶矩阵的乘法

\mathbf{M}_{1} := (\mathbf{A}_{1,1} + \mathbf{A}_{2,2}) (\mathbf{B}_{1,1} + \mathbf{B}_{2,2})
\mathbf{M}_{2} := (\mathbf{A}_{2,1} + \mathbf{A}_{2,2}) \mathbf{B}_{1,1}
\mathbf{M}_{3} := \mathbf{A}_{1,1} (\mathbf{B}_{1,2} - \mathbf{B}_{2,2})
\mathbf{M}_{4} := \mathbf{A}_{2,2} (\mathbf{B}_{2,1} - \mathbf{B}_{1,1})
\mathbf{M}_{5} := (\mathbf{A}_{1,1} + \mathbf{A}_{1,2}) \mathbf{B}_{2,2}
\mathbf{M}_{6} := (\mathbf{A}_{2,1} - \mathbf{A}_{1,1}) (\mathbf{B}_{1,1} + \mathbf{B}_{1,2})
\mathbf{M}_{7} := (\mathbf{A}_{1,2} - \mathbf{A}_{2,2}) (\mathbf{B}_{2,1} + \mathbf{B}_{2,2})
然后
\mathbf{C}_{1,1} = \mathbf{M}_{1} + \mathbf{M}_{4} - \mathbf{M}_{5} + \mathbf{M}_{7}
\mathbf{C}_{1,2} = \mathbf{M}_{3} + \mathbf{M}_{5}
\mathbf{C}_{2,1} = \mathbf{M}_{2} + \mathbf{M}_{4}
\mathbf{C}_{2,2} = \mathbf{M}_{1} - \mathbf{M}_{2} + \mathbf{M}_{3} + \mathbf{M}_{6}

由(1)式得

当然要考虑N不是2的整次幂的情况。在N不是很大时Strassen算法不如矩阵直接相乘,它也不能推广到稀疏矩阵,而且不易并行化。当用浮点项运算时,在数值上不如经典算法稳定。算法稳定性是指:舍入误差在算法计算过程中是可控的。

 

posted @ 2012-09-07 19:12  张朝阳  阅读(1519)  评论(2编辑  收藏  举报