Skip to content

Commit dc7a1bb

Browse files
committed
early failure on bad factorization
1 parent 8d6494c commit dc7a1bb

File tree

3 files changed

+31
-14
lines changed

3 files changed

+31
-14
lines changed

src/LinearSolve.jl

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -134,26 +134,33 @@ include("extension_algs.jl")
134134
include("adjoint.jl")
135135
include("deprecated.jl")
136136

137+
@inline function _issucess(F::LinearAlgebra.QRCompactWY)
138+
(m, n) = size(F)
139+
U = view(F.factors, 1:min(m, n), 1:n)
140+
return any(iszero, Iterators.reverse(@view U[diagind(U)]))
141+
end
142+
@inline _issucess(F) = hasmethod(LinearAlgebra.issuccess, (typeof(F),)) ?
143+
LinearAlgebra.issuccess(F) : true
144+
137145
@generated function SciMLBase.solve!(cache::LinearCache, alg::AbstractFactorization;
138146
kwargs...)
139147
quote
140148
if cache.isfresh
141149
fact = do_factorization(alg, cache.A, cache.b, cache.u)
142150
cache.cacheval = fact
151+
152+
# If factorization was not successful, return failure. Don't reset `isfresh`
153+
if _issucess(fact)
154+
return SciMLBase.build_linear_solution(
155+
alg, cache.u, nothing, cache; retcode = ReturnCode.Failure)
156+
end
157+
143158
cache.isfresh = false
144159
end
160+
145161
y = _ldiv!(cache.u, @get_cacheval(cache, $(Meta.quot(defaultalg_symbol(alg)))),
146162
cache.b)
147-
148-
#=
149-
retcode = if LinearAlgebra.issuccess(fact)
150-
SciMLBase.ReturnCode.Success
151-
else
152-
SciMLBase.ReturnCode.Failure
153-
end
154-
SciMLBase.build_linear_solution(alg, y, nothing, cache; retcode = retcode)
155-
=#
156-
SciMLBase.build_linear_solution(alg, y, nothing, cache)
163+
return SciMLBase.build_linear_solution(alg, y, nothing, cache)
157164
end
158165
end
159166

src/default.jl

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,19 @@ function defaultalg(A, b, assump::OperatorAssumptions{Bool})
216216
elseif assump.condition === OperatorCondition.WellConditioned
217217
DefaultAlgorithmChoice.NormalCholeskyFactorization
218218
elseif assump.condition === OperatorCondition.IllConditioned
219-
DefaultAlgorithmChoice.QRFactorizationPivoted
219+
if is_underdetermined(A)
220+
# Underdetermined
221+
DefaultAlgorithmChoice.QRFactorizationPivoted
222+
else
223+
DefaultAlgorithmChoice.QRFactorization
224+
end
220225
elseif assump.condition === OperatorCondition.VeryIllConditioned
221-
DefaultAlgorithmChoice.QRFactorizationPivoted
226+
if is_underdetermined(A)
227+
# Underdetermined
228+
DefaultAlgorithmChoice.QRFactorizationPivoted
229+
else
230+
DefaultAlgorithmChoice.QRFactorization
231+
end
222232
elseif assump.condition === OperatorCondition.SuperIllConditioned
223233
DefaultAlgorithmChoice.SVDFactorization
224234
else

test/default_algs.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ b = [1.0, 0.0, 0.0]
121121
prob = LinearProblem(A, b)
122122
sol = solve(prob)
123123

124-
@test sol.u [0.4, 0.2]
124+
@test !SciMLBase.successful_retcode(sol.retcode)
125125

126126
## Show that we cannot select a default alg once by checking the rank, since it might change
127127
## later in the cache
@@ -143,4 +143,4 @@ cache.A = [2.0 1.0
143143

144144
sol = solve!(cache)
145145

146-
@test sol.u [0.4, 0.2]
146+
@test !SciMLBase.successful_retcode(sol.retcode)

0 commit comments

Comments
 (0)