Your job is to design the charging current profile for a lithium-ion cell that must be rushed from empty to 90% state-of-charge in at most half an hour, over and over, without wrecking the cell. The physics engine is PyBaMM's Doyle-Fuller-Newman model with the full degradation stack switched on — SEI growth (also on crack surfaces), particle swelling and cracking, stress-driven loss of active material, lumped thermal dynamics, plus an overvoltage capacity-loss term dQ/dt = 0.3·max(V − 4.2, 0)³. Aggressive current charges fast but grows SEI, cracks particles and burns capacity above 4.2 V; timid current fails to reach the SOC target inside the window. Your protocol must thread that needle across cells that differ in ambient temperature, ageing state and cycle count.
A protocol is a 41-entry table of charging currents (amps), indexed by SOC bins [0.10, 0.12), [0.12, 0.14), …, [0.88, 0.90); below SOC 0.10 the first entry applies. The verifier rebuilds a smooth (sigmoid-blended) current profile from your table and simulates the full cycling experiment — discharge to 3.0 V, CV hold, YOUR charge step, rest — for the instance's number of cycles, on its own trusted copy of the model.
Hard Constraints
- Solution format:
/app/methods/main/solver.pyexposingsolve(instance: dict, time_budget_s: float) -> list[41 floats], currents in amps; values are clipped to [0.05, 6.0] A. - The charge step gets at most 1800 s per cycle and terminates only
when SOC reaches the target. The target must genuinely be met: a
successful charge stops exactly at it, so if any cycle ends below
soc_target − 0.002the whole instance scores the failure loss 3.0. There is no top-up rescue and no voltage-cap termination — overvoltage is penalized through physics (the Q_loss ODE), not clipped for you. - Per instance your solver gets a 600 s wall-clock budget in the verifier. Overrunning it is recorded and the child is killed shortly after; if you printed a complete table before that, the last one you printed is what gets scored, and if you printed nothing usable the instance scores the failure loss 3.0.
- Do not modify
/app/fastcharge.pyor the verifier; your solver may read every file under/appand simulate freely. - The verifier re-simulates your table from scratch; only the 41 numbers you return matter — any SOH your own simulation claims is ignored.
table_protocolbuilds a SYMBOLIC pybamm expression: the callable is evaluated once with symbolic variables, so Pythonif soc < x:branching silently misbehaves. Use the provided sigmoid-table builder.
What You Have
/app/fastcharge.py— the exact evaluator the verifier uses (table_protocol,evaluate_protocol, model options, parameters)./app/instances_visible.json— three development instances:base(10 cycles, 308.5 K),hot(318.15 K),aged_sei(SEI kinetics ×8). Held-out instances vary the same knobs (temperature, ageing severity, cycle count) within physically sensible ranges — no new mechanisms, but you cannot memorize the pool./app/methods/main/solver.py— a working weak baseline (3-step CC staircase 5.6/4.8/4.0 A) to replace./app/probe_window.py— a ~20 s single-cycle diagnostic that reports, for a candidate table, how much of the 1800 s window it uses, whether it reaches the target, its peak voltage, seconds above 4.2 V and the resulting overvoltage capacity loss. Far cheaper than a scored run./app/selfcheck.py— ~1-minute smoke test of the toolchain.- One full 10-cycle simulation of one instance takes ≈60 s on 4 CPUs (IDAKLU). Budget your experiments.
What You Submit
The modified /app/methods/main/solver.py (plus any helper files it
imports from /app/methods/). It must return the 41-float current
table within the per-instance budget, for any instance dict shaped
like the visible ones.
How It Is Judged
Per hidden instance, the verifier simulates your protocol and scores
loss = −ln((SOH_end − 0.6)/0.4); lower is better, 0.0 would be a
pristine cell. Simulation failure, a malformed table, a short-charge,
or a budget overrun with no usable table printed all score 3.0.
The task score is the MEAN loss over the hidden instances, mapped to a
reward band that rises as the loss falls. The band is bounded above: no
submission can score 1.0 or higher, however good its protocol is.