Automatic Differentiation
What It Is
QAtlas uses forward-mode automatic differentiation (AD) via ForwardDiff.jl to extract thermodynamic quantities from the partition function $Z(\beta, J, h, \ldots)$. All equilibrium observables are derivatives of $\ln Z$:
\[\langle E \rangle = -\frac{\partial \ln Z}{\partial \beta}, \qquad C_v = \beta^2 \frac{\partial^2 \ln Z}{\partial \beta^2}, \qquad \langle \sigma\sigma \rangle_{\mathrm{nn}} = \frac{1}{\beta}\frac{\partial \ln Z}{\partial J}\]
By computing $Z$ as a differentiable function and passing dual numbers through it, all derivatives are obtained exactly (to machine precision) without finite differences or symbolic manipulation.
See calc/ad-thermodynamics-from-z.md for the full derivation of thermodynamic identities.
How It Works
ForwardDiff.jl implements forward-mode AD via dual numbers. A dual number $a + b\,\varepsilon$ with $\varepsilon^2 = 0$ carries a function value and its derivative simultaneously through any computation:
\[f(a + b\varepsilon) = f(a) + f'(a) \cdot b\varepsilon\]
For second derivatives (specific heat), nested dual numbers are used: the outer dual differentiates with respect to $\beta$, and the inner dual differentiates the result again.
using ForwardDiff
# Energy: first derivative of -ln Z
E(beta) = ForwardDiff.derivative(b -> -log(Z(b)), beta)
# Specific heat: second derivative
Cv(beta) = beta^2 * ForwardDiff.derivative(
b -> ForwardDiff.derivative(b2 -> log(Z(b2)), b), beta)Key Requirement: Real Type Signatures
For AD to work, every function in the computation chain must accept any Real subtype, not just Float64. The dual number type ForwardDiff.Dual{T,V,N} <: Real must propagate through:
- Transfer matrix construction
- Matrix multiplication ($T^{L_x}$)
- Trace computation
- Logarithm
Any function with a restrictive type signature f(x::Float64) will fail when called with a Dual input. QAtlas's fetch methods are designed to accept Real arguments throughout.
Why tr(T^Lx), Not Eigenvalue Decomposition
The partition function can in principle be computed as $Z = \sum_i \lambda_i^{L_x}$ from the eigenvalues of $T$. However, LAPACK's eigenvalue routines (DSYEV, DGEEV) are implemented in Fortran and perform internal comparisons and branches that are incompatible with dual-number arithmetic. Calling eigvals on a matrix of Dual elements will fail.
Matrix multiplication and tr are purely algebraic operations that propagate duals correctly. Therefore QAtlas computes
\[Z = \mathrm{tr}(T^{L_x})\]
via repeated squaring ($O(\log L_x)$ matrix multiplications). This is the reason QAtlas uses the transfer matrix approach with tr rather than eigenvalue decomposition.
Verification
AD-computed derivatives are verified against brute-force ensemble averages (explicit sum over all $2^N$ configurations) to machine precision ($\sim 10^{-15}$ relative error). This confirms that:
- The transfer-matrix construction preserves differentiability.
- The AD chain rule propagates correctly through
tr, matrix power, andlog. - No non-differentiable operations (e.g.,
ifbranches on values) break the derivative.
Applications in QAtlas
| Observable | Formula | Used in |
|---|---|---|
| Internal energy $\langle E \rangle$ | $-\partial_\beta \ln Z$ | IsingSquare thermal verification |
| Specific heat $C_v$ | $\beta^2 \partial_\beta^2 \ln Z$ | Cross-check #7: $\alpha = 0$ |
| NN correlation $\langle\sigma\sigma\rangle$ | $\beta^{-1}\partial_J \ln Z$ | IsingSquare correlation check |
References
- J. Revels, M. Lubin, T. Papamarkou, "Forward-mode automatic differentiation in Julia", arXiv:1607.07892 (2016) –- ForwardDiff.jl.
- A. G. Baydin, B. A. Pearlmutter, A. A. Radul, J. M. Siskind, "Automatic differentiation in machine learning: a survey", JMLR 18, 1 (2018) –- AD review.