Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix exception type for sparse LDLᵀ #33372

Merged
merged 4 commits into from
Oct 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,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


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