You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Tracked follow-up from #275 (DP holds charge for a known-worse future price
on extended horizons) and the design doc docs/superpowers/specs/2026-07-12-dp-continuous-path-reconstruction-fix-design.md
(Option C there). Not being implemented as part of the #275 fix — this is a
larger algorithm redesign, filed here so the idea isn't lost.
The problem it would solve
The DP's backward induction (core/bess/dp_battery_algorithm.py) only
computes its value function V[t, i] at a fixed grid of SOE points
(SOE_STEP_KWH = 0.1) and searches a fixed grid of power actions
(POWER_STEP_KW = 0.2). The real battery's actual SOE almost never lands
exactly on a grid point, so reconstructing the actual schedule (Step 2 of optimize_battery_schedule) has to interpolate V at off-grid states. V has genuine kinks (slope discontinuities) wherever the optimal action
changes character — e.g. crossing BATTERY_EXPORT_THRESHOLD_KWH's
self-throttling cutoff, or a price threshold where exporting stops being
worth it — and linear interpolation across a kink gives a wrong answer.
That's the confirmed root cause of #275, and a smaller, previously-shipped
version of the same mechanism (2026-07-06 guardrail-removal doc).
Two options already tried (grid-snap vs. interpolated recompute) each win
in a different regime (single-day vs. multi-day horizons) — see #275 and the
2026-07-12 design doc for the empirical evidence. Neither eliminates the
error; they just move it around.
What this issue proposes investigating
Remove the fixed grid as the source of the mismatch entirely, via one or
both of:
Solve for the optimal power level analytically instead of grid search.
For a fixed price/state, one-period reward is mostly piecewise-linear in
the charge/discharge power, so the true per-period optimum could be
computed directly (root-finding / closed-form) at the actual continuous
SOE, instead of testing ~150 discrete power values.
Track V as an exact piecewise-linear function of SOE, not a sampled
grid. Classical LP-sensitivity result: for linear dynamics and
piecewise-linear reward, the true value function at each time step is
itself exactly piecewise-linear, with a small number of real breakpoints
— not the artificial ones introduced by uniform 0.1 kWh sampling.
Tracking those breakpoints exactly would make "interpolation" exact
rather than approximate, since there'd be no hidden kink to interpolate
across.
Real algorithm redesign, not a patch — touches _run_dynamic_programming's
core loop and _compute_reward's structure.
Needs proof that the reward function is piecewise-linear/concave enough
for either approach to work cleanly; BATTERY_EXPORT_THRESHOLD_KWH
(dp_battery_algorithm.py:344) is itself a hard discontinuity worth
checking against this assumption.
No existing prototype — 2026-07-06 already flagged this direction as out
of scope for that PR, for the same reasons.
docs/superpowers/specs/2026-07-12-dp-continuous-path-reconstruction-fix-design.md — full options analysis (A: grid-snap, B: finer discretization, C: this issue)
docs/superpowers/specs/2026-07-06-dp-bellman-guardrail-removal-design.md — where the grid-snap-vs-interpolation mechanism was first identified and partially mitigated
Summary
Tracked follow-up from #275 (DP holds charge for a known-worse future price
on extended horizons) and the design doc
docs/superpowers/specs/2026-07-12-dp-continuous-path-reconstruction-fix-design.md(Option C there). Not being implemented as part of the #275 fix — this is a
larger algorithm redesign, filed here so the idea isn't lost.
The problem it would solve
The DP's backward induction (
core/bess/dp_battery_algorithm.py) onlycomputes its value function
V[t, i]at a fixed grid of SOE points(
SOE_STEP_KWH = 0.1) and searches a fixed grid of power actions(
POWER_STEP_KW = 0.2). The real battery's actual SOE almost never landsexactly on a grid point, so reconstructing the actual schedule (Step 2 of
optimize_battery_schedule) has to interpolateVat off-grid states.Vhas genuine kinks (slope discontinuities) wherever the optimal actionchanges character — e.g. crossing
BATTERY_EXPORT_THRESHOLD_KWH'sself-throttling cutoff, or a price threshold where exporting stops being
worth it — and linear interpolation across a kink gives a wrong answer.
That's the confirmed root cause of #275, and a smaller, previously-shipped
version of the same mechanism (2026-07-06 guardrail-removal doc).
Two options already tried (grid-snap vs. interpolated recompute) each win
in a different regime (single-day vs. multi-day horizons) — see #275 and the
2026-07-12 design doc for the empirical evidence. Neither eliminates the
error; they just move it around.
What this issue proposes investigating
Remove the fixed grid as the source of the mismatch entirely, via one or
both of:
For a fixed price/state, one-period reward is mostly piecewise-linear in
the charge/discharge power, so the true per-period optimum could be
computed directly (root-finding / closed-form) at the actual continuous
SOE, instead of testing ~150 discrete power values.
Vas an exact piecewise-linear function of SOE, not a sampledgrid. Classical LP-sensitivity result: for linear dynamics and
piecewise-linear reward, the true value function at each time step is
itself exactly piecewise-linear, with a small number of real breakpoints
— not the artificial ones introduced by uniform 0.1 kWh sampling.
Tracking those breakpoints exactly would make "interpolation" exact
rather than approximate, since there'd be no hidden kink to interpolate
across.
Why this is deferred, not part of #275's fix
_run_dynamic_programming'score loop and
_compute_reward's structure.for either approach to work cleanly;
BATTERY_EXPORT_THRESHOLD_KWH(
dp_battery_algorithm.py:344) is itself a hard discontinuity worthchecking against this assumption.
of scope for that PR, for the same reasons.
approach is chosen.
References
docs/superpowers/specs/2026-07-12-dp-continuous-path-reconstruction-fix-design.md— full options analysis (A: grid-snap, B: finer discretization, C: this issue)docs/superpowers/specs/2026-07-06-dp-bellman-guardrail-removal-design.md— where the grid-snap-vs-interpolation mechanism was first identified and partially mitigated