Skip to content

Commit

Permalink
fix exception type for sparse LDLᵀ (#33372)
Browse files Browse the repository at this point in the history
* fix exception type for sparse LDLᵀ

* update tests for SingularException

* whoops, is_ll means this is Cholesky

* ZeroPivotException
  • Loading branch information
stevengj authored and andreasnoack committed Oct 2, 2019
1 parent 035acf4 commit ef0c910
Show file tree
Hide file tree
Showing 8 changed files with 37 additions and 15 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ Standard library changes

* `dot` now admits a 3-argument method `dot(x, A, y)` to compute generalized dot products `dot(x, A*y)`, but without computing and storing the intermediate result `A*y` ([#32739]).

* `ldlt` and non-pivoted `lu` now throw a new `ZeroPivotException` type ([#33372]).

#### Random

* `AbstractRNG`s now behave like scalars when used in broadcasting ([#33213]).
Expand Down
1 change: 1 addition & 0 deletions stdlib/LinearAlgebra/docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ Base.:*(::AbstractMatrix, ::AbstractMatrix)
Base.:\(::AbstractMatrix, ::AbstractVecOrMat)
LinearAlgebra.SingularException
LinearAlgebra.PosDefException
LinearAlgebra.ZeroPivotException
LinearAlgebra.dot
LinearAlgebra.cross
LinearAlgebra.factorize
Expand Down
19 changes: 18 additions & 1 deletion stdlib/LinearAlgebra/src/exceptions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
export LAPACKException,
SingularException,
PosDefException,
RankDeficientException
RankDeficientException,
ZeroPivotException

struct LAPACKException <: Exception
info::BlasInt
Expand Down Expand Up @@ -43,3 +44,19 @@ end
struct RankDeficientException <: Exception
info::BlasInt
end

"""
ZeroPivotException <: Exception
Exception thrown when a matrix factorization/solve encounters a zero in a pivot (diagonal)
position and cannot proceed. This may *not* mean that the matrix is singular:
it may be fruitful to switch to a diffent factorization such as pivoted LU
that can re-order variables to eliminate spurious zero pivots.
The `info` field indicates the location of (one of) the zero pivot(s).
"""
struct ZeroPivotException <: Exception
info::BlasInt
end
function Base.showerror(io::IO, ex::ZeroPivotException)
print(io, "ZeroPivotException: factorization encountered one or more zero pivots. Consider switching to a pivoted LU factorization.")
end
4 changes: 3 additions & 1 deletion stdlib/LinearAlgebra/src/factorization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ size(F::Adjoint{<:Any,<:Factorization}) = reverse(size(parent(F)))
size(F::Transpose{<:Any,<:Factorization}) = reverse(size(parent(F)))

checkpositivedefinite(info) = info == 0 || throw(PosDefException(info))
checknonsingular(info) = info == 0 || throw(SingularException(info))
checknonsingular(info, pivoted::Val{true}) = info == 0 || throw(SingularException(info))
checknonsingular(info, pivoted::Val{false}) = info == 0 || throw(ZeroPivotException(info))
checknonsingular(info) = checknonsingular(info, Val{true}())

"""
issuccess(F::Factorization)
Expand Down
4 changes: 2 additions & 2 deletions stdlib/LinearAlgebra/src/lu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ function generic_lufact!(A::StridedMatrix{T}, ::Val{Pivot} = Val(true);
end
end
end
check && checknonsingular(info)
check && checknonsingular(info, Val{Pivot}())
return LU{T,typeof(A)}(A, ipiv, convert(BlasInt, info))
end

Expand Down Expand Up @@ -552,7 +552,7 @@ function lu!(A::Tridiagonal{T,V}, pivot::Union{Val{false}, Val{true}} = Val(true
end
end
B = Tridiagonal{T,V}(dl, d, du, du2)
check && checknonsingular(info)
check && checknonsingular(info, pivot)
return LU{T,Tridiagonal{T,V}}(B, ipiv, convert(BlasInt, info))
end

Expand Down
8 changes: 4 additions & 4 deletions stdlib/LinearAlgebra/test/lu.jl
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,10 @@ end
@test_throws SingularException lu!(copy(A); check = true)
@test !issuccess(lu(A; check = false))
@test !issuccess(lu!(copy(A); check = false))
@test_throws SingularException lu(A, Val(false))
@test_throws SingularException lu!(copy(A), Val(false))
@test_throws SingularException lu(A, Val(false); check = true)
@test_throws SingularException lu!(copy(A), Val(false); check = true)
@test_throws ZeroPivotException lu(A, Val(false))
@test_throws ZeroPivotException lu!(copy(A), Val(false))
@test_throws ZeroPivotException lu(A, Val(false); check = true)
@test_throws ZeroPivotException lu!(copy(A), Val(false); check = true)
@test !issuccess(lu(A, Val(false); check = false))
@test !issuccess(lu!(copy(A), Val(false); check = false))
F = lu(A; check = false)
Expand Down
4 changes: 2 additions & 2 deletions stdlib/SuiteSparse/src/cholmod.jl
Original file line number Diff line number Diff line change
Expand Up @@ -746,7 +746,7 @@ function solve(sys::Integer, F::Factor{Tv}, B::Dense{Tv}) where Tv<:VTypes
if s.is_ll == 1
throw(LinearAlgebra.PosDefException(s.minor))
else
throw(ArgumentError("factorized matrix has one or more zero pivots. Try using `lu` instead."))
throw(LinearAlgebra.ZeroPivotException(s.minor))
end
end
Dense(ccall((@cholmod_name("solve"),:libcholmod), Ptr{C_Dense{Tv}},
Expand Down Expand Up @@ -1446,7 +1446,7 @@ function ldlt!(F::Factor{Tv}, A::Sparse{Tv};
# Compute the numerical factorization
factorize_p!(A, shift, F, cm)

check && (issuccess(F) || throw(LinearAlgebra.PosDefException(1)))
check && (issuccess(F) || throw(LinearAlgebra.ZeroPivotException(1)))
return F
end

Expand Down
10 changes: 5 additions & 5 deletions stdlib/SuiteSparse/test/cholmod.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ using DelimitedFiles
using Test
using Random
using Serialization
using LinearAlgebra: issuccess, PosDefException
using LinearAlgebra: issuccess, PosDefException, ZeroPivotException
using SparseArrays
using SparseArrays: getcolptr

Expand Down Expand Up @@ -384,8 +384,8 @@ end
b = fill(1., size(A1, 1))
@test_throws PosDefException cholesky(C - 2λmaxC*I)
@test_throws PosDefException cholesky(C, shift=-2λmaxC)
@test_throws PosDefException ldlt(C - C[1,1]*I)
@test_throws PosDefException ldlt(C, shift=-real(C[1,1]))
@test_throws ZeroPivotException ldlt(C - C[1,1]*I)
@test_throws ZeroPivotException ldlt(C, shift=-real(C[1,1]))
@test !isposdef(cholesky(C - 2λmaxC*I; check = false))
@test !isposdef(cholesky(C, shift=-2λmaxC; check = false))
@test !issuccess(ldlt(C - C[1,1]*I; check = false))
Expand Down Expand Up @@ -849,8 +849,8 @@ end
B = sparse(ComplexF64[0 0; 0 0])
for M in (A, B, Symmetric(A), Hermitian(B))
F = ldlt(M; check = false)
@test_throws PosDefException ldlt(M)
@test_throws PosDefException ldlt!(F, M)
@test_throws ZeroPivotException ldlt(M)
@test_throws ZeroPivotException ldlt!(F, M)
@test !issuccess(ldlt(M; check = false))
@test !issuccess(ldlt!(F, M; check = false))
end
Expand Down

0 comments on commit ef0c910

Please sign in to comment.