Skip to content

🇬🇧 English · 🇪🇸 Español

Continuación de ramas de equilibrio

puremacro.core.continue_equilibrium sigue una rama local de \(F(x,\theta)=0\), variando un parámetro y manteniendo fijos los demás. Usa el mismo contrato de residuos y los jacobianos comprobados de la interfaz común de derivadas.

El predictor avanza sobre una tangente en coordenadas escaladas; un corrector Newton amortiguado resuelve las ecuaciones y un hiperplano tangente. Esta es la construcción de pseudo-longitud de arco descrita en la documentación de BifurcationKit. El sistema aumentado puede seguir siendo regular en un pliegue simple donde falla la derivada ordinaria respecto al parámetro; véase Dickson et al. para su condicionamiento.

Trazar e inspeccionar una rama

import numpy as np
from puremacro.core import EquilibriumSystem, continue_equilibrium

system = EquilibriumSystem(
    lambda x, p: x**3 - x - p,
    ("capital",), ("policy",),
)
branch = continue_equilibrium(
    system, [-1.5], [-1.875],
    step=.08, max_step=.12, max_steps=100,
    parameter_bounds=(-2., 2.), branch_id="cubic-example",
)
assert len(branch.folds) == 2
assert all(f.status == "simple_fold" for f in branch.folds)
print(branch.summary())
ax = branch.plot("capital")

El punto inicial debe satisfacer las ecuaciones. direction=1 o -1 selecciona la dirección inicial del parámetro, que puede invertirse en un pliegue. Con varios parámetros se especifica parameter="name". Semillas y opciones inválidas, y excepciones de las funciones o del dominio del modelo, generan errores directamente.

states y parameters contienen coordenadas físicas. tangents contiene vectores unitarios en coordenadas escaladas de estado/parámetro seleccionado, con el parámetro al final. arclength acumula longitudes de cuerda en esas coordenadas; step_sizes contiene distancias solicitadas al hiperplano tangente. Los arreglos son copias de solo lectura. Las funciones genéricas siguen bajo control del usuario y deben ser puras; los adaptadores incorporados conservan copias de sus entradas numéricas.

to_frame/to_dataframe, summary, to_markdown, to_latex, to_typst y plot muestran puntos aceptados. Las columnas usan prefijos state: y parameter:. attempts_frame() incluye intentos aceptados y rechazados, iteraciones, residuos y motivos. Los diagnósticos no disponibles en predictores rechazados son NaN. Los gráficos no llaman a show.

Reiniciar o invertir el recorrido

reverse = continue_equilibrium(
    branch.system, branch.states[-1], branch.parameters[-1],
    parameter=branch.parameter_name,
    initial_tangent=-branch.tangents[-1],
    step=.03, max_step=.05, max_steps=8,
)
assert reverse.states[-1, 0] < reverse.states[0, 0]

initial_tangent determina la orientación y tiene prioridad sobre direction; debe pertenecer al espacio nulo aumentado en coordenadas escaladas. Comenzar en un punto de giro del parámetro exige esta orientación explícita. Los pasos de hiperplano inversos no tienen que visitar puntos idénticos.

Reutilizar las ecuaciones de un modelo

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)
growth = continue_equilibrium(
    lin.system, lin.state, lin.parameters, parameter="beta",
    step=.002, max_step=.002, max_steps=8,
)
assert growth.status == "max_steps"

La misma llamada acepta el sistema conservado por linearize_aiyagari. Consumo, probabilidades estacionarias y tasas de interés cambian conjuntamente. Las mallas y la cadena de ingreso permanecen fijas. La implementación se detiene ante cambios declarados de régimen de restricción, interpolación o lotería. Las ramas suaves y pequeñas de Aiyagari se comparan con soluciones independientes; esto no establece continuación global entre regímenes.

Pasos, terminación y pliegues

Los valores iniciales son step=.05, min_step=1e-5, max_step=.2, max_steps=100, max_newton=12 y max_retries=8. Los intentos fallidos reducen el paso a la mitad; los exitosos lo adaptan según el esfuerzo del corrector y la alineación de tangentes. Correcciones grandes y giros bruscos provocan reintentos. Los límites finitos del parámetro detienen el recorrido, posiblemente antes de alcanzarlos exactamente. Restringen la trayectoria, no las sondas de derivación: las ecuaciones necesitan un entorno bilateral.

La terminación por presupuesto o límite usa max_steps o parameter_bound. Los demás estados conservan la trayectoria parcial aceptada e identifican el último fallo diagnosticado, como regime_change, newton_failed, rank_deficient, rank_unresolved, possible_branch_point, ill_conditioned o step_not_representable. Revise estado e intentos antes de usar una rama. Una prueba de signos detecta algunos puntos de ramificación intermedios; no puede detectar todas las singularidades entre muestras.

Las tolerancias iniciales del equilibrio escalado y del hiperplano son 1e-9. derivative_step=1e-5 y derivative_tol=1e-3 controlan la comprobación de jacobianos. La derivada aumentada debe cumplir rank_tol=1e-10 y condition_limit=1e10. Cerca de una pérdida de rango, un paso de derivación reducido a la mitad comprueba que el menor valor singular supere la discrepancia observada entre derivadas.

Una inversión de la tangente del parámetro delimita un candidato a pliegue. El refinamiento usa hasta fold_max_iter=40 correcciones y tolerancia escalada del intervalo fold_tol=1e-7. Los registros incluyen corango de estado, condicionamiento aumentado, transversalidad del vector nulo izquierdo y un coeficiente direccional cuadrático. La curvatura usa curvature_step=1e-4 y la mitad de ese paso; degeneracy_tol=1e-5 controla las pruebas de no degeneración. Se distingue entre simple_fold, degenerate_or_unresolved y unresolved. Son clasificaciones numéricas según escalas y tolerancias declaradas, no certificados matemáticos. Los pliegues refinados se registran aparte de la trayectoria. Una resolución finita puede omitir pliegues cercanos o giros muy planos.

Alcance y ejemplo reproducible

El método es denso, con max_states=1500 por defecto. Conserva arreglos de la trayectoria, no todos los jacobianos densos. Las escalas afectan la geometría y el condicionamiento. No hay cambio automático de rama, enumeración de raíces desconectadas, afirmación de exhaustividad global, clasificación de estabilidad, análisis de Hopf ni inferencia estadística. branch_id es una etiqueta del usuario.

Ejecute python -m puremacro.examples.equilibrium_branches --output /tmp/equilibrium-branches. El modelo ilustrativo de ahorro fijo tiene producción f(k)=.05+k**2/(1+k**2) y equilibrio .1*k=s*f(k). Los archivos CSV/JSON y PNG/PDF comparan trayectoria y pliegues con una curva analítica independiente. En s=.20, soluciones escalares independientes recuperan tres equilibrios y coinciden con el polinomio cúbico asociado. La ilustración no es una economía estimada ni un modelo de ahorro óptimo.

Las pruebas también cubren una curva cúbica en S, ecuaciones acopladas, transformaciones de unidades, pliegues degenerados, semillas de ramificación, reintentos y fallos, parámetros fijos no diferenciables y soluciones independientes de RBC/Aiyagari.