Quick Start
This is the smallest NFXP path: fit the reference structural estimator, then inspect parameters, standard errors, policy, and value objects. It is a usage example, not a substitute for the pre-estimation checks.
from econirl.datasets import load_rust_bus
from econirl import NFXP
df = load_rust_bus()
model = NFXP(n_states=90, discount=0.9999, utility="linear_cost")
model.fit(df, state="mileage_bin", action="replaced", id="bus_id")
print(model.params_) # {"theta_c": ..., "RC": ...}
print(model.se_)
print(model.summary())
Fitted attributes follow the same convention as CCP and UFXP:
Attribute |
Meaning |
|---|---|
|
Estimated structural reward parameters. |
|
Standard errors for the structural parameters. |
|
Coefficients as a numpy array. |
|
Estimated action probabilities by state. |
|
Estimated value function by state. |
|
Maximized conditional choice log likelihood. |
|
Whether the outer optimizer reported convergence. |
Custom Reward Features
The utility="linear_cost" default builds the Rust bus features for you. To use
your own features, pass a RewardSpec to fit. The feature array has shape
(n_states, n_actions, n_features), and reward= takes priority over the
default reward features.
import numpy as np
from econirl import NFXP, RewardSpec
from econirl.datasets import load_rust_bus
df = load_rust_bus()
n_states, n_actions = 90, 2
mileage = np.arange(n_states) / n_states
features = np.zeros((n_states, n_actions, 2))
features[:, 0, 0] = -mileage # operating cost on "keep", rising with mileage
features[:, 1, 1] = -1.0 # flat replacement cost on "replace"
spec = RewardSpec(features, names=["operating_cost", "replacement_cost"])
model = NFXP(n_states=n_states, discount=0.9999)
model.fit(df, state="mileage_bin", action="replaced", id="bus_id", reward=spec)
print(model.params_) # {"operating_cost": ..., "replacement_cost": ...}
A RewardSpec whose state or action dimension does not match n_states /
n_actions raises a clear ValueError at fit time, not a broadcasting error
later.
Counterfactual Example
cf = model.counterfactual(RC=4.0)
print(cf.params)
print(cf.policy[50, 1])
This solves the fitted model again with a higher replacement cost and returns the new value function and policy.
Full Estimator API
Use econirl.estimation.nfxp.NFXPEstimator when you need direct control over
panel objects, utility objects, transition tensors, optimizer options, or
diagnostic metadata:
from econirl.estimation import NFXPEstimator
result = NFXPEstimator(inner_solver="hybrid", inner_tol=1e-10).estimate(
panel, utility, problem, transitions
)