Loading [MathJax]/jax/output/CommonHTML/jax.js

lanczos算法及C++实现(三)实对称三对角阵特征值分解的分治算法

1. 基本思想

第一篇中,我们讨论了lanczos算法的基本框架。当我们用lanczos算法将一个实对称阵转化成三对角阵之后,我们可以用第二篇中的QR算法计算三对角阵的特征值特征向量。

本篇我们将讨论计算该三对角阵更加快速的算法——分治法(Divide and Conquer),该算法最早由Cuppen于1981年提出。

 

给定实对称三对角阵

T=(α1β1β1α2β2β2α3β3)

分治法的基本思想是将T分成两块三对角阵,求得这两块三对角阵的特征值特征向量之后,再合并,求合并之后的特征值特征向量:

分(Divide):

Block diagonal plus correction.png

^T1,^T2的特征值分解:

^T1=Q1D1QT1

^T2=Q2D2QT2

合并(Conquer)

T可以表示为:

T=(Q1Q2)(D+βzzT)(QT1QT2) 

其中,D=(D1D2),zT=(qT1,qT2), qT1Q1的最后一行, qT2Q2的第一行

 

现在要求T的特征值分解,T=QΛQT,可以先求D+βzzT的特征值分解 D+βzzT=PΛPT,再令Q=(Q1Q2)P

 

如何求D+βzzT 的特征值分解呢?如果β=0则显然P=I。下面假设β0

假设λ0是特征值,p0是对应的特征向量,根据特征值定义我们有

(D+βzzT)p=λp

(DλI)p+βzzTp=0

p+(DλI)1βzzTp=0

zTp+zT(DλI)1βzzTp=0

假如D所有对角线元素各不相同,并且z的所有元素不为0 (这两个假设来自wiki,但是感觉没什么道理,anyway先pass)。可以证明zTp0

反证法,否则(D+βzzT)p=Dp=λp,p是D的特征向量。因为D对角线元素各不相同,因此p只能有一个非0分量,而由于z所有分量非0,所以得到zTp0

由此我们有

1+βzT(DλI)1z=0

或者写成如下形式:

1+βiz2idiλ=0

其中di=Dii

因此求特征值问题最后归结为求解一个方程的根。这个方程被称为"Secular Equation"。 该方程的解法下面会详细讨论,这里略过。得到特征值之后,根据 上面第二行 (DλI)p+βzzTp=0,可以得出(DλI)1z是特征值λ对应的特征向量。

至此我们得到了分治法的框架,总结如下:

[Q,D] = DivideAndConquer(T)
//输入T实对称三对角阵,输出T的特征值分解T=Q D Q',Q为正交阵,每列为T的特征向量,D为对角阵,对角线元素为T的特征值
if T is 1x1 matrix
         Q=1, D=T
else
         Divide
                  Block diagonal plus correction.png
         [Q1,D1]=DivideAndConquer(^T1)
         [Q2,D2]=DivideAndConquer(^T2)
         let D=(D1D2),zT=(qT1,qT2),Q1
的最后一行和Q2的第一行拼接成的向量
         Find eigen values λ=[λ1,λ2]T
of D+βzzT by solving Secular Equation
                  1+βiz2idiλ=0
         Calculate corresponding eigen vectors
                  pi=(DλiI)1z
         Update eigen vectors of T:
                 Q=(Q1Q2)P
        where P=[p1,p2,]
        return D=diag(λ), Q
end

2. Secular Equation的解法

这节讨论secular方程1+βni=1z2idiλ=0的解法,这里假设i,zi0,ij,didj

任选一个i,作变量代换:

λ=di+βμ

δj=djdiβ

这样secular方程就变为

hi(μ)=1+ni=jz2jδjμ=0

这个方程有n个根,且根各不相同,按照从小到大的顺序,记这n个根为μ1<μ2<<μn

不失一般性,假设δ1<δ2<<δi1<0=δi<δi+1<<δn,则有 δj<μj<δj+1, 对于j=n的情况,δn<μn<+=δn+1

举个例子,函数h3(μ)=1+0.12μ+0.50.5μ+0.2μ+0.21μ+0.42μ的图像如下

可以看到0<μi<δi+1, 我们可以在区间(0,δi+1)内求解第i个根。我们把这个区间放大,得到如下图像。

可以看到这段区间内,函数h单调增,与x轴有1个交点。如何求这个点呢,最简单的是2分法,可以在log时间内收敛。

更快的是牛顿迭代法。但是这里注意一个问题,就是如果初始点选的不好,牛顿法会发散,找不到根。如何保证牛顿法收敛呢?这里我们需要对变量作一个替换,

γ=1μ

这样,原来的定义域0<μi<δi+1就变成了γi>1δi+1,对于i=n的情况,γn>0

现在我们看一下新的函数hi(γ)在区间(1δi+1,)上的图像.

可见,在区间(1,)上,函数hi(γ)单调递减。假设hi(γ)的根为γ,论文Numerical solution of a secular equation证明了,如果初始点选在γ的左侧,则牛顿法必定收敛。换句话说,如果初始点γ满足hi(γ)>0,则用牛顿法得到的γ序列收敛到γ

如何找这个初始点呢?论文Numerical solution of a secular equation构造了hi(γ)的一个下界函数gi(γ)hi(γ),通过求解gi(γ)=0得到根γ,则有0=gi(γ)hi(γ),从而求得初始点。

现在我们推出这个下界函数。先讨论i<n的情况,然后讨论i=n的情况。

我们直接通过函数hi(μ)来推出下界函数。根据前面所述,

hi(μ)=1+ni=jz2jδjμ

=1+nji(z2jδj+z2j/δ2j1/μ1/δj)z2iμ

=1+nj<i(z2jδj+z2j/δ2j1/μ1/δj)+nj>i+1(z2jδj+z2j/δ2j1/μ1/δj)z2iμ+z2i+1δi+1+z2i+1/δ2i+11/μ1/δi+1

当j<i时,δj<0,因此1/μ1/δj>0

当j>i时,μ<δj,同样有1/μ1/δj>0

所以

hi(μ)1+jiz2jδj+z2i+1/δ2i+11/μ1/δi+1z2iμ

这时,用γ=1μ带入,得到

hi(γ)1+jiz2jδj+z2i+1/δ2i+1γ1/δi+1z2iγ

令右边等于0,我们得到一个方程,通过通分,去分母,最后转成一个二次方程:

z2iγ2(1+z2iδi+1+jiz2jδj)γ+(1+jiz2jδj)/δi+1z2i+1δ2i+1=0

用求根公式可以得到两个解,注意定义域γi>1δi+1,因此取大根即可。

当i=n时,此时的定义域为γn>0,其实hn(γ=0)=hn(μ=)=1也是有定义的,而且此时γ=0是该函数的最左边的点,因此直接选取γ=0作为初始点即可。

之后牛顿迭代:

γ(k+1)=hi(γ(k))hi(γ(k))+γ(k)

一般两到三次迭代即可收敛,可以认为是O(1) 时间。

这里只讨论了分治算法最基本的实现,论文A Serial Implementation of Cuppen's Divide and Conquer Algorithm for the Symmetric Eigenvalue Problem还提到了用deflation加速,此外分治算法还有稳定性等问题。这里就不详细探讨了。

3. 参考文献

https://en.wikipedia.org/wiki/Divide-and-conquer_eigenvalue_algorithm

A. Melman Numerical solution of a secular equation

J Rutter A Serial Implementation of Cuppen's Divide and Conquer Algorithm for the Symmetric Eigenvalue Problem  Chapter 3。本文的一些插图来自这篇文章。

 

本文属作者原创,转载请注明出处

http://www.cnblogs.com/qxred/p/dcalgorithm.html

本系列目录:

lanczos算法及C++实现(〇)C++代码

lanczos算法及C++实现(一)框架及简单实现

lanczos算法及C++实现(二)实对称阵奇异值分解的QR算法

lanczos算法及C++实现(三)实对称三对角阵特征值分解的分治算法

posted @   qxred  阅读(6412)  评论(5编辑  收藏  举报
点击右上角即可分享
微信分享提示