econirl
EconIRL is a Python package for structural dynamic discrete choice and inverse reinforcement learning. Use it to estimate forward-looking choice models, recover rewards, and predict behaviour under policy changes.
If you are new to these models, read this page as a map: first install the package, then choose an estimator, then use the estimator-specific pages for the math, assumptions, evidence, and examples.
Install
You can install EconIRL via:
pip install econirl
Estimators
Start with Choosing an Estimator for the estimator chooser, the canonical NFXP case, reward targets, transitions, and identification strategies.
The links below are method pages. Open one after you know the decision problem, the data you have, and the reward object you want to recover.
NFXP · CCP · MPEC · UFXP · NNES · TD-CCP · MCE-IRL · Neural MCE-IRL · AIRL · RHIP · f-IRL · GLADIUS · IQ-Learn
Theory
See Theory for the proof map behind the core estimators: soft Bellman equivalence, reward identification, classical DDC inversion, IRL identification boundaries, and the GLADIUS empirical-risk objective.
Replications
See Replications for the terse paper-number ledger. That page is about direct paper-number comparisons; broader synthetic evidence lives in the simulation studies.
Example
Here is an example that estimates Rust (1987):
from econirl.datasets import load_rust_bus, rust_bus_reward_spec
from econirl import NFXP
df = load_rust_bus()
reward = rust_bus_reward_spec(n_states=90) # explicit features, your own names
model = NFXP(n_states=90, discount=0.9999, utility=reward)
model.fit(df, state="mileage_bin", action="replaced", id="bus_id")
print(model.summary())
The report shows data coverage, identification, estimates, uncertainty, and model fit.
================================================================================
Dynamic Discrete Choice Estimation Results
================================================================================
Method: NFXP (Nested Fixed Point) Observations: 9,410
Optimizer: BHHH Individuals: 90
Family: structural (linear utility) Discount (β): 0.9999
Scale (σ): 1.0
Date: 2026-07-25
[1] DATA
State space: 90 states x 2 actions
Periods per individual: ~120
Obs per state: max 901 . p95 703 . p50 61 . p5 4 . min 2
State coverage: 52/90 visited (58%)
Single-action states: 14
[2] PRE-ESTIMATION CHECKS
Reward features (K): 2
Design rank: 2/2 Condition: 5.2e+01
Contrast rank: 2/2 Contrast condition: 1.0e+02
Verdict: identified -- every reward parameter varies across actions
[3] FIRST-STAGE TRANSITION ESTIMATION
Transition source: estimated from fitted panel
Method: empirical frequencies (multinomial MLE)
Transitions used: N = 9,410 Free parameters: 72
Rows with full support: 90/180
Std err across cells: max 0.2722 . p50 0.0258 . min 0.0000
Held fixed in stage two (block-diagonal information).
--------------------------------------------------------------------------------
[4] RESULTS
4a. Estimation
coef std err t P>|t| [0.025 0.975]
operating_cost 0.0010 0.0004 2.58 0.010 0.0002 0.0018
replacement_cost 3.0723 0.0740 41.54 0.000 2.9273 3.2172
4b. Identification
Hessian condition: 72,739.9 Min eigenvalue: 180.93
Status: Potentially weakly identified
4c. Inference & fit
Converged: yes
Iterations: 5
Estimation time: 6.04 seconds
Message: Converged
SE method: robust (sandwich)
Log-lik: -1,900.33
AIC/BIC: 3,804.7 / 3,819.0
accuracy 94.9%
================================================================================
Counterfactuals
A fitted model evaluates policy changes. The counterfactual compares the baseline and counterfactual policies over long-run demand and welfare. Raising the replacement cost lowers the long-run replacement rate and lets buses run to higher mileage.
cf = model.counterfactual(replacement_cost=4.0) # raise the replacement cost
print(cf.summary())
==========================================================================
Counterfactual Summary
==========================================================================
Type 3: reward parameter change Oracle: none
Change: parameters [0.001, 3.072] -> [0.001, 4.0]
--------------------------------------------------------------------------
baseline counterfactual change
Action rate a=0 (long-run) 0.947 0.971 +0.023
Action rate a=1 (long-run) 0.053 0.029 -0.023
Long-run state mean 10.502 16.612 +6.110
Expected value E_mu[V] 339.703 -2.482 -342.186
--------------------------------------------------------------------------
Policy shift |dpi|: max 0.03 . p95 0.03 . p50 0.03 . p5 0.03
Welfare change: -342.29 utils (mean states) , -342.19 (stationary)
(welfare = E[V], the inclusive value / consumer surplus)
==========================================================================