Mathematica is the de facto standard for symbolic differentiation and integration. But many other languages also have great facilities for Calculus. For example, R has the deriv()
function in the base stats
package as well as the numDeriv, Deriv and Ryacas packages. Python has NumPy and SymPy.
Let’s check out what Julia has to offer.
Numerical Differentiation
First load the Calculus package.
using Calculus
The derivative() function will evaluate the numerical derivative at a specific point.
derivative(x -> sin(x), pi)
-0.9999999999441258
derivative(sin, pi, :central) # Options: :forward, :central or :complex
-0.9999999999441258
There’s also a prime notation which will do the same thing (but neatly handle higher order derivatives).
f(x) = sin(x);
f'(0.0) # cos(x)
0.9999999999938886
f''(0.0) # -sin(x)
0.0
f'''(0.0) # -cos(x)
-0.9999977482682358
Functions exist for second derivatives, gradients (for multivariate functions) and Hessian matrices too. Related packages for derivatives are ForwardDiff and ReverseDiffSource.
Symbolic Differentiation
Symbolic differentiation works for univariate and multivariate functions expressed as strings.
differentiate("sin(x)", :x)
:(cos(x))
differentiate("sin(x) + exp(-y)", [:x, :y])
2-element Array{Any,1}:
:(cos(x))
:(-(exp(-y)))
It also works for expressions.
differentiate(:(x^2 \* y \* exp(-x)), :x)
:((2x) \* y \* exp(-x) + x^2 \* y \* -(exp(-x)))
differentiate(:(sin(x) / x), :x)
:((cos(x) * x - sin(x)) / x^2)
Have a look at the JuliaDiff project which is aggregating resources for differentiation in Julia.
Numerical Integration
Numerical integration is a snap.
integrate(x -> 1 / (1 - x), -1 , 0)
0.6931471805602638
Compare that with the analytical result. Nice.
diff(map(x -> - log(1 - x), [-1, 0]))
1-element Array{Float64,1}:
0.693147
By default the integral is evaluated using Simpson’s Rule. However, we can also use Monte Carlo integration.
integrate(x -> 1 / (1 - x), -1 , 0, :monte_carlo)
0.6930203819567551
Symbolic Integration
The SymPy package supports the SymPy Python library. You might want to restart your Julia session before loading it.
using Sympy
Revisiting the same definite integral from above we find that we now have an analytical expression as the result.
integrate(1 / (1 - x), (x, -1, 0))
log(2)
convert(Float64, ans)
0.6931471805599453
To perform symbolic integration we need to first define a symbolic object using Sym()
.
x = Sym("x"); # Creating a "symbolic object"
typeof(x)
Sym (constructor with 6 methods)
sin(x) |> typeof # f(symbolic object) is also a symbolic object
Sym (constructor with 6 methods)
There’s more to be said about symbolic objects (they are the basis of pretty much everything in SymPy), but we are just going to jump ahead to constructing a function and integrating it.
f(x) = cos(x) - sin(x) * cos(x);
integrate(f(x), x)
2
sin (x)
- ─────── + sin(x)
2
What about an integral with constant parameters? No problem.
k = Sym("k");
integrate(1 / (x + k), x)
log(k + x)
We have really only grazed the surface of SymPy. The capabilities of this package are deep and broad. Seriously worthwhile checking out the documentation if you are interested in symbolic computation.
I’m not ready to throw away my dated version of Mathematica just yet, but I’ll definitely be using this functionality often. Come back tomorrow when I’ll take a look at solving differential equations with Julia.