Symbolic sqrt(2) and sin(pi)

It seems I was looking in the wrong place because this is explained in the SymbolicUtils docs:
https://symbolicutils.juliasymbolics.org/api/

I guess that the answer here is to use toexpr although I don’t see how to change the accuracy:

julia> expr
sqrt(2)

julia> toexpr(expr)
:((sqrt)(2))

julia> eval(toexpr(expr))
1.4142135623730951

How would I compute that with higher precision? More precisely how would I request a result with a given precision? SymPy’s evalf can compute the result accurate to any requested precision (not the same as computing using a given precision). It is slow because of this. The equivalent of toexpr is not really evalf but lambdify which is used to make functions that can be called with numpy etc. Is there an equivalent of evalf that can do things like this:

In [18]: ((10**100 * pi) % 1).evalf(20)
Out[18]: 0.82148086513282306647

I doesn’t look like symbolics actually supports any exact evaluation. It seems to be more of a floating point library with symbols. Note that this is very different from what sympy does e.g.:

In [20]: sin(10**10000*pi)
Out[20]: 0

With Julia I get:

julia> sin(BigInt(10)^10000*pi)
0.9242897329862240904757015163414326685882171473043200522236191072809156717509005

That’s not using Symbolics but I don’t immediately see any way to get Symbolics to compute something like that exactly (without using Term and writing my own rules). This is a core feature that would typically be expected in any general purpose CAS. I realise that Symbolics is still young but I’m asking about this because I want to understand what the intended design is for how these things would be handled. Note that the evaluation architecture is a significant reason for the slowness of SymPy for some operations. Many things in SymPy could be much faster if this was changed (but it’s a lot of work and not backwards compatible etc.).

Looking at the SymbolicsUtils docs it seems that it is based on the same architecture as SymPy’s Basic class. It also looks like the same fundamental design flaws have been copied over. I can use Term to prevent evaluation when constructing an expression just like in SymPy I can use evaluate=False. It doesn’t really work though because any operation (e.g. substitute) that rebuilds the expression tree will then cause it to evaluate. Actually the way this is implemented in SymbolicUtils might be even more problematic because it seems to default to fixed-precision floating point even for exact expressions. If I’m understanding this correctly then I strongly recommend taking a different approach where evaluation is something that only happens at the explicit request of the user.

6 Likes