测试矩阵是否为半正定矩阵

计算科学 线性代数 特征值
2021-12-06 02:05:16

我有一个对称矩阵列表我需要检查正半定性(即它们的特征值是非负的。)L

上面的评论暗示可以通过计算各自的特征值并检查它们是否为非负数来做到这一点(也许必须注意舍入误差。)

在我的场景中计算特征值非常昂贵,但我注意到我使用的库对正定性有相当快的测试(也就是说,如果矩阵的特征值严格为正。)

因此这个想法是,给定一个矩阵,一个测试是否是正定的。如果不是,则不是半正定的,否则可以计算的特征值以确保它确实是半正定的。BLB+ϵIBB

我现在的问题是:

如果给出了正定性的有效测试,是否有更直接和有效的方法来测试矩阵是否为半正定?

3个回答

您对“半正定”或“正定”的工作定义是什么?在浮点运算中,您必须为此指定某种容差。

您可以根据矩阵的计算特征值来定义它。但是,您应该首先注意到矩阵的计算特征值与矩阵成线性比例,例如,我通过将乘以一百万的因子得到的矩阵的特征值乘以一百万。是负特征值吗如果你的矩阵的所有其他特征值都是正的并且在的数量级上,那么实际上是 0 并且不应被视为负特征值。因此,重要的是要考虑缩放。 Aλ=1.01030λ=1.0

一种合理的方法是计算矩阵的特征值,如果所有特征值都大于,其中是最大的特征值。 ϵ|λmax|λmax

不幸的是,计算矩阵的所有特征值相当耗时。另一种常用的方法是,如果矩阵在浮点算术中具有 Cholesky 分解,则认为对称矩阵是正定矩阵。计算 Cholesky 分解比计算特征值快一个数量级。您可以通过向矩阵添加一个小的单位数倍数将其扩展到正半定性。同样,存在缩放问题。一种快速的方法是对矩阵进行对称缩放,使对​​角线元素为 1.0,并在计算 Cholesky 分解之前 ϵ

不过,您应该小心这一点,因为这种方法存在一些问题。例如,在某些情况下,是正定的,因为它们具有浮点 Cholesky 因式分解,但没有 Cholesky 因式分解。因此,“浮点 Cholesky 可分解正定矩阵”的集合不是凸的! AB(A+B)/2

  • Kerr, TH,“确定性测试矩阵和产生需求的应用示例”,AIAA 指导、控制和动力学杂志,卷。10,第 5 期,第 503-506 页,1987 年 9 月至 10 月。

  • Kerr, TH,“关于正半定矩阵检验的错误陈述”,AIAA 指导、控制和动力学杂志,卷。13,第 3 期,第 571-572 页,5 月至 6 月。1990.(如在 1970 年代和 1980 年代使用反例的导航和目标跟踪软件中发生的那样)

  • Kerr, TH,“矩阵正定性/半定性计算测试中的谬误”,IEEE 航空航天和电子系统汇刊,卷。26, No. 2, pp. 415-421, Mar. 1990. [列出了作者发现在 1970 年代末和 1980 年代初美国海军潜艇导航和声纳浮标软件中经常存在的错误算法,并使用反例指出问题。 ]

Python 对于@Brian Borchers 的建议,尝试 Cholesky 分解:

from sksparse.cholmod import cholesky, CholmodNotPositiveDefiniteError
    # https://scikit-sparse.readthedocs.io/en/latest/cholmod.html

def testposdef( A, beta=1e-6, pr="" ):
    """ try cholesky( a scipy.sparse matrix  + beta I )

    Why A + beta I, beta say 1e-6 ?
    If A has tiny eigenvalues, 0 to within machine precision,
    about half of these "zeros" may be negative -- tough on solvers.
    Also the condition number improves to ~ rho(A) / beta.
    """
    try:
        solve = cholesky( A, beta=beta )  # A + beta I
        if pr:
            print( "%s + %g I is positive-definite" % (pr, beta ))
        return solve  # x = solve( b )
    except CholmodNotPositiveDefiniteError:
        if pr:
            print( "%s + %g I is not positive-definite" % (pr, beta ))
        return False