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
A regular (non-scoped) flex-context commitment now binds each device individually against its baseline, instead of binding the aggregate flow of all the commodity's devices. This appears to be an unreleased regression introduced by #1946 (multi-commodity support), and it contradicts the original intent (commitments are electricity/commodity-scoped aggregate commitments).
convert_commitments_to_subcommitments then enumerates each of these as its own commitment c, whose deviation constraint sums ems_power over just {d} — so each device's own flow is held to the baseline, with its own deviation penalty.
Note that #1946's internal commitment does aggregate correctly:
FlowCommitment(name=f"{commodity} net energy", device=commodity_devices, device_group=commodity, ...) # device = list of all commodity devices
So user commitments should follow the same shape.
Impact
A commitment baseline: 10 MW on a commodity with N devices currently penalises each device for deviating from 10 MW, rather than penalising the sum of the N devices deviating from 10 MW. These give very different schedules (and costs) once a commodity has more than one device.
Unreleased: Add multi‑commodity support to device scheduler #1946 is not in any tagged release (latest release v0.33.1 predates it), so this can be fixed on main/v1.0.0.dev without a released-behaviour migration.
Suggested fix
In convert_to_commitments, bind oneFlowCommitment per (commitment, commodity) over all of that commodity's devices, mirroring the internal net-energy commitment:
(Canonical indices from self.device_inventory, e.g. commodity_to_devices.) The current per-device warning-when-empty behaviour still applies when a commodity has no devices.
Test gap
test_commitment_commodity_does_not_bind_other_commodity_devices and test_commitments_in_commodity_contexts_are_converted only use one device per commodity, so they pass under both the per-device and the aggregate implementations. Add a case with two+ devices of the same commodity and assert the sum is bound (mirroring the aggregate assertion in #2295's test_sensor_scoped_commitment_binds_aggregate_of_selected_devices).
#2295 adds explicit scoped (subset) aggregate commitments. Fixing this regression makes an unscoped commitment aggregate over its whole commodity again; the sensors/group scopes remain the way to aggregate over a chosen subset.
Summary
A regular (non-scoped) flex-context commitment now binds each device individually against its baseline, instead of binding the aggregate flow of all the commodity's devices. This appears to be an unreleased regression introduced by #1946 (multi-commodity support), and it contradicts the original intent (commitments are electricity/commodity-scoped aggregate commitments).
Surfaced while reviewing #2295: #2295 (comment)
Evidence (git bisect of
StorageScheduler.convert_to_commitments)Before #1946 (
003c145c5^) — one EMS-level commitment per spec,devicedefaulting toNone, i.e. aggregated over all devices:After #1946 (current
main) — one commitment per device:convert_commitments_to_subcommitmentsthen enumerates each of these as its own commitmentc, whose deviation constraint sumsems_powerover just{d}— so each device's own flow is held to the baseline, with its own deviation penalty.Note that #1946's internal commitment does aggregate correctly:
So user commitments should follow the same shape.
Impact
baseline: 10 MWon a commodity with N devices currently penalises each device for deviating from 10 MW, rather than penalising the sum of the N devices deviating from 10 MW. These give very different schedules (and costs) once a commodity has more than one device.v0.33.1predates it), so this can be fixed onmain/v1.0.0.devwithout a released-behaviour migration.Suggested fix
In
convert_to_commitments, bind oneFlowCommitmentper (commitment, commodity) over all of that commodity's devices, mirroring the internal net-energy commitment:(Canonical indices from
self.device_inventory, e.g.commodity_to_devices.) The current per-device warning-when-empty behaviour still applies when a commodity has no devices.Test gap
test_commitment_commodity_does_not_bind_other_commodity_devicesandtest_commitments_in_commodity_contexts_are_convertedonly use one device per commodity, so they pass under both the per-device and the aggregate implementations. Add a case with two+ devices of the same commodity and assert the sum is bound (mirroring the aggregate assertion in #2295'stest_sensor_scoped_commitment_binds_aggregate_of_selected_devices).Relation to #2295
#2295 adds explicit scoped (subset) aggregate commitments. Fixing this regression makes an unscoped commitment aggregate over its whole commodity again; the
sensors/groupscopes remain the way to aggregate over a chosen subset.🤖 Filed with Claude Code after a review question from @Flix6x on #2295.