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

Small inconsistencies #693

Open
andreasvarga opened this issue Aug 9, 2022 · 3 comments
Open

Small inconsistencies #693

andreasvarga opened this issue Aug 9, 2022 · 3 comments

Comments

@andreasvarga
Copy link

andreasvarga commented Aug 9, 2022

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.

@andreasvarga andreasvarga changed the title Samll inconsistencies Small inconsistencies Aug 9, 2022
@bowenszhu
Copy link
Member

bowenszhu commented Aug 9, 2022

@symbolic_wrap struct Num <: Real
val
end

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

Base.convert(::Type{Num}, x::Number) = Num(x)

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.

@ChrisRackauckas
Copy link
Member

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)

@hersle
Copy link
Contributor

hersle commented May 9, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants