Symbolic sqrt(2) and sin(pi)

Sorry, I thought it was pretty clear but the threads are long now. We need to capture the literal 2 and make it Literal(2). But then the issue is that we want Literal{T} <: T semantics. I.e. in promote_type it should use the promotions of T to build the value that is finally used in its rule applications or in its generated code. But not just promote_type, but every function. Without Literal{T} <: T semantics, that would require the symbolic library mimics promote_type, sin, and etc. dispatches of every number type, which then would mean we only would support Literal{T} for chosen types. So for now you can create the number with the type that you want, i.e. Term(sqrt,[big(2)]) and when the whole Sym{T} <: T passes are working Literal will just be a new istree under the same semantics and that would do this automatically.

Sym{T} <: T of course has been talked about at length on these forums and elsewhere with the solution to be to build it in the tracing environment. We just need to make any type satisfying some trait be captured to automatically have these semantics.

3 Likes

Just started learning Symbolics.jl a few weeks ago.

Why wouldn’t something like @register sqrt(x::Real) work?

It would be piracy, equivalent to:

sqrt(x::Real) = Term(sqrt,[x])

and now something that wants to specialize on Real might get hijacked. That’s why we want to define this in a local context of sorts.

2 Likes

This came up recently again in Promotion with rationals when constructing arrays · Issue #849 · JuliaSymbolics/Symbolics.jl · GitHub. The current best practice seems to be

using Symbolics
sqrt2 = Symbolics.wrap(Symbolics.Term(sqrt, [2]))

Please note the additional Symbolics.wrap.

1 Like

Revisiting the problem I wanted to handle with Symbolics.jl, I think I’ve figured out a favourable design for my use case.

Two levels of implementation to enable the flexibility of calling my mathematical functions with both Num and actual numeric instances, while avoiding piracy.

mysqrt(x::Real) = sqrt(x)
mysqrt(x::Num) = Symbolics.Term(sqrt, [x]) |> Symbolics.wrap

so when used inside my algorithmic implementations,

myalg(x::T, y::T) where T <: Real = x / mysqrt(y |> T)

will let me call it as both:

myalg(1, 2)

@variables x, y
myalg(x, y)
1 Like