NoraAI — BatterySwapAI 2026
Participant-authored submission for the
BatterySwapAI 2026 Challenge.
This repository contains everything needed to reproduce the stored models and
run inference / plan generation used by the competition runner.
Approach (short)
- Prognostics: sklearn
HistGradientBoostingRegressor quantile models
(P10 / P50 / P90) for remaining useful life (RUL).
- Planning: greedy urgent-first work-order planner under travel / worker
constraints (OR-Tools available for VRPTW experiments; competition default
is greedy for runtime).
- Digital twin (local research pipeline): open-loop + twin stress-testing
of scheduling policies against operational cost (see
src/simulation/).
Twin code supports policy selection; the competition entry point is
script.py → NoraPlanner.
Repository layout
| Path | Role |
|---|
script.py | Hugging Face / Docker entry point |
src/features/ | Health-indicator feature extraction |
src/prognostics/ | RUL labels, sklearn quantile training, predictor |
src/scheduling/ | Priority scoring + greedy / hybrid / VRPTW planners |
src/submission/nora_planner.py | Official Planner implementation |
src/simulation/ | Evaluation, digital twin, official metric helpers |
submission/nora_planner.pickle | Pickled planner stub loaded at runtime |
data/processed/models/ | Trained sklearn quantile model + config |
scripts/train_sklearn_submission.py | Train + refresh stored model artifacts |
Dockerfile | Competition container build |
requirements.txt | Declared dependencies (runtime image may ignore extras) |
LICENSE | MIT (participant-authored code) |
Setup
1python3 -m venv .venv
2source .venv/bin/activate
3pip install -U pip
4pip install -r requirements.txt
5# Optional local-only extras (training / dashboards / tests):
6pip install -r requirements.dev.txt
Competition dataset (gated): follow organizer instructions for
batteryswapaichallenge/BatterySwapAI-2026-Test-Train (or the public split
mounted by the runner). Locally we expect data under data/real/{public,private,train}
or /tmp/data in the competition image.
Preprocessing
- Place / mount the official split folders (locations, metrics, EOL, scenarios).
- For local retraining, build a processed feature table (parquet) used by
scripts/train_sklearn_submission.py. The competition image does not
ship features.parquet; at inference time NoraPlanner extracts
last-window health indicators on the fly from truncated scenario metrics
(src/features/health_indicators.py).
Typical local feature build (research pipeline):
1# After ingesting raw/official data into data/raw and data/processed
2python -m scripts.build_features # if using the full local Makefile pipeline
3# or follow Makefile targets: make ingest-real / make features (when available)
Training / stored-model generation
The submission model is sklearn-only (competition allowlist friendly).
1# Requires local processed features + batteries.csv
2python scripts/train_sklearn_submission.py
This writes:
data/processed/models/sklearn_quantile.joblib
data/processed/models/config.joblib (primary: sklearn)
submission/nora_planner.pickle
Environment knobs used by the training script (defaults shown):
SKLEARN_MAX_BATTERIES=200
SKLEARN_SUBSAMPLE_EVERY_N=48
SKLEARN_MAX_ROWS=30000
Inference (competition / Docker)
The runner executes:
script.py loads NoraPlanner, calls batteryswap_public.utils.make_submissions,
and writes submission.csv.
Environment variables:
| Variable | Default | Meaning |
|---|
BATTERYSWAP_DATASET_PATH | /tmp/data | Dataset root with split folders |
BATTERYSWAP_SPLITS | public,private | Comma-separated splits |
BATTERYSWAP_SUBMISSION_PATH | submission.csv | Output path |
BATTERYSWAP_PLANNER_PATH | submission/nora_planner.pickle | Optional pickle path |
Local Docker check:
1docker build -t batteryswapai-noraai .
2docker run --name batteryswapai -v ./data/real:/tmp/data:ro batteryswapai-noraai
3docker cp batteryswapai:/app/submission.csv ./docker_submission.csv
Planner behavior (scoring window)
Official evaluation only executes plan days inside planning_window_days,
but plans must still list every battery. NoraPlanner schedules a small set of
lowest-RUL batteries inside the window and parks the rest on days after
the window so the plan stays complete without paying early-swap cost on healthy
batteries.
Digital twin (optional, local)
For policy stress-testing / reports (not required by script.py):
1# Examples from the research Makefile / scripts
2python scripts/run_twin_shootout.py
3python scripts/run_twin_calibration.py
4python scripts/select_submission_policy.py
See docs/DIGITAL_TWIN.md and docs/PRIORITY_B_SPRINT.md when present in a
full checkout.
Dependencies, versions, and licenses
Participant code in this repository is MIT (LICENSE).
Competition / runtime stack
requirements.txt pins minimum versions. Versions observed in the local
repro environment used to prepare artifacts:
| Package | Version (local) | License (upstream) |
|---|
batteryswap_public | 0.3.4 | Provided by organizers (competition package) |
scikit-learn | 1.9.0 | BSD-3-Clause |
numpy | 2.5.2 | BSD-3-Clause |
scipy | 1.18.1 | BSD-3-Clause |
pandas | 2.3.3 | BSD-3-Clause |
joblib | 1.5.3 | BSD-3-Clause |
pyarrow | 25.0.1 | Apache-2.0 |
fastparquet | 2026.5.0 | Apache-2.0 |
ortools | 9.15.6755 | Apache-2.0 |
lifelines | 0.30.3 | MIT |
huggingface_hub | 1.28.0 | Apache-2.0 |
pydantic-settings | 2.15.0 | MIT |
structlog | 26.1.0 | Apache-2.0 / MIT (upstream) |
tqdm | 4.70.0 | MPL-2.0 / MIT (upstream) |
Additional packages listed in requirements.txt (e.g. torch, plotly,
polars, statsmodels) may be unused by the sklearn submission path; the
competition Docker note states custom requirement changes may be ignored in
favor of the organizer image allowlist.
Local-only extras (requirements.dev.txt): LightGBM, scikit-survival,
Streamlit, matplotlib, pytest — not required for the HF script.py path.
Pretrained models
No external pretrained neural checkpoints. The only stored model is the
sklearn quantile ensemble trained by scripts/train_sklearn_submission.py
and shipped under data/processed/models/.
External datasets
- BatterySwapAI 2026 sensor / location / travel / EOL data from the
organizers (Hugging Face dataset
batteryswapaichallenge/BatterySwapAI-2026-Test-Train and competition
mounts). Access and license terms are those of the challenge organizers;
this repo does not redistribute the raw gated dataset.
Security
This repository must not contain passwords, API tokens, private keys, or
.env secrets. If a token was ever exposed via a local git remote URL,
revoke it on Hugging Face and rotate credentials.
Citation / contact
Team / HF user: Atomattias
Challenge: BatterySwapAI 2026 (NORA)