Symbolics.jl icon indicating copy to clipboard operation
Symbolics.jl copied to clipboard

Rogue `true` in inverse of a matrix

Open dpsanders opened this issue 4 years ago • 10 comments

julia> @variables a, b, c, d
(a, b, c, d)

julia> A = [a b; c d]
2×2 Matrix{Num}:
 a  b
 c  d

julia> inv(A)
2×2 Matrix{Num}:
                       (a^-1)*(true + (b*c*(a^-1)*((d - (b*c*(a^-1)))^-1)))  …  -b*(a^-1)*((d - (b*c*(a^-1)))^-1)
 -c*(a^-1)*((d - (b*c*(a^-1)))^-1)                                                          (d - (b*c*(a^-1)))^-1

Note the truein A[1, 1].

┆Issue is synchronized with this Trello card by Unito

dpsanders avatar Mar 01 '21 16:03 dpsanders

It does equal to d/det(A) so at least it's not wrong :-). We might want to special case small inverses.

YingboMa avatar Mar 02 '21 17:03 YingboMa

Maybe it should be returned in the form(1 / det(A)) * adj(A) with the det factored out?

dpsanders avatar Mar 02 '21 21:03 dpsanders

In Julia v1.7 this has a nasty side effect:

julia> inv(A)
ERROR: MethodError: no method matching checknonsingular(::Int64, ::Val{true})
Closest candidates are:
  checknonsingular(::Any) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.7/LinearAlgebra/src/factorization.jl:21
  checknonsingular(::Any, ::LinearAlgebra.RowMaximum) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.7/LinearAlgebra/src/factorization.jl:19
  checknonsingular(::Any, ::LinearAlgebra.NoPivot) at /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.7/LinearAlgebra/src/factorization.jl:20
Stacktrace:
 [1] sym_lu(A::Matrix{Num}; check::Bool)
   @ Symbolics ~/.julia/packages/Symbolics/1TCCw/src/linear_algebra.jl:49
 [2] #lu#25
   @ ~/.julia/packages/Symbolics/1TCCw/src/num.jl:174 [inlined]
 [3] lu
   @ ~/.julia/packages/Symbolics/1TCCw/src/num.jl:174 [inlined]
 [4] inv(A::Matrix{Num})
   @ LinearAlgebra /Users/julia/buildbot/worker/package_macos64/build/usr/share/julia/stdlib/v1.7/LinearAlgebra/src/dense.jl:874
 [5] top-level scope
   @ REPL[7]:1

(Julia v1.7.0-beta3.0, SymbolicUtils v0.13.4, Symbolics v3.2.0)

michakraus avatar Aug 23 '21 10:08 michakraus

Yeah that's not good. @YingboMa you got this one?

ChrisRackauckas avatar Aug 23 '21 10:08 ChrisRackauckas

That's not related to this issue. Could you open another issue?

YingboMa avatar Aug 24 '21 14:08 YingboMa

Is it not? As far as I can see, the problem comes from checknonsingular being called on the true that appears in the expression of the inverse, which maybe shouldn't be there in the first place?

michakraus avatar Aug 24 '21 14:08 michakraus

That true is not related to this at all.

YingboMa avatar Aug 24 '21 14:08 YingboMa

Ok, then I'll open another issue (#357).

michakraus avatar Aug 24 '21 14:08 michakraus

I just had this issue, and in my case I have an upper triangular 2x2-matrix A for which inv seems to compute ldiv!(A, Matrix{Num}(I, (2, 2))). The type of I is UniformScaling{Bool} and I get the result I expect by using 1.0*I instead of I to replace the UniformScaling{Bool} by a UniformScaling{Float64}.

The code in triangular.jl from the LinearAlgebra stdlib calls (in this case)

Matrix{Num}(I, (2, 2))

which becomes a matrix containing true due to Num(true) evaluating to a value true.

I suggest that Num(true) should return one(Num) which is a "1" of some form instead of a symbolic expression with the content true.

Is there a reason to want to treat symbolic boolean expressions at all, such as piecewise defined functions?

I expect that the standard library calls Matrix{Num}(I, (2, 2)) with the expectation that it return a value with ones along the diagonal, and I would therefore expect Num(true) should return a value that represents the value 1 more clearly than true does.

Johan-Gronqvist avatar Aug 10 '22 14:08 Johan-Gronqvist

This seems to give me the behaviour I want, in the case I am looking at now:

import Symbolics: Num
Num(b :: Bool) = ifelse(b, one(Num), zero(Num))

Johan-Gronqvist avatar Aug 10 '22 15:08 Johan-Gronqvist

Does this get some improvement? Currently result of inverse matrix is basically unreadable.

PhyX-Meow avatar Oct 29 '22 04:10 PhyX-Meow

Does this get some improvement? Currently result of inverse matrix is basically unreadable.

Unfortunately no. See this related issue https://github.com/JuliaSymbolics/Symbolics.jl/issues/693.

bowenszhu avatar Oct 29 '22 04:10 bowenszhu