Quick Start

Custom Reward Features

rust_bus_reward_spec(n_states) builds the Rust bus features for you. To use your own features, build a RewardSpec directly and pass it to fit. The feature array has shape (n_states, n_actions, n_features). Passing reward= to fit overrides the constructor default.

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({name: round(value, 6) for name, value in model.params_.items()})

Result

{'operating_cost': 0.090265, 'replacement_cost': 3.072221}

If a RewardSpec state dimension does not match n_states, or its action dimension does not match n_actions, fit raises a clear ValueError instead of a later broadcasting error.

Counterfactual Example

cf = model.counterfactual(replacement_cost=4.0)

print(f"replacement_cost = {cf.params['replacement_cost']:.6f}")
print(f"P(replace | state=50) = {cf.policy[50, 1]:.6f}")

Result

replacement_cost = 4.000000
P(replace | state=50) = 0.055196

This solves the fitted model again with a higher replacement cost and returns the new value function and policy. The Counterfactuals page shows how to change the transition model and reports the resulting policy change.

summary(alpha=0.10) reports 90 percent confidence intervals. The report also shows whether estimation converged, how many iterations it took, elapsed time, and where the transition probabilities came from. The Simulation Study shows the complete report.

Advanced API

Use econirl.estimation.nfxp.NFXPEstimator when you need direct control over the model inputs and optimizer. See the NFXPEstimator source for the low-level interface.