Automatic differentiation rules for selected
MatrixEquations.jl
solvers, plus a Klein/Sims first-order policy-map primitive. AD rules
(ForwardDiff Dual dispatches and Enzyme forward / reverse) load
through package extensions when the relevant AD package is in scope.
See the documentation for derivations, worked examples, and the per-solver API:
- Klein Policy Map —
first-order DSGE policy
(g_x, h_x) - Discrete Lyapunov (Schur) —
lyapd(A, C)solvingA X A^\top - X + C = 0 - Kronecker Discrete Lyapunov —
lyapdkr(A, C)Kronecker LU variant - Generalised Sylvester —
gsylv/gsylvkrforA X B + C X D = E - Algebraic Riccati (DARE) —
ared(A, B, R, Q, S)with stabilising gainF
using Pkg
Pkg.add(url = "https://github.com/QuantEcon/MatrixEquationsAD.jl")Differentiate a small discrete Lyapunov solve with ForwardDiff:
using ForwardDiff
using MatrixEquations
using MatrixEquationsAD
A = [0.55 0.08; -0.04 0.42]
C = [1.0 0.2; 0.2 0.7]
lyapd_sum(x) =
sum(lyapd(reshape(x[1:4], 2, 2), reshape(x[5:8], 2, 2)))
ForwardDiff.gradient(lyapd_sum, [vec(A); vec(C)])The same loss with Enzyme reverse mode:
using Enzyme: Active, Const, Duplicated, Reverse, autodiff, make_zero
using LinearAlgebra: dot
using MatrixEquations
using MatrixEquationsAD
A = [0.55 0.08; -0.04 0.42]
C = [1.0 0.2; 0.2 0.7]
W = [0.4 -0.1; -0.1 0.7]
weighted(A, C, W) = dot(W, lyapd(A, C))
A_bar = make_zero(A); C_bar = make_zero(C)
autodiff(
Reverse, weighted, Active,
Duplicated(A, A_bar), Duplicated(C, C_bar), Const(W),
)