This release is a pre-release and may not be stable for production use.
equilibria
A Python framework for Computable General Equilibrium modeling
Build CGE models from modular blocks — like LEGO for economists — and check them against GAMS and GEMPACK.
Created by Marlon Molina
Installation • Quick Start • Documentation • Roadmap • Contributing
Why equilibria?
CGE models are usually written in GAMS or GEMPACK. equilibria brings them to Python without giving up the reference implementations: every template is checked against them cell by cell.
| 🧱 Models built from blocks | A model is a stack of blocks, each declaring its parameters, variables and equations. GTAP Standard 7 is eight of them. |
| ✅ Checked against the originals | GAMS and GEMPACK are the source of truth. Parity gates compare every solved cell, same engine on both sides. |
| 🔁 One model, two solve forms | The same model solves as an MCP (PATH, through its C API) or as an NLP (IPOPT), like GAMS's ifMCP. |
| 🌐 Native data I/O | A pure-Python reader and writer for GEMPACK HAR files, a GDX reader, and SAM tools (audit, balancing, MIP → SAM). |
Templates today: GTAP Standard 7 (multi-period, both ifSUB modes),
PEP-1-1 v2.1 (pep_pyomo) and a didactic simple open economy.
Installation
pip install --pre "equilibria[path]"
The release on PyPI is an early alpha (0.6.2a1): the API can still change
before 0.6.2.
The path extra installs path-capi-python,
which MCP solves use. The PATH solver itself is not on PyPI; get it from its authors:
- Download the PATH libraries for your platform from
https://pages.cs.wisc.edu/~ferris/path/julia/ (macOS arm64:
libpath50.silicon.dylibandliblusol.silicon.dylib; Linux:.so; Windows:.dll) and point to them:export PATH_CAPI_LIBPATH=/absolute/path/to/libpath50.silicon.dylib export PATH_CAPI_LIBLUSOL=/absolute/path/to/liblusol.silicon.dylib
- Without a license PATH stops at 300 variables, which is smaller than the
quickstart model. The PATH authors publish a free evaluation license in
https://pages.cs.wisc.edu/~ferris/path/julia/LICENSE; set it as
PATH_LICENSE_STRING.
NLP solves use IPOPT through the ipopt extra (cyipopt), which needs an Ipopt
installation on the system.
Other extras: excel, viz (matplotlib, plotly), poi (PyOptInterface),
modelcache (cloudpickle), docs, all.
To work on equilibria itself, install from source:
git clone https://github.com/mmc00/equilibria.git
cd equilibria
pip install -e ".[pyomo,path,ipopt,excel]"
See Solving with PATH for where equilibria looks for the PATH libraries.
Quick Start
GTAP: a tariff shock
from equilibria import load_bundled
from equilibria.templates.gtap import apply_shock
from equilibria.templates.gtap.gtap_block_model import build_block_model
from equilibria.templates.gtap.gtap_contract import GTAPClosureConfig
from equilibria.templates.gtap.gtap_multiperiod_driver import solve_multiperiod
from equilibria.templates.gtap.welfare_regional import regional_ev
params = load_bundled("gtap", "nus333") # ships in the package
closure = GTAPClosureConfig(
name="base", closure_type="MCP", capital_mobility="sluggish",
fix_endowments=False, fix_taxes=False, fix_technology=False,
if_sub=False, numeraire="pnum",
)
m, _ = build_block_model(params, params.sets, closure, "ROW")
# +10% on the tariff power of US manufacturing exports to ROW, as in a GEMPACK .EXP
apply_shock(m, {"imptx": {("USA", "MFG", "ROW"): 10.0}})
results = solve_multiperiod(m, params, closure, mode="gtap", skip_base_solve=True, solve_check=True)
print(results["shock"]["code"]) # 1 = solved
print(regional_ev(m)) # {'USA': -0.1079..., 'ROW': 0.0885...}
The model solves base → check → shock in one go, as GAMS's loop(tsim).
The full walk-through, including the comparison against GAMS, is the
GTAP quickstart.
PEP: the reference shock
import copy
from pathlib import Path
from pyomo.environ import value
import equilibria.templates
from equilibria.templates.pep_calibration_unified import PEPModelCalibrator
from equilibria.templates.pep_pyomo.pep_pyomo_equations import build_pep_model
from equilibria.templates.pep_pyomo.pep_pyomo_scenarios import apply_sim1_export_tax_cut
from equilibria.templates.pep_pyomo.pep_pyomo_solver import solve_pep
data = Path(equilibria.templates.__file__).parent / "reference" / "pep2" / "data"
state = PEPModelCalibrator(
sam_file=data / "SAM-V2_0.gdx", val_par_file=data / "VAL_PAR.xlsx"
).calibrate()
# SIM1 of the GAMS reference: export tax rates × 0.75, solved as an MCP
shocked = apply_sim1_export_tax_cut(copy.deepcopy(state), factor=0.75)
m = build_pep_model(shocked, variant="base", form="mcp")
print(solve_pep(m).code, round(value(m.GDP_BP), 1)) # 1 46748.2 (GAMS: 46748.2)
See the PEP quickstart.
Data: read and write GEMPACK HAR files
import numpy as np
from equilibria.babel.har import HarWriter, read_har
data = read_har("data/gtap7/gtap7_3x3/basedata.har") # dict[name -> HeaderArray]
vdpp = data["VDPP"]
print(vdpp.long_name, vdpp.array.shape, vdpp.set_names)
with HarWriter("synthetic.har") as w:
w.add_set("REG", ["USA", "ROW"])
w.add_set("COMM", ["AGR", "MFG"])
w.add_array("VDPP", np.array([[1.0, 2.0], [3.0, 4.0]], dtype=np.float32),
set_names=["COMM", "REG"], long_name="domestic private purchases")
More in HAR file I/O and MIP → SAM.
How it is built
A model is a stack of blocks, written for one period and copied once per
period; a shock is one instrument cell that differs in the shock period;
the driver follows a recipe and holds no model logic. The
architecture overview
explains it with pictures, and each rule is an Architecture Decision Record
in docs/adr/.
Status
What matches what, measured: the GTAP coverage matrix against GAMS, the one against GEMPACK, and the PEP coverage matrix. What comes next: docs/roadmap.md.
Examples
examples/cge/ walks through the framework step by step, from sets and
parameters to a model on the Pyomo backend:
python examples/cge/example_01_basic_setup.py
Citation
If you use equilibria in your research, please cite it. GitHub's
"Cite this repository" button reads CITATION.cff; the
archived releases are on Zenodo:
@software{equilibria,
author = {Molina, Marlon},
title = {equilibria: A Python Framework for CGE Modeling},
year = {2026},
doi = {10.5281/zenodo.23675339},
url = {https://github.com/mmc00/equilibria}
}
Contributing
We welcome contributions! See CONTRIBUTING.md for guidelines.
Dev quickstart
uv sync --dev
uv tool install prek && prek install # pre-commit hooks (ruff + ty + hygiene)
prek run --all-files
Hooks are fast hygiene only (format / lint / type, no solver). Use prek, not
pre-commit — same config, faster runner. See CONTRIBUTING.md
for the ty ratchet and the separate parity gates.
License
MIT License - see LICENSE for details.
Acknowledgments
equilibria builds on the shoulders of giants:
- PEP Network - Standard CGE methodology
- GTAP - Global trade analysis
- IFPRI - CGE modeling resources
- Pyomo - Optimization modeling
- The broader CGE modeling community
Created by Marlon Molina • Made with ❤️ for economists who code
Metadata
Release files for equilibria 0.6.2a1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| equilibria-0.6.2a1.tar.gz | 2.2 MB | Without provenance | Details for equilibria-0.6.2a1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| equilibria-0.6.2a1-py3-none-any.whl | Python 3 | none | any | Details for equilibria-0.6.2a1-py3-none-any.whl |
Total release size: 3.5 MB
Release files / equilibria-0.6.2a1.tar.gz
| Download URL | equilibria-0.6.2a1.tar.gz |
|---|---|
| Size | 2.2 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8937d2d8df4f0de1743437a1fa3ff2ccc0ca64eb4c7852a326e7da0d7840a3b2
|
|
BLAKE2b-256 checksum How to use checksums |
d218b557ce4a63114896b5ace367b0d1b6ecd4e17727bbb51e305b4635c4f210
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / equilibria-0.6.2a1-py3-none-any.whl
| Download URL | equilibria-0.6.2a1-py3-none-any.whl |
|---|---|
| Size | 1.4 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
19b66453cb7de02d1a6c0164c4cfcdd25fb22e5493232c105d0e6995ff8c75a3
|
|
BLAKE2b-256 checksum How to use checksums |
f7b4d3499f86766aabf43ce23e49ef371da30b6cc50c630e007a1f11644bd9a0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for equilibria 0.6.2a1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.