pybhatlib
Python reimplementation of BHATLIB — an open-source library for statistical and econometric matrix-based inference methods.
BHATLIB (Bhat, Clower, Haddad, Jones; UT Austin / Aptech Systems) provides efficient matrix operations, gradient-enabled routines for multivariate distribution evaluation (including Bhat's 2018 MVNCD analytic approximation), and pre-built econometric models.
Installation
git clone https://github.com/UMN-Choi-Lab/pybhatlib.git
cd pybhatlib
pip install -e . # core (NumPy + SciPy + Numba)
pip install -e ".[torch]" # add PyTorch backend (optional GPU)
pip install -e ".[dev]" # add pytest, ruff, mypy
pip install -e ".[all]" # everything (torch + dev)
Quick Start — Multinomial Probit (MNP)
Sample data: examples/data/TRAVELMODE.csv (3 modes — DA / SR / TR, 1125 observations).
from pybhatlib.models.mnp import MNPModel, MNPControl
model = MNPModel(
data="examples/data/TRAVELMODE.csv",
alternatives=["Alt1_ch", "Alt2_ch", "Alt3_ch"],
availability="none",
spec={
"CON_SR": {"Alt1_ch": "sero", "Alt2_ch": "uno", "Alt3_ch": "sero"},
"CON_TR": {"Alt1_ch": "sero", "Alt2_ch": "sero", "Alt3_ch": "uno"},
"IVTT": {"Alt1_ch": "IVTT_DA", "Alt2_ch": "IVTT_SR", "Alt3_ch": "IVTT_TR"},
"OVTT": {"Alt1_ch": "OVTT_DA", "Alt2_ch": "OVTT_SR", "Alt3_ch": "OVTT_TR"},
"COST": {"Alt1_ch": "COST_DA", "Alt2_ch": "COST_SR", "Alt3_ch": "COST_TR"},
},
control=MNPControl(iid=True),
)
results = model.fit()
results.summary()
Quick Start — Multivariate Ordered Response Probit (MORP)
from pybhatlib.models.morp import MORPModel, MORPControl
model = MORPModel(
data=df, # DataFrame or CSV path
dep_vars=["satisfaction", "recommendation"], # ordinal outcome columns
spec={
"income": {"satisfaction": "income", "recommendation": "income"},
"age": {"satisfaction": "age", "recommendation": "age"},
"education": {"satisfaction": "education", "recommendation": "education"},
},
n_categories=[3, 3],
control=MORPControl(iid=True, seed=42),
)
results = model.fit()
results.summary()
A runnable end-to-end example (with morp_ate, morp_predict,
morp_predict_category) is at
examples/tutorials/t05b_morp_ate_predict.ipynb.
Features
Models
- Multinomial Probit (MNP) — IID, flexible covariance, heteroscedastic-only, random coefficients, mixture-of-normals
- Multivariate Ordered Response Probit (MORP) — multiple ordinal outcomes
with shared covariance; per-outcome
specmapping - Multiple Discrete-Continuous Extreme Value (MDCEV) — traditional
(Bhat 2008) and linear (Bhat 2018) outside-good utility specifications,
selected via
MDCEVControl.utility
Numerical core
vecup— vecdup, matdupfull, LDLT decomposition, truncated MVN momentsmatgradient— gradcovcor, gomegxomegax, spherical / Cholesky parameterizationsgradmvn— Bhat (2018) MVNCD analytic approximation with analytic gradients
Estimation
- Multiple SE estimators (
se_method="bhhh" | "hessian" | "sandwich"); BHHH is the default to match GAUSS BHATLIB's_max_CovPar=2. All three are computed at fit time and exposed asse_bhhh/se_hessian/se_sandwich;results.summary()prints a side-by-side diagnostic block (a large Hessian/BHHH divergence is a misspecification signal). MNPControl.active_maskto freeze a subset of parameters at their starting values without recoding the model.verboselevels:0silent,1summary,2per-iteration NLL,3per-iteration parameter / gradient / relative-gradient table.
Backend
- NumPy by default; optional PyTorch backend with GPU support (install with
[torch]). All numerical functions take an optionalxpkwarg.
Post-estimation
- Average Treatment Effects (ATE) with scenario-matrix support, forecasting, per-category MORP probability prediction.
- MORP ATEs from supplied coefficients without re-fitting:
MORPResults.from_estimates(beta, thresholds, correlation)rebuilds a results object from natural-space estimates, andmorp_ate_from_params/morp_joint_probs(mean joint category-combination probabilities, the GAUSSate1.csvequivalent) compute effects directly from them.
Verification
pybhatlib reproduces Table 1 from the BHATLIB paper (Bhat 2018) using the TRAVELMODE dataset (3 modes — DA, SR, TR; 1125 observations):
| Model | Specification | Target LL | Achieved LL | Status |
|---|---|---|---|---|
| (a)(i) | IID errors | -670.956 | -670.956 | exact match |
| (a)(ii) | Flexible covariance | -661.111 | -661.111 | exact match |
| (b) | + AGE45 demographics | -659.285 | -659.284 | exact match |
| (c) | + Random coeff. OVTT | -635.871 | -635.871 | exact match |
| (d) | 2-segment mixture | -634.975 | -632.912 | close (multi-modal) |
Models (a)–(c) reproduce the published estimates and BHHH standard errors to ≤0.001 on every parameter (verified end-to-end against GAUSS 26.1.1 + MaxLik 5.0.9). Model (d) is documented as multi-modal — the Python optimum is a slightly better local mode than the published one.
For MORP, iid=False now uses GAUSS BHATLIB's unit-variance identification by
default (MORPControl.fix_scales=True): the latent-utility variances are fixed
at 1 and only correlations are estimated. The full-covariance MORP_DINING /
MORP_WALK models reproduce the GAUSS mean log-likelihoods (−4.6598 / −3.7591)
and correlation matrices. summary() reports the actual threshold cut-points
(with delta-method standard errors) and a gradient column, matching GAUSS's
output. See docs/plans/MORP_BHATLIB_PARITY.md.
The driving notebooks are
t04h_bhatlib_table1.ipynb and
t04i_bhat2018_table2.ipynb.
Tutorials
A complete tutorial series lives under
examples/tutorials/ as Jupyter notebooks (each with a
matching .py script under python_scripts/):
| Track | Notebooks |
|---|---|
| Foundations | t00_quickstart, t01a_vectorization, t01b_ldlt, t01c_truncated_mvn |
| Matrix gradients | t02a_gradcovcor, t02b_spherical, t02c_chain_rules |
| MVNCD | t03a_mvncd_methods, t03b_mvncd_gradients, t03c_mvncd_rect, t03d_univariate_cdfs, t03e_bhat2018_table1 |
| MNP | t04a_mnp_iid … t04g_mnp_forecasting, t04h_bhatlib_table1, t04i_bhat2018_table2 |
| MORP | t05b_morp_ate_predict |
| MDCEV | t07a_mdcev_trad, t07b_mdcev_lin |
| Backends & verification | t06a_backend_switching, t06b_custom_specs, t06c_gradient_verification |
Contributing
See CONTRIBUTING.md for development setup, the PR-test
workflow, and CODEOWNERS conventions. Key tests:
pytest tests/ # full suite
pytest tests/ -m "not slow" # skip integration tests
pytest tests/ -m torch # PyTorch backend tests only
References
- Bhat, C. R. (2018). New Matrix-Based Methods for the Analytic Evaluation of the Multivariate Cumulative Normal Distribution Function. Transportation Research Part B, 109: 238–256.
- Bhat, C. R., Clower, E., Haddad, A. J., Jones, J. BHATLIB: An Open-Source Library for Statistical and Econometric Matrix-Based Inference Methods in GAUSS.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pybhatlib-0.3.2.tar.gz.
File metadata
- Download URL: pybhatlib-0.3.2.tar.gz
- Upload date:
- Size: 594.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b18e6e805a1517e689c3c340ae53ea64c5d8f3e7c42386846de7241b95a5e845
|
|
| MD5 |
647436bae1e73f1cb70b42fba36704ba
|
|
| BLAKE2b-256 |
4c700380b4dda94263d7543e0827c0de0c4f560fb667c3c34579c547df5f8500
|
Provenance
The following attestation bundles were made for pybhatlib-0.3.2.tar.gz:
Publisher:
publish.yml on UMN-Choi-Lab/pybhatlib
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pybhatlib-0.3.2.tar.gz -
Subject digest:
b18e6e805a1517e689c3c340ae53ea64c5d8f3e7c42386846de7241b95a5e845 - Sigstore transparency entry: 2219650393
- Sigstore integration time:
-
Permalink:
UMN-Choi-Lab/pybhatlib@9c8693c51917bb5e0084dd6a2cd78f238cb45678 -
Branch / Tag:
refs/tags/v0.3.2 - Owner: https://github.com/UMN-Choi-Lab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9c8693c51917bb5e0084dd6a2cd78f238cb45678 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pybhatlib-0.3.2-py3-none-any.whl.
File metadata
- Download URL: pybhatlib-0.3.2-py3-none-any.whl
- Upload date:
- Size: 256.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7a8700105464933d2b404a3d229f2a88cbbe970723f072f6005c06fcbf959fc
|
|
| MD5 |
0688d7aedc83281d7e8864a320ee1338
|
|
| BLAKE2b-256 |
16006ca5c249456f0043d78fcfd69957627d208002fa6e3ee6f275dfe4913620
|
Provenance
The following attestation bundles were made for pybhatlib-0.3.2-py3-none-any.whl:
Publisher:
publish.yml on UMN-Choi-Lab/pybhatlib
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pybhatlib-0.3.2-py3-none-any.whl -
Subject digest:
a7a8700105464933d2b404a3d229f2a88cbbe970723f072f6005c06fcbf959fc - Sigstore transparency entry: 2219650459
- Sigstore integration time:
-
Permalink:
UMN-Choi-Lab/pybhatlib@9c8693c51917bb5e0084dd6a2cd78f238cb45678 -
Branch / Tag:
refs/tags/v0.3.2 - Owner: https://github.com/UMN-Choi-Lab
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9c8693c51917bb5e0084dd6a2cd78f238cb45678 -
Trigger Event:
release
-
Statement type: