Introduction to the Julia programming language
20 Symbolic Math¶
Symbolic math in Julia¶
Julia offers several packages for symbolic computer algebra, providing functionalities for symbolic manipulation, differentiation, integration, equation solving, and more. Here we focus on Symbolics.jl and SymPy.jl.
Symbolics.jl is a fast and modern Computer Algebra System (CAS) for a fast and modern programming language (Julia). The goal is to have a high-performance and parallelized symbolic algebra system that is directly extendable in the same language as that of the users.
SymPy.jl provides a Julia interface to the SymPy library in Python, which is a well-established symbolic mathematics library. It allows you to perform various symbolic operations including symbolic manipulation, solving equations, calculus, and more.
Derivatives¶
using Symbolics
@variables t
D = Differential(t)
z = t + t^2
D(z)
D is a lazy operator because it lets us symbolically represent "The derivative with respect to $t$". If we want to expand the derivative operators, we'd use expand_derivatives:
expand_derivatives(D(z))
The variable, that you are taking the derivative with respect to, is accessed with:
D.x
Simplification and Substitution¶
@variables x y
simplify(2x + 2y)
simplify(sin(x)^2+cos(x)^2)
simplify(cosh(x)^2-sinh(x)^2)
This can be applied to arrays by using Julia's broadcast mechanism:
B = simplify.([t + t^2 + t + t^2 2t + 4t
x + y + y + 2t x^2 - x^2 + y^2])
We can then use substitute to change values of an expression around:
simplify.(substitute.(B, (Dict(x => y^2),)))
Example: Error propagation with Symbolics.jl¶
function err_prop(f, vars)
@variables sum
sum = 0
for (x, sigma) in vars
D = Differential(x)
sum += expand_derivatives(D(f))^2 * sigma^2
end
return sqrt(simplify(sum))
end
err_prop (generic function with 1 method)
Take the volume of a cylinder as an example:
@variables r, h, σ_r, σ_h
V = pi * r^2 * h
σ_V = err_prop(V, [(r, σ_r), (h, σ_h)])
Plug in numerical values:
using Formatting
r_meas = 3 # cm
σ_r_meas = 0.1 # cm
h_meas = 5 # cm
σ_h_meas = 0.1; # cm
V_num = substitute(V, Dict(r => r_meas, h => h_meas))
σ_V_num = substitute(σ_V, (Dict(r => r_meas, σ_r => σ_r_meas,
h => h_meas, σ_h => σ_h_meas)))
printfmt("V = ({:.2f} ± {:.2f}) cm^3", Symbolics.value(V_num), Symbolics.value(σ_V_num))
V = (141.37 ± 9.84) cm^3
Error propgation with Measurements.jl¶
For the particular problem of error propgation, there are also other tools, e.g., Measurements.jl
See arXiv:1610.08716
using Measurements
r = measurement(3, 0.1)
h = measurement(5, 0.1)
V = pi * r^2 * h
SymPy¶
using SymPy
@which simplify
WARNING: using SymPy.simplify in module Main conflicts with an existing identifier. WARNING: using SymPy.Differential in module Main conflicts with an existing identifier.
SymbolicUtils
sympy.sqrt(2)
sympy.sqrt(2).evalf(50)
x, y = sympy.symbols("x y")
x + 1/2
x + sympy.S(1)/2
Expression manipulation¶
expr = sympy.cosh(x)^2 - sympy.sinh(x)^2
sympy.simplify(expr)
sympy.trigsimp(2 * sin(x) * cos(x))
sympy.factor(x^2 +2x +1)
Differentiation¶
sympy.diff(sin(x)*exp(x), x)
Symbolic integration¶
sympy.integrate(exp(x)*sin(x) + exp(x)*cos(x), x)
sympy.integrate(cos(x)^2, (x, 0, pi))
Solving equations¶
sympy.solve(x^2 - 8x + 15, x)
2-element Vector{Sym{PyCall.PyObject}}: 3 5
eq1 = sympy.Eq(x + y, 5)
eq2 = sympy.Eq(x^2 + y^2, 17)
sympy.solve((eq1, eq2), (x, y))
2-element Vector{Tuple{Sym{PyCall.PyObject}, Sym{PyCall.PyObject}}}: (4, 1) (1, 4)
Substitution¶
expr = x^2 + y^2
expr.subs(x, 2)
expr.subs([(x,3), (y,4)])
Variable transformation¶
using Latexify
x, y, z, r, phi, theta = sympy.symbols("x, y, z, r, theta, phi")
(x, y, z) = (r * sin(theta) * cos(phi),
r * sin(theta) * sin(phi),
r * cos(theta))
X = sympy.Matrix([x, y, z])
Y = sympy.Matrix([r, theta, phi])
J = X.jacobian(Y)
latexify(J)
sympy.simplify(J.det())