BatterySwapAI 2026 — survival-model RUL + expected-cost work-order planner
Submission for the BatterySwapAI 2026 challenge
(NORA / Soundsensing). Participant-authored code is released under the MIT License (see LICENSE).
This candidate is protocol REENTRY-C5-PHASE-PEER-VETO-V1, based on the
frozen Try23/C5 source at commit 7d172c7d9ac81ae53f7bf8bd70044337777e9ef1.
Its supporting result is exploratory and post-outcome, not a preregistered
gate: analysis/c5_phase_peer_exploratory_v1/RESULT.json, SHA-256
065f092222af61ed6054cf3dbd0277fadbae46aacc3a1de29984fcd4ef2a95dd.
Approach
- Label reproduction.
bsw/daily.py(reference) /bsw/daily_fast.py(polars, bit-identical) aggregate the hourly series per device-day and reproduce the official EOL criterion exactly (smooth_series()voltage < 2.40 V; 461/461 train devices match). - Remaining-useful-life models. Two complementary forecasters are blended in logit space (
bsw/blend.py):bsw/features.py+bsw/model.py+bsw/ensemble.py: per-device features at cut timeT(only data beforeT: smoothed-voltage level/slopes/extrapolations, raw-voltage statistics, temperature and seasonality, temperature sensitivity, age/replacement history) feed a feature-view-diverse ensemble of multi-horizon gradient-boosted survival models (HistGradientBoostingClassifier, horizon as input, monotone in horizon and voltage) that outputP(EOL <= T + h)on a grid of horizons.- The re-entry component uses static C5 device calibration, guarded by a
target-free compositional certificate. It preserves the full C5 effect
unless either (a) supported pre-/post-
T-42dphases have opposite signs, or (b) the device sign opposes the median of at least three other supported nonzero devices in its current building. A contradiction abstains exactly to the fleet base; missing views never veto. bsw/physics.py: a discharge-curve forecaster on the temperature-compensated voltage (population priordU/dt = r(U)fitted on the train split, device-specific rate multiplier, seasonal room-temperature forecast from the device/building/fleet history beforeT, explicit modelling of the label's temperature filter), giving a second survival CDF.- Blend weights and logit-scale calibrations were determined by building-grouped 6-fold CV on the train split
(
analysis/cv_ensemble.py): OOF planner cost 1416 h/scenario (single GBM: ~1800; oracle: ~101). - Serving uses a causal support guard after two missed weekly reporting intervals: when a device has supplied no observation for at least 14 days, its CDF is set to zero before the unchanged optimizer replans. This avoids extrapolating supervision selected toward streams that later resume to permanently silent devices; an observation stamped exactly at the current cut explicitly cancels the guard.
- Planner.
bsw/sim.pyis an exact, fast re-implementation of the cost accounting ofbatteryswap_public.evaluate.evaluate_plan(time, overtime, daily/weekly limits — including the travel-home carry-over), verified against the official evaluator.bsw/planner.pycomputes, for every device and candidate day, the expected early/late penalty (using the evaluator's conventions for unobserved EOL, per-device data end and emergency visits) and runs a multi-start local search over swap-day assignments minimising expected penalties + exact routing/overtime/limit costs. Devices not worth swapping are scheduled after the window. - Submission.
script.pyloads the stored artifacts (artifacts/) and producessubmission.csvfor all splits viabatteryswap_public.utils.make_submissions. Each scenario is planned from its own inputs only (data up to the scenario start, locations, travel costs, settings).
Reproduction
python -m venv venv && . venv/bin/activate
pip install -r requirements-train.txt # exact versions used (Python 3.10.x)
python train.py --dataset_path /path/to/dataset # writes artifacts/ (GBM ensemble, physics prior, meta.json); ~10 min on 16 cores
BATTERYSWAP_DATASET_PATH=/path/to/dataset BATTERYSWAP_SPLITS=train python script.py
BATTERYSWAP_DATASET_PATH=/path/to/dataset BATTERYSWAP_SPLITS=train BATTERYSWAP_SUBMISSION_PATH=submission.csv python -m batteryswap_public.metric
Training is deterministic (fixed seeds, single-threaded-safe histogram gradient boosting). The dataset is the official
batteryswapaichallenge/BatterySwapAI-2026-Public train split (no external data, no pretrained models).
Files
script.py— competition entry point.train.py— trains the model and writesartifacts/.bsw/— solution package (see above).artifacts/—survival_model.joblib(GBM ensemble, scikit-learn 1.7.2),physics_prior.joblib(population prior + base CDF),meta.json(features, knots, members, blend constants).requirements.txt— the competition runtime requirements (unchanged);requirements-train.txt— pinned versions used for training.THIRD_PARTY.md— third-party dependencies and licenses.
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support