🇬🇧 English · 🇪🇸 Español
Derivadas comunes del equilibrio
puremacro.core.EquilibriumSystem describe ecuaciones cuadradas de equilibrio
\(F(x,\theta)=0\). linearize_equilibrium conserva sus jacobianos locales
y resuelve \(F_x\,\partial x/\partial\theta=-F_\theta\).
Esta primera implementación usa matrices densas y un límite configurable del
número de estados. La continuación de ramas
reutiliza estas ecuaciones. Los conjuntos de confianza estadísticos siguen
siendo una extensión separada, todavía no implementada en esta API.
Ecuaciones explícitas
import numpy as np
from puremacro.core import EquilibriumSystem, linearize_equilibrium
system = EquilibriumSystem(
residual=lambda x, p: np.array([2*x[0] + x[1] - p[0], x[1] - p[0]]),
state_names=("capital", "price"),
parameter_names=("technology",),
)
lin = linearize_equilibrium(system, [0., 1.], [1.], branch_id="benchmark")
result = lin.sensitivity()
assert result.valid
print(result.to_frame()) # derivadas: capital=0, price=1
Las funciones opcionales state_jacobian(x, theta) y
parameter_jacobian(x, theta) se contrastan con diferencias centrales de los
residuos. Sin estas funciones, las diferencias centrales generan ambos
jacobianos: son derivadas numéricas, aunque la aplicación del teorema
de la función implícita resuelva un sistema lineal.
lin.jvp(v) y lin.vjp(w) aplican \(F_x\) y \(F_x^T\).
lin.solve(rhs) y lin.solve(rhs, transpose=True) reutilizan una
factorización LU. Estas operaciones forman matrices densas. Las ecuaciones
se conservan en lin.system.evaluate(x, theta).
Las funciones genéricas deben ser puras y siguen bajo control del usuario;
los adaptadores de modelos conservan copias de sus entradas numéricas.
Proyección del modelo de crecimiento
from puremacro.vfi import CollocationProblem, linearize_projection
kss = (.36 * .96)**(1 / (1 - .36))
problem = CollocationProblem(
domain=(.5*kss, 1.5*kss), orders=6, method="euler", beta=.96,
params={"alpha": .36, "delta": 1., "sigma": 1.},
options={"tol": 1e-12, "max_iter": 500},
)
solution = problem.solve()
lin = linearize_projection(solution, problem, parameters=("alpha", "beta"))
result = lin.sensitivity()
assert result.valid, result.reasons
policy_derivative = solution.basis.evaluate(kss) @ result.jacobian
Los estados son coeficientes de Chebyshev. La derivada de la política mantiene
fijos el estado de evaluación, la base y el dominio. Se admiten las ecuaciones
Euler incorporadas de una dimensión, beta y los parámetros declarados
alpha, delta, sigma/gamma, z/A. Se rechazan alias anulados por
su parámetro canónico. Bellman, funciones personalizadas, FEM y splines
requieren otro adaptador o ecuaciones explícitas. Se rechazan recortes físicos
de la política y continuación fuera del dominio en el punto inicial.
Aiyagari continuo
from puremacro.vfi import solve_aiyagari_continuous, linearize_aiyagari
equilibrium = solve_aiyagari_continuous(
beta=.95, n_a=30, N_k=60, n_z=3,
xtol=1e-11, egm_tol=1e-11, tol_ge=1e-6,
)
lin = linearize_aiyagari(equilibrium, parameters=("alpha", "beta", "gamma", "delta"))
result = lin.sensitivity()
assert result.valid, result.reasons
print(result.to_frame().loc[["interest_rate"]])
Las incógnitas son consumo en los nodos EGM, probabilidades del histograma y tasa de interés de equilibrio, en ese orden. Las ecuaciones combinan el punto fijo de Coleman, transporte estacionario con una ecuación sustituida por normalización y equilibrio del mercado de capital. Al reconstruir matrices, el orden es por filas: activos primero, ingreso después.
Se conserva la cadena de ingreso efectiva, incluidas cadenas personalizadas.
Se admiten alpha, beta, gamma y delta, con mallas y procesos de ingreso
fijos. La restricción de endeudamiento usa una extensión local del conjunto
activo: el ahorro es cero en nodos restringidos y su ecuación de consumo
impone el presupuesto. Los pasos de diferenciación comprueban el conjunto
activo, las celdas de interpolación y las celdas de la lotería del histograma.
Si el cambio persiste, no se entrega una derivada ordinaria. No se admiten
resultados genéricos de continuous_stationary_equilibrium.
Hay (n_a + N_k) * n_z + 1 estados. El ejemplo tiene 271; las mallas por
defecto del solucionador exceden max_states=1500, el límite inicial del
linealizador. Aumentarlo exige considerar almacenamiento denso y costo cúbico
de factorización. Las mallas pequeñas verifican la API, no precisión económica
de la discretización ni escalabilidad a HANK.
Diagnósticos y alcance
state_scale, parameter_scale y residual_scale son unidades positivas de
coordenadas y ecuaciones. El paso es step * coordinate_scale, con
step=1e-5, y puede reducirse ocho veces. Los valores singulares se calculan
sobre diag(1/residual_scale) @ F_x @ diag(state_scale).
Al cambiar unidades, hay que ajustar las escalas; los diagnósticos de
condicionamiento dependen de ellas.
Las tolerancias iniciales son residual_tol=1e-7, derivative_tol=1e-3,
singular_tol=1e-10 y condition_limit=1e10. Los motivos de rechazo incluyen
not_equilibrium, regime_change, inconsistent_stencil,
derivative_mismatch, singular, ill_conditioned y linear_solve_failed.
Las sensibilidades rechazadas contienen NaN y no se permite resolver el
sistema lineal rechazado. No hay regularización ni corrección implícita del
equilibrio. Entradas inválidas y excepciones del modelo se propagan; las
diferencias necesitan un entorno bilateral dentro del dominio declarado.
Los arreglos son copias de solo lectura. snapshot_id identifica por hash
datos numéricos, matrices y escalas, no código fuente. branch_id es una
etiqueta del usuario, no una certificación de ramas. Los pasos finitos y
residuos pequeños no prueban suavidad, unicidad, precisión de malla,
identificación estadística ni inferencia válida. Las
API IFT especializadas conservan su comportamiento.
Los resultados ofrecen summary, to_frame/to_dataframe, to_markdown,
to_latex, to_typst y plot(states=...). Los gráficos no llaman a show y
admiten como máximo 30 filas de estados.
Ejecute python -m puremacro.examples.equilibrium_linearization --output /tmp/equilibrium-derivatives
para generar CSV/JSON con sensibilidades de política, capital agregado y tasa
de interés, además de un caso singular. Las pruebas comparan soluciones
independientes en dos calibraciones de crecimiento y dos procesos de ingreso,
incluyendo toda la distribución Aiyagari y su derivada de masa total cero.