Skip to content

🇬🇧 English · 🇪🇸 Español

Automatic differentiation and model adapters

PureMacro's NumPy-based dual and hyper-dual arithmetic differentiates supported functions. The model protocol is a separate interface: its presence does not mean that every model operation uses automatic differentiation or is supported.

Supported calculations

Model Likelihood and score Limits
Scalar StateSpaceModel Native Kalman likelihood and analytical sensitivity recursion Stationary system; parameters are rho, sigma_eps, sigma_meas; preserves the supplied loadings and intercepts
First-order LinearModel Native state-space likelihood and Kalman score Re-solvable equations and structural parameter names required; state-space sensitivities may use finite differences
BlockDAG Native Whittle likelihood and central-difference score Explicit observed data, observables, shock covariance, parameters and steady state required
DFM, SVAR, trade, spatial adapters Delegate supported native methods Unsupported operations raise NotImplementedError; there is no universal fitted-model score
Adapter constructed with model=None Synthetic demonstration with DualArray derivatives Emits a warning; does not estimate an economic model

Unknown model classes raise TypeError. A protocol conformance check verifies method names, not scientific validity.

DSGE likelihoods use stationary Kalman initialization. Structural scores re-solve the supplied model at the requested parameters. Shock and measurement covariances should be supplied explicitly when unit shock variance and zero measurement noise are inappropriate. Missing observations are handled by the Kalman path; the Whittle path requires finite, complete observations.

The DAG score holds the supplied steady state fixed as parameters change. It is a conditional score, not the total derivative through a recalibrated steady state. Steady-state recalibration must be performed in an outer objective when the research design requires it.

Derivative arithmetic

For a dual number \(x+\varepsilon d\), with \(\varepsilon^2=0\), \(f(x+\varepsilon d)=f(x)+\varepsilon f'(x)d\). Hyper-dual arithmetic adds a mixed term for second derivatives. These rules apply to supported differentiable operations; they do not remove identification problems, nonsmooth policy choices, or Monte Carlo error.

import numpy as np
from puremacro._autodiff import value_and_grad, hessian_forward

def loss(theta):
    return 100*(theta[0]-0.02)**2 + 50*theta[1]**2 + 20*theta[0]*theta[1]

theta = np.array([0.035, 0.015])
value, gradient = value_and_grad(loss, theta)
_, _, hessian = hessian_forward(loss, theta)
np.testing.assert_allclose(hessian, [[200, 20], [20, 100]])
print(value, gradient)

Native state-space example

The data below are explicitly simulated for this example. For estimation, replace them with observed data and retain the same column order.

import numpy as np
from puremacro.state_space import StateSpaceModel
from puremacro.core.protocol import wrap_differentiable_model

ssm = StateSpaceModel(
    T=np.array([[0.75]]), Z=np.array([[1.0]]),
    Q=np.array([[0.20**2]]), H=np.array([[0.05**2]]),
)
model = wrap_differentiable_model(ssm)
data = model.simulate(periods=100, seed=42)
loglik, score = model.loglik_and_grad([0.75, 0.20, 0.05], data)
irf = model.impulse_response(shock=0, horizon=12)
print(loglik, score)

For a solved DSGE, choose structural parameters explicitly, for example wrap_differentiable_model(dsge, param_names=["beta", "sigma", "kappa"]). Pass observables=["y", "pi"] when the likelihood data contain those variables. A misspelled parameter is an error.

A DSGE counterfactual can provide param_override and shock_sequence. The adapter re-solves the equations with the overrides and simulates the specified innovations. Unsupported scenario formats fail explicitly.

flowchart TD
    A[Supplied model and observed data] --> B{Supported native operation?}
    B -- Yes --> C[Native equations or state space]
    C --> D[Likelihood and documented score method]
    B -- No --> E[Explicit unsupported-operation error]
    F[Explicit model=None] --> G[Warned synthetic demonstration]

Validation and interpretation

tests/test_protocol_model_fidelity.py compares native likelihoods against a separate Kalman evaluation and DAG Whittle evaluation. It changes structural loadings and checks that likelihoods change, checks scores against finite differences, and verifies that invalid input cannot trigger synthetic fallback.

Agreement of a score with finite differences verifies a local derivative for that objective. It does not establish identification, posterior accuracy, or economic adequacy. Use the independent benchmark scripts in tools/reference_validation/ before extending the model to a research study.