OPT-20: a refusal probe asks only PROBE_W, not the whole trade
The probe's trade was sized at the probing battery's rating. Its SAFETY-73
pin held 200 W of that, and the allocator put the rest on a battery with no
mode range (one in a maintenance phase): TEST-23 OPT-15 g7, -2300 W on A in
its maintenance charge for 34 s, grid 3100 W.
modetrade.decide() now asks PROBE_W for the probing battery plus what the
other chargers would have had without the probe; size() adds the probe on top
of their share, or files PROBE_W exactly, or nothing. _mode_trade() carries
the pin only on the ticks it is filed, so the window's first and last cycle
do not move another battery's share either. Modes off and modes on with no
probe are unchanged (bf9019e digests). Tests: test_opt20.py.
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude
parent
bf9019e70d
commit
06339a2446
@@ -2441,6 +2441,19 @@ class Controller:
|
||||
tick = self.mode_tick
|
||||
if tick is None:
|
||||
return False
|
||||
if tick.action == modetrade.CHARGE:
|
||||
# OPT-20: the ask carries PROBE_W for exactly the probes whose pin
|
||||
# is filed this tick. `decide()` ran before the pin was (or the
|
||||
# window closed since), so the two can differ by one cycle; left
|
||||
# alone, the allocator takes the pin's watts out of another
|
||||
# battery's share, or hands them to one it can reach.
|
||||
pins = _ctl.PROBE_W * sum(
|
||||
1 for c in claims if c.source == "refused"
|
||||
and c.kind == "set" and c.value < 0)
|
||||
if pins != tick.probe_w:
|
||||
tick = self.mode_tick = dataclasses.replace(
|
||||
tick, ask_w=tick.ask_w + tick.probe_w - pins,
|
||||
probe_w=pins)
|
||||
size = modetrade.size(tick, self.loop_bound(claims)
|
||||
if tick.action else None, self.arb_headroom_w)
|
||||
runs = self.mode_runs
|
||||
|
||||
Reference in New Issue
Block a user