I got from the documentation that you can use Symbolics.jl and Latexify.jl together to display your equations.
However, what can be evaluated gets evaluated right away so in that sense not the same as sympy or Sympy.jl [1][2].
For instance,
using Symbolics
using Latexify
@variables r
v = 4 / 3 * π * r ^ 3
D = Differential(r)
a = expand_derivatives(D(v))
latexify(a)
returns
L"\begin{equation}
12.566 r^{2}
\end{equation}
"
A workaround (launching a new instance of Julia):
using Symbolics
using Latexify
@variables r, π
v = 4 // 3 * π * r ^ 3
D = Differential(r)
a = expand_derivatives(D(v))
latexify(a)
assuming that π
has not already been associated with Base.pi
through a prior calculation (hence requiring the launch of a new Julia instance; otherwise maybe enclose in a let...end
block).
This returns
L"\begin{equation}
4 r^{2} \pi
\end{equation}
"
To use this for computation,
a_expr = (x) -> substitute(a, Dict(π => Symbolics.pi, r => x))
a_expr(2)
returns 50.26548245743669
. In this case, care must be taken that the argument to the anonymous function cannot be r
as it is now considered a symbol in this namespace (which I found out by accident - that r
would remain a symbol within the scope of the anonymous function was expected behavior).
Alternatively, I can also convert this to a function. If I understand correctly, π will evaluate to Symbolics.pi
(which is the same as Base.pi
) even without my substitution.
a_fn = build_function(a, r, expression=Val{false})
a_fn(2)
returns the same value as above.
Am I understanding the use cases correctly - or is there a more direct way to use the same notation for defining symbolic expressions for displaying and calculations?
Is there a better way to contain the scope of symbolic variables? Should they always be used within a let...end
block?