Day 20: Calculus

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
The SymPy logo.

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.

xkcd cartoon about the invention of Calculus.

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.