BatterySwapAI 2026 Submission β Survival RUL Model + Urgency-Scored Planner
Solution for the BatterySwapAI 2026 challenge: predicts each battery's Remaining Useful Life (RUL) as a calibrated distribution using a right-censored survival model, then schedules a technician's swap route around those predictions.
This repo started from the official example repository and replaces its dummy median-only RUL model and one-swap-per-day planner with the implementation described below.
Approach
Part 1 β RUL prediction (batteryswap_example/features.py, rul_model.py)
- Voltage/temperature features: rolling mean/min/variance, slope and curvature (rate and acceleration of decline), cumulative time spent below key voltage thresholds, an Arrhenius-adjusted thermal-stress integral, and a lightweight knee-point (changepoint) detector.
- Building-pooled feature aggregates as an ID-free proxy for shared environmental risk between co-located batteries β chosen so it still works on buildings not seen during training, since public/private splits use different buildings than the training split.
SurvivalRULModel: a right-censored Cox proportional-hazards model (vialifelines), with a Weibull AFT fallback, trained on RUL durations synthesized from multiple scenario cuts of the raw timeseries. Returns calibrated p10/p50/p90 RUL quantiles instead of a single point estimate.
Part 2 β Scheduling (batteryswap_example/planner.py)
UrgencyPlanner: a greedy earliest-deadline-first router for the single traveling technician the evaluator simulates.- Swap deadlines are derived from the model's p10 RUL quantile β chosen because the evaluator penalizes a late swap 20x more heavily than an early one by default, so the cost-optimal target sits deep in the early tail of the failure-time distribution.
- Visits to the same building are batched together to amortize the fixed building-change/travel cost, and are deferred until shortly before their deadline rather than scheduled as early as possible, to avoid needless early-replacement penalties.
- Batteries not due within the current planning window are given a placeholder day past the window (the evaluator ignores plan rows past the horizon), so the route only spends travel time on batteries that actually need attention this cycle.
Known limitations
train.pytrains on a small, fixed number of scenario cuts by default (seeDEFAULT_TRAIN_SCENARIOSand the comment above it). Stacking many more scenarios was tried and made the fitted hazard model noticeably worse in local testing, likely because scenario cuts of the same ~460 physical devices are correlated pseudo-replicates rather than independent training examples. A more careful fix (sample weighting, cross-validated regularization, or a proper train/validation split across scenarios) is a natural next step.- Evaluated locally only against the
trainsplit; not yet validated against thepublic/privatesplits or run inside the official Docker image under the full 32GB/CPU-only/30-minute constraints.
Setup
Prerequisites
You need to have the following installed
- git
- Python 3.10+
- Docker
Setting up virtual environment
On Linux / Mac OS / Windows Subsystem for Linux (WSL)
python -m venv venv
source venv/bin/activate
Install dependencies
pip install -r requirements.txt -r requirements.dev.txt
Developing
Develop in virtual environment
Run the training
python batteryswap_example/train.py
Making submissions
Submitting trained models
Trained models or other output used by submission processing (script.py),
must be committed in the git repository.
An example is batteryswap_example/planners/best.pickle.
Test submissions in Docker - recommended
Using Docker allows to have exactly the same software versions as the submissions system.
This helps to ensure there are no errors when running in the submission environment.
NOTE: this requires around 20 GB+ of disk space.
Build Docker image
docker build -t batteryswapai-2026-example .
Make submissions and run evaluation
docker run --name batteryswapai -v ./dataset:/tmp/data batteryswapai-2026-example bash -c "/app/env/bin/python3 script.py && /app/env/bin/python3 -m batteryswap_public.metric"
Copy submission.csv out of container
docker cp batteryswapai:/app/submission.csv ./submission.csv
Create new submission
NOTE: remember to commit and push your changes to the HuggingFace model repository.
Use New submission in the competition application to submit your current code for evaluation.