BatiPathway
Renovation pathway optimizer for residential building stocks.
BatiPathway decides which renovation combination to apply to each building in a stock so as to minimize Net Present Cost (NPC) subject to policy constraints (GHG caps, energy caps, primary energy per m², electric peak, renovation-rate caps, minimum EPC class).
It implements the optimization core of SHAPE (Rit et al., Applied Energy 2024) as a vectorized multidimensional multiple-choice knapsack problem (MMCKP) — a binary MILP built with linopy and solved by default with the open-source HiGHS solver.
The heavy lifting — enumerating valid renovation combinations and simulating their energy
consumption — happens in an upstream simulation package. BatiPathway consumes that package's
output (a single xarray.Dataset) and performs only the selection optimization.
- Status: 0.1.0 (Alpha)
- Python: ≥ 3.11 (tested on 3.11, 3.12, 3.13)
- License: MIT
Installation
pip install batipathway
Or from source:
git clone https://gitlab.com/energytransition/BatiPathway.git
cd BatiPathway
pip install -e ".[dev]"
Optional extras: gurobi (Gurobi solver), docs (Sphinx docs), plot (seaborn), dev
(test/lint tooling).
Quick start
import batipathway as bp
import xarray as xr
# Dataset produced by the upstream simulation package
ds = xr.open_dataset("renovation_options.nc")
config = bp.ScenarioConfig(
discount_rate=0.04,
growth_rate=0.02,
ghg_cap={2050: 2_000.0},
pe_per_m2_cap={2050: 80.0},
)
model = bp.build_model(bp.validate_input(ds), config)
bp.solve(model)
decisions = bp.extract_decisions(model, ds)
kpis = bp.compute_kpis(decisions, ds, config)
print(f"Total NPC: {kpis['total_npc']:.2e} €")
The typical flow is validate_input → build_model → solve → extract_decisions →
compute_kpis. See examples/ for runnable scenarios.
How it works
For each building b, the upstream package enumerates valid renovation combinations c
(including the do-nothing baseline). BatiPathway introduces a binary variable
x[b, c] ∈ {0, 1} and selects exactly one combination per building to minimize total NPC:
min Σ_{b,c} x[b,c] · npc[b,c]
The per-combination NPC coefficient is pre-aggregated into a scalar (discounted investment
plus block-aggregated, annualized energy billing), so the objective is a single inner
product. Policy targets are added as linear constraints, each independently disableable via
ScenarioConfig:
| Constraint | Config field | SHAPE ref |
|---|---|---|
| Annual GHG cap | ghg_cap |
O_GHG_12 |
| Annual total final-energy cap | energy_cap |
O_EC |
| Average primary energy per m² | pe_per_m2_cap |
O_EC_EPC |
| Electric peak cap | peak_electric_factor |
O_PE |
| Renovation-rate cap | reno_count_cap |
O_nb_reno, Eq. (13) |
| Minimum EPC class | min_epc_class_by_year |
O_class_EPC |
See docs/theory.md for the full formulation and its mapping to the paper.
Input data
BatiPathway expects a single xarray.Dataset with these dimensions: building,
combination, year, carrier, gesture_type. Required variables are valid,
is_baseline, consumption, investment, is_renovating, and area, plus exogenous
energy_price and emission_factor on a full annual year_full axis. Optional variables
(peak_electric, epc_energy_class, pe_factor) unlock the corresponding constraints.
validate_input enforces the schema strictly; pass coerce=True for sensible automatic
fixes. The authoritative reference is docs/input_schema.md, and a
complete synthetic example lives in tests/fixtures.py:make_synthetic_dataset.
Documentation
The full documentation (built with Sphinx) lives in docs/:
installation.md— install instructionstheory.md— mathematical formulation and SHAPE mappinginput_schema.md— normative input schema referencetutorial.md— end-to-end walkthroughapi.md— API reference
Development
pip install -e ".[dev]"
ruff check src/ tests/ # lint
ruff format --check src/ tests/ # format check
mypy src/batipathway/ # type-check (strict)
pytest --cov # tests
These mirror the CI pipeline (.github/workflows/ci.yml), which runs on Python 3.11–3.13.
References
- Rit, M., Thomas, A., Villot, J., Thorel, M., Garreau, E., & Girard, R. (2024). SHAPE: A temporal optimization model for residential buildings retrofit to discuss policy objectives. Applied Energy, 361, 122936. doi:10.1016/j.apenergy.2024.122936
- Hofmann, F. (2023). Linopy: Linear optimization with n-dimensional labeled variables. Journal of Open Source Software, 8(84), 4823.
License
MIT — see LICENSE.
Metadata
Release files for batipathway 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| batipathway-0.1.0.tar.gz | 171.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| batipathway-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 199.0 kB
Release files / batipathway-0.1.0.tar.gz
| Download URL | batipathway-0.1.0.tar.gz |
|---|---|
| Size | 171.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
75e8abdb6030c8828f295518346b5ca49504804be07edeac2a9990a81891531b
|
|
BLAKE2b-256 checksum How to use checksums |
7f30fd36d3a2fb3077d8cd4d08f020fdbeb6abc683d8546a607f01c08d16b706
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / batipathway-0.1.0-py3-none-any.whl
| Download URL | batipathway-0.1.0-py3-none-any.whl |
|---|---|
| Size | 27.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bd24d36cf0f690f951560d7e9271c1bb1b7331537401f11ca50754e49c6f23ee
|
|
BLAKE2b-256 checksum How to use checksums |
0655b45ce8aac2a2a68afa380d4717c7c8f969fb1401a99559174b45678daa2d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|