库快速上手#
如果你不想先经过 BCW 示例,而是希望从一个可用环境直接走到第一次 finhjb 求解,就从这里开始。
下面这个例子故意保持得很小。它不是经济模型模板,而是为了把包里的对象分工讲清楚。
开始前#
最小可用求解示例#
下面这个例子是故意压到最小的。它不是研究模型,而是一个 package smoke test,用来清楚展示 Parameter / Boundary / PolicyDict / Policy / Model 这五层结构。
from dataclasses import dataclass
import jax.numpy as jnp
import finhjb as fjb
class Parameter(fjb.AbstractParameter):
offset: float = 0.0
class PolicyDict(fjb.AbstractPolicyDict):
control: object
@dataclass
class Boundary(fjb.AbstractBoundary[Parameter]):
pass
@dataclass
class Policy(fjb.AbstractPolicy[Parameter, PolicyDict]):
@staticmethod
def initialize(grid: fjb.Grid, p: Parameter) -> PolicyDict:
return PolicyDict(control=jnp.zeros_like(grid.s))
@staticmethod
@fjb.explicit_policy(order=1)
def keep_zero(grid: fjb.Grid) -> fjb.Grid:
grid.policy["control"] = jnp.zeros_like(grid.s)
return grid
@dataclass
class Model(fjb.AbstractModel[Parameter, PolicyDict]):
@staticmethod
def hjb_residual(v, dv, d2v, s, policy, jump, boundary, p):
return v - (s + p.offset)
@staticmethod
def auxiliary(grid: fjb.Grid):
return {"value_mean": jnp.mean(grid.v)}
parameter = Parameter()
boundary = Boundary(
p=parameter,
s_min=0.0,
s_max=1.0,
v_left=0.0,
v_right=1.0,
)
solver = fjb.Solver(
boundary=boundary,
model=Model(policy=Policy()),
policy_guess=True,
number=200,
config=fjb.Config(derivative_method="central"),
)
state, history = solver.solve()
grid = state.grid
print(type(state).__name__)
print(history.shape)
print(grid.df.head())
print(grid.aux)
这个例子说明什么#
Parameter放模型输入Boundary定义状态和值函数边界PolicyDict声明求解器要维护哪些策略数组Policy负责初始化和策略更新Model.hjb_residual(...)是求解器要逼近为零的核心方程
这就是最小直接 package 工作流。若你的目标是自己写模型,而不是先复现 BCW,它就是更合适的起点。
求解后先看什么#
第一次求解后,优先检查:
type(state).__name__historystate.grid.boundarystate.grid.df.head()state.grid.df.tail()如果你实现了
auxiliary(grid),再看state.grid.aux