lanczos算法及C++实现(三)实对称三对角阵特征值分解的分治算法
1. 基本思想
在第一篇中,我们讨论了lanczos算法的基本框架。当我们用lanczos算法将一个实对称阵转化成三对角阵之后,我们可以用第二篇中的QR算法计算三对角阵的特征值特征向量。
本篇我们将讨论计算该三对角阵更加快速的算法——分治法(Divide and Conquer),该算法最早由Cuppen于1981年提出。
给定实对称三对角阵
T=(α1β1…β1α2β2…β2α3β3……)
分治法的基本思想是将T分成两块三对角阵,求得这两块三对角阵的特征值特征向量之后,再合并,求合并之后的特征值特征向量:
分(Divide):
求^T1,^T2的特征值分解:
^T1=Q1D1QT1
^T2=Q2D2QT2
合并(Conquer)
T可以表示为:
T=(Q1Q2)(D+βzzT)(QT1QT2)
其中,D=(D1D2),zT=(qT1,qT2), qT1是Q1的最后一行, qT2是Q2的第一行
现在要求T的特征值分解,T=QΛQT,可以先求D+βzzT的特征值分解 D+βzzT=PΛPT,再令Q=(Q1Q2)P
如何求D+βzzT 的特征值分解呢?如果β=0则显然P=I。下面假设β≠0
假设λ≠0是特征值,p≠0是对应的特征向量,根据特征值定义我们有
(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)。可以证明zTp≠0。
反证法,否则(D+βzzT)p=Dp=λp,p是D的特征向量。因为D对角线元素各不相同,因此p只能有一个非0分量,而由于z所有分量非0,所以得到zTp≠0
由此我们有
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
[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,zi≠0,∀i≠j,di≠dj
任选一个i,作变量代换:
λ=di+βμ
δj=dj−diβ
这样secular方程就变为
hi(μ)=1+∑ni=jz2jδj−μ=0
这个方程有n个根,且根各不相同,按照从小到大的顺序,记这n个根为μ1<μ2<⋯<μn。
不失一般性,假设δ1<δ2<⋯<δi−1<0=δi<δi+1<⋯<δn,则有 δj<μj<δj+1, 对于j=n的情况,δn<μn<+∞=δn+1
举个例子,函数h3(μ)=1+0.1−2−μ+0.5−0.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+∑nj≠i(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+∑j≠iz2jδj+z2i+1/δ2i+11/μ−1/δi+1−z2iμ
这时,用γ=1μ带入,得到
hi(γ)≥1+∑j≠iz2jδj+z2i+1/δ2i+1γ−1/δi+1−z2iγ
令右边等于0,我们得到一个方程,通过通分,去分母,最后转成一个二次方程:
z2iγ2−(1+z2iδi+1+∑j≠iz2jδj)γ+(1+∑j≠iz2jδj)/δi+1−z2i+1δ2i+1=0
用求根公式可以得到两个解,注意定义域γi>1δi+1,因此取大根即可。
当i=n时,此时的定义域为γn>0,其实hn(γ=0)=hn(μ=∞)=1也是有定义的,而且此时γ=0是该函数的最左边的点,因此直接选取γ=0作为初始点即可。
之后牛顿迭代:
γ(k+1)=−hi(γ(k))h′i(γ(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
本系列目录:
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步