Skip to content

Necessity of the hard symmetry/hermiticity checks in eigh(!) decompositions #76

@leburgel

Description

@leburgel

When using the Hermitian eigenvalue decompositions eigh_full and eigh_trunc, I've run into the practical issue that I almost always have to manuall 'resymmetrize' my input matrix in order to be able to use these decompositions. If I don't do this, numerical inaccuracies always trigger the input checks in the implementation of the LAPACK wrappers. There's currently no way of using the Hermitian decompositions 'at my own risk' for not entirely Hermitian objects. This is quite different behavior from the LinearAlgebra.LAPACK routines, where there's no such strict input checking.

For example, I think it would not be unreasonable to use the Hermitian decompositions on objects of the kind:

using LinearAlgebra
using MatrixAlgebraKit

a = randn(ComplexF64, 10, 10)
a = (a + a') / 2
ap = a + 1e-14 * norm(a, Inf) * randn(eltype(a), size(a)...) # perturb slightly
@show ishermitian(ap) # false
@show norm(ap - ap') # very small

However, eigh_full using a divide and conquer (or any other) algorithm just errors out inYALAPACK.heevd!

alg = LAPACK_DivideAndConquer()
D, V = eigh_full(ap, alg)
Stacktrace:
 [1] heevd!(A::Matrix{ComplexF64}, W::Vector{Float64}, V::Matrix{ComplexF64}; uplo::Char)
   @ MatrixAlgebraKit.YALAPACK ~/.julia/packages/MatrixAlgebraKit/xv5dv/src/yalapack.jl:1300
 [2] heevd!
   @ ~/.julia/packages/MatrixAlgebraKit/xv5dv/src/yalapack.jl:1288 [inlined]
 [3] eigh_full!
   @ ~/.julia/packages/MatrixAlgebraKit/xv5dv/src/implementations/eigh.jl:86 [inlined]
 [4] eigh_full!(A::Matrix{ComplexF64}, alg::LAPACK_DivideAndConquer{@NamedTuple{}})
   @ MatrixAlgebraKit ~/.julia/packages/MatrixAlgebraKit/xv5dv/src/algorithms.jl:244
 [5] eigh_full(A::Matrix{ComplexF64}, alg::LAPACK_DivideAndConquer{@NamedTuple{}})
   @ MatrixAlgebraKit ~/.julia/packages/MatrixAlgebraKit/xv5dv/src/algorithms.jl:234
 [6] top-level scope
   @ REPL[84]:1

At the same time, I can use the routines from LinearAlgebra.LAPACK just fine on this kind of object,

D, V = LAPACK.syevd!('V', 'U', copy(ap)))
D
10-element Vector{Float64}:
 -3.407857755214439
 -2.387292210584882
 -1.45936482040303
 -0.68936395419045
 -0.21846056222030638
  0.6404302497673092
  1.5579324860696977
  2.3320360765034693
  3.2679939158673332
  3.650456704365599

Would it be reasonable to either remove these input checks, make them less strict by checking with respect to some tolerance, or at the very least replace the error with a warning so people know that what they're doing might not be technically correct and they acting at their own risk?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions