Dual Numbers and Automatic Differentiation
This document provides a mathematically rigorous explanation of dual numbers and how they enable forward-mode automatic differentiation as implemented in the codebase.
I. Mathematical Definition of Dual Numbers
A dual number \(u\) is defined as
where \(x\) and \(y\) are real numbers representing the real and dual parts, respectively, and \(\epsilon\) is the dual unit satisfying
In the codebase, dual numbers are implemented via the ScalarDual(T) generic structure, where the real part \(x\) corresponds to the field val and the dual part \(y\) corresponds to the field der.
Algebraic Properties and Code Implementation
Given two dual numbers \(u=x_1+y_1\epsilon\) and \(v=x_2+y_2\epsilon\), the fundamental algebraic operations are mapped directly to methods on the ScalarDual(T) structure:
- Addition: Evaluated via the
addmethod as
and scalar addition adds as \(u+c=(x_1+c)+y_1\epsilon\).
- Subtraction: Evaluated via the
submethod as
and scalar subtraction subs as \(u-c=(x_1-c)+y_1\epsilon\).
- Multiplication: Evaluated via the
mulmethod using the product rule as
and scalar multiplication muls as \(u\cdot c=x_1c+y_1c\epsilon\).
- Division: Evaluated via the
divmethod using the quotient rule as
and scalar division divs as \(u/c=x_1/c+(y_1/c)\epsilon\), under the condition that the denominator is non-zero.
- Exponential: Evaluated via the
expmethod using the chain rule as
which propagates the derivative through exponential functions.
- Absolute Value: Evaluated via the
absmethod as
which implements the derivative of the absolute value function.
II. Differentiation with Dual Numbers
The connection between dual numbers and differentiation arises from the Taylor series expansion of a real-analytic function \(f\) evaluated at a dual number \(u=x+y\epsilon\), which is given by
Since all powers of \(\epsilon\) greater than or equal to two are zero, the infinite series truncates exactly after the first-order term, leaving
By setting the dual component \(y=1\), evaluating \(f(x+\epsilon)\) yields the function value in the real part and the exact derivative in the dual part.
Generalizing to Multivariate Functions
For a multivariate function \(f\) mapping \(\mathbb{R}^n\) to \(\mathbb{R}\), we can compute the partial derivative with respect to the coordinate \(r_j\) by setting the input vector \(\mathbf{r}\) to have a dual component of one at index \(j\) and zero elsewhere, which we write as
where \(\mathbf{e}_j\) is the \(j\)-th standard basis vector. Evaluating the function on this dual vector yields
This represents the principle of forward-mode automatic differentiation. The codebase utilizes this trick to evaluate nuclear gradients (such as in Møller–Plesset perturbation theory) by propagating dual numbers throughout the entire self-consistent field and molecular orbital transformation routines, avoiding finite-difference truncation errors.