Scmutils Notation for Partial Derivatives
In this short post, I express the Scmutils notation for partial derivatives of scalar functions with multiple parameters using JavaScript. As usual, you find the JavaScript program by following the Source Academy link, but this time, you need to change the language from Source §4 to “full JavaScript”.
The Single-parameter Case
An example of a scalar function with one parameter is the square
function.
const square = x => x * x;
A naive numerical differentiation function
follows the definition of derivatives, using Lagrange’s notation:
f'(x) = (f(x + d) - f(x)) / d
, where d
approaches 0.
Translating this definition to JavaScript yields
differentiation function.
const differentiate = f => x => (f(x + delta) - f(x)) / delta;
I call it “naive” because rounding errors creep in very quickly, if
delta
is chosen to be very small. For precise methods
of numerical differentiation, see
an earlier post. To explore the notation for differentiation, I ignore these
issues and stick to the naive version with a relatively large delta
.
const delta = 1e-4;
Using this differentiate
function, you can differentiate square
as follows.
differentiate(square); // returns a function square'
// approximately square'(x) = 2 * x
Applying the function that results from differentiating square
to 1
gives approximately 2.
differentiate(square)(1);
The square function above only has one argument, so when
you write square'
, it is clear what argument you are
differentiating for.
Multiple Parameters
The problem with Lagrange’s notation is that it doesn’t spell out which parameter(s) you are differentiating for when there are multiple parameters.
For functions with multiple parameters, you would like to compute a partial derivative by changing one value and leave the other values unchanged.
For example, you would like to compute the partial
derivative of
f(x, y) = x² + x y + y²
separately with respect to x
, and with respect to y
.
Euler’s notation uses the parameter name for this,
regardless of its position in the list of arguments:
(Dx f)(x, y) = (f(x + d, y) - f(x, y)) / d
where d
approaches 0
and
(Dy f)(x, y) = (f(x, y + d) - f(x, y)) / d
where d
approaches 0
In the use cases of Scmutils, functions are often generated by other functions, and then the parameter names may not be obvious.
Scmutils Notation for Partial Derivatives
Scmutils solves the issue by defining a function partial
that takes a subset of the parameter indices (rather than names)
of the function
to be differentiated, and returns a function transformer:
A function that differentiates its argument function with
repect to the parameters indicated by the indices.
Let’s start with the naive partial derivative with respect to a single parameter index:
const partial_single =
i => f => (...x) => (f(...add_to_index(x, i, delta))
- f(...x))
/ delta;
where the helper function add_to_index
adds a value delta
to
the i
th component of the vector values
.
const add_to_index =
(values, i, delta) => values.map((x, j) => i === j ? x + delta : x);
You can apply partial_single
to 0 and f
and get
the partial derivative of f
with respect to the first parameter x
partial_single(0)(f); // returns Dx f
partial_single(0)(f)(1, 2); // returns Dx f(1, 2), approximately 4
or with respect to parameter y
partial_single(1)(f); // returns Dy f
partial_single(1)(f)(1, 2); // returns Dy f(1, 2), approximately 5
You can use partial_single
to differentiate the square function.
partial_single(0)(square); // returns approximately Dx square: square'(x) = 2 * x
partial_single(0)(square)(1); // returns approximately square'(1) = 2
The partial
function in Scmutils
takes multiple parameter indices as arguments and
returns a function transformer: A function
that differentiates a given scalar function with repect to each
of the indices. The corresponding JavaScript function partial
is defined as follows, using a given partial_single
function.
const partial =
(...ids) => ids.length === 0
? f => f // base case: no index given: keep f as it is
// ids.slice(1) removes the first index from ids
: f => partial_single(ids[0])(partial(...ids.slice(1))(f));
To illustrate partial
, let’s define g(x, y, z) = x² + 2 y² + 3 z² + x y z
.
const g = (x, y, z) => square(x) + 2 * square(y) + 3 * square(z) + x * y * z;
Now, you can play with partial
and g
:
partial(2)(g)(1, 2, 3); // returns Dz g(1, 2, 3), approximately 20
partial(0,1)(g)(1, 2, 3); // returns Dx Dy g(1, 2, 3), approximately 3
partial(0,2)(g)(1, 2, 3); // returns Dx Dz g(1, 2, 3), approximately 2
partial(0,1,2)(g)(1, 2, 3); // returns Dx Dy Dz g(1, 2, 3), approximately 1
The Nabla Function
The Nabla function (usually denoted by the symbol ∇) is a function
transformer that takes a
multi-parameter scalar function f
as argument
and returns a multi-parameter function that returns the gradient
vector of f
at the given position. In JavaScript, the Nabla function
can be defined using partial_single
as follows:
const Nabla = f => {
// indices is vector [0, 1,...,n] where n is arity of f
const indices = Array(f.length).fill().map( (ignore, i) => i);
// partials is vector [Dx f, Dy f,...] if f has parameters x, y, ...
const partials = indices.map(i => partial_single(i)(f));
return (...x) => partials.map(p => p(...x));
};
For example, you can apply Nabla
to the function f
above as follows.
Nabla(f); // the Nabla function of f
Nabla(f)(1, 2); // the gradient vector of f at position (1,2),
// approximatately [4, 5]
For the function g
you get:
Nabla(g)(1, 2, 3); // the gradient vector of g at position (1,2,3):
// [Dx g(1,2,3), Dy g(1,2,3), Dz g(1,2,3)], approximately
// [8, 11, 20]