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
fix(plan): score plan selection on the plan as optimised, not as clipped
clip_export_slots and clip_charge_slots set the charge/export percentage shown
on the plan and sent to the inverter. Measured across the random benchmark,
export clipping changes the mid-case cost by exactly 0.00 on every call - it is
a no-op in the expected world - but it still moves the metric, entirely through
the PV10 branch, by an amount that depends on plan shape: 7 of 12 scenarios
taxed, 0 improved, up to +4.25.
That tax lands between optimisation and should_replace_plan, so plan selection
was partly deciding on a difference clipping invented rather than one the plans
really have. A plan taxed 4.25 could lose to one taxed 0.0 on that alone. By
then the slot is usually hours out and will be re-planned many times before it
executes, so constraining its PV10 branch today buys nothing.
Clipping is unchanged - the executed and displayed percentages are exactly as
before. calculate_plan now keeps a snapshot of the plan taken before clipping
and scores selection on that. Both sides fall back to the clipped plans
together when either snapshot is missing, so a fresh plan is never scored
untaxed against a taxed incumbent. The snapshot is persisted with the plan so a
restart does not lose it.
An earlier attempt made clipping itself span both traces. That fixed the metric
but changed the executed percentages, which is the wrong trade: the percentage
should reflect the expected case.
Tests: plan_scoring_pair is unit tested including the never-mix fallback, the
save/load round trip covers the snapshot, and a new plan_preclip test drives
two real recomputes on a scenario where clipping demonstrably taxes the metric
(3.49) and asserts the snapshot scores no worse than the executed plan. Taking
the snapshot after clipping instead makes that test fail.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
self.log("Previous plan best metric is {} (cost {}) and new plan best metric is {} (cost {})".format(dp2(metric_prev), dp2(cost_prev), dp2(metric), dp2(cost)))
self.log("New plan metric is not significantly better (metric_min_improvement_plan {}) than previous plan, using previous plan".format(self.metric_min_improvement_plan))
self.log("New plan metric is significantly better from previous plan, using new plan")
1284
1316
else:
1285
1317
self.log("New plan is a cost-neutral improvement but less fragmented ({} vs {} segments), using new plan".format(fragmentation_new, fragmentation_prev))
1286
1318
1319
+
# Carry the pre-clip snapshot of whichever plan we kept into the next cycle
1320
+
self.plan_preclip=preclip_new
1321
+
1287
1322
# Plan is now valid
1288
1323
self.log("Plan valid is now true after recompute was {}".format(self.plan_valid))
0 commit comments