Symbolics.jl
Symbolics.jl copied to clipboard
Small inconsistencies
Working with Symbolics.jl, I came accross to the following small inconsistency (see the true
value in the (1,2) element):
julia> F
2×2 Matrix{Num}:
0.0 1.0
-1.0 - 10.0cos(t) -24.0 - 19.0sin(t)
julia> inv(F)
2×2 Matrix{Num}:
(24.0 + 19.0sin(t)) / (-1.0 - 10.0cos(t)) true / (-1.0 - 10.0cos(t))
1.0 0.0
Also, checking the result produces a (1,2) element of apparently different type from the rest:
julia> Symbolics.simplify.(inv(F)*F)
2×2 Matrix{Num}:
1.0 0
0.0 1.0
Also
julia> F\F
2×2 Matrix{Num}:
1 0.0
0.0 1.0
julia> F/F
2×2 Matrix{Num}:
1.0 0.0
0.0 1
generate entries of different nature.
I wonder if this is the expected behaviour.
https://github.com/JuliaSymbolics/Symbolics.jl/blob/da72404e92ad6894697f741747bfd828ff9df516/src/num.jl#L1-L3
Num
is a wrapper for Real
, SymbolicUtils.Symbolic
, etc. The symtype T
of SymbolicUtils.Symbolic{T}
and the numeric types of integers and floating-point numbers are ignored because of Num
.
Bool
true
inv(A::StridedMatrix{T})
calls inv!(A::LU{T,<:StridedMatrix})
https://github.com/JuliaLang/julia/blob/686afd3e41a797c070000d2d402ea224b4b25a0b/stdlib/LinearAlgebra/src/dense.jl#L893
inv!(A::LU{T,<:StridedMatrix})
calls Matrix{T}(s::UniformScaling, dims::Dims{2})
with s = I
where I
is the identity matrix (see doc)
https://github.com/JuliaLang/julia/blob/686afd3e41a797c070000d2d402ea224b4b25a0b/stdlib/LinearAlgebra/src/lu.jl#L514
Matrix{T}(s::UniformScaling, dims::Dims{2})
calls T(s.λ)
where s = I
https://github.com/JuliaLang/julia/blob/686afd3e41a797c070000d2d402ea224b4b25a0b/stdlib/LinearAlgebra/src/uniformscaling.jl#L498
I.λ
is true
of type Bool
which indicates the simplest one. T
is normally Int64
, Float64
, etc. So T(s.λ)
essentially converts true
to a one of the desired numeric type T
.
However, in our case T
is Num
, so T(true)
actually calls the constructor of Num
, instead of doing type conversion.
Int64
1
one(::Type{T})
https://github.com/JuliaLang/julia/blob/70656e214882ccb8744386e2f08db1e1eea46919/base/number.jl#L346
https://github.com/JuliaSymbolics/Symbolics.jl/blob/da72404e92ad6894697f741747bfd828ff9df516/src/num.jl#L158
When some functions, such as lu
, call one
internally, the result is just a 64-bit integer Int64
1
.
using Symbolics
@variables x::Float64
x_one = one(x) # Int64 1
t = typeof(x) # Num
xt_one = one(t) # Int64 1
y = Num(3.4)
y_one = one(y) # Int64 1
Fix
We can maybe add a parametric type to Num{T}
, but this doesn't seem easy.
Num{T} <: T
would be ideal but it's not possible in the language. We've discussed with the core compiler team and I don't think it'll be able to do this anytime soon. So Num <: Number
, which is where the oddities stem from. These are a bit hard to fix without overloading every single fallback individually (which we can do)
The true
is gone now, but
using Symbolics
F = [0.0 1.0; -1.0-10.0*cos(t) -24.0-19.0*sin(t)]
inv(F)
outputs mixed floats and integers:
2×2 Matrix{Num}:
(-24.0 - 19.0sin(t)) / (1.0 + 10.0cos(t)) -1.0 / (1.0 + 10.0cos(t))
1 0.0