Skip to content

Commit d452174

Browse files
committed
Add check for singularity
1 parent c0cfcf5 commit d452174

File tree

3 files changed

+29
-11
lines changed

3 files changed

+29
-11
lines changed

src/ModelingToolkit.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ Base.convert(::Type{<:Array{Num}}, x::AbstractArray) = map(Num, x)
123123
Base.convert(::Type{<:Array{Num}}, x::AbstractArray{Num}) = x
124124
Base.convert(::Type{Sym}, x::Num) = value(x) isa Sym ? value(x) : error("cannot convert $x to Sym")
125125

126-
LinearAlgebra.lu(x::Array{Num}; kw...) = sym_lu(x)
126+
LinearAlgebra.lu(x::Array{Num}, ::Union{Val{false}, Val{true}}; check=true, kw...) = sym_lu(x; check=check)
127127

128128
"""
129129
$(TYPEDEF)

src/solve.jl

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,35 @@ function nterms(t)
99
end
1010
# Soft pivoted
1111
# Note: we call this function with a matrix of Union{SymbolicUtils.Symbolic, Any}
12-
# It should work as-is with Operation type too.
13-
function sym_lu(A)
12+
function sym_lu(A; check=true)
13+
SINGULAR = typemax(Int)
1414
m, n = size(A)
1515
F = map(x->x isa Num ? x : Num(x), A)
1616
minmn = min(m, n)
1717
p = Vector{BlasInt}(undef, minmn)
18-
info = zero(BlasInt)
18+
info = 0
1919
for k = 1:minmn
20-
val, i = findmin(map(ii->_iszero(F[ii, k]) ? Inf : nterms(F[ii,k]), k:n))
21-
if !(val isa Symbolic) && (val isa Number) && val == Inf && iszero(info)
20+
kp = k
21+
amin = SINGULAR
22+
for i in k:m
23+
absi = _iszero(F[i, k]) ? SINGULAR : nterms(F[i,k])
24+
if absi < amin
25+
kp = i
26+
amin = absi
27+
end
28+
end
29+
30+
p[k] = kp
31+
32+
if amin == SINGULAR && !(amin isa Symbolic) && (amin isa Number) && iszero(info)
2233
info = k
2334
end
24-
i += k - 1
35+
2536
# swap
2637
for j in 1:n
27-
F[k, j], F[i, j] = F[i, j], F[k, j]
38+
F[k, j], F[kp, j] = F[kp, j], F[k, j]
2839
end
29-
p[k] = i
40+
3041
for i in k+1:m
3142
F[i, k] = F[i, k] / F[k, k]
3243
end
@@ -36,7 +47,8 @@ function sym_lu(A)
3647
end
3748
end
3849
end
39-
LU(F, p, info)
50+
check && LinearAlgebra.checknonsingular(info, Val{true}())
51+
LU(F, p, convert(BlasInt, info))
4052
end
4153

4254
# Given a vector of equations and a

test/operation_overloads.jl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,19 @@ aa = a; # old a
2121
X = [0 b c; d e f; g h i]
2222
@test iszero(simplify(det(X) - ((b * f * g) + (c * d * h) - (b * d * i) - (c * e * g)), polynorm=true))
2323
F = lu(X)
24+
@test F.p == [2, 1, 3]
2425
R = simplify.(F.L * F.U - X[F.p, :], polynorm=true)
2526
@test iszero(R)
26-
@test simplify.(F \ X, polynorm=true) == I
27+
@test simplify.(F \ X) == I
2728
@test ModelingToolkit._solve(X, X) == I
2829
inv(X)
2930
qr(X)
3031

32+
X2 = [0 b c; 0 0 0; 0 h 0]
33+
@test_throws SingularException lu(X2)
34+
F2 = lu(X2, check=false)
35+
@test F2.info == 1
36+
3137
# test operations with sparse arrays and Operations
3238
# note `isequal` instead of `==` because `==` would give another Operation
3339

0 commit comments

Comments
 (0)