flexmeasures.data.models.planning.highspy_optimization
Direct HiGHS (highspy) implementation of the device scheduler.
Warning
TWO MODELS TO KEEP IN SYNC
This module deliberately duplicates the mathematical model of
flexmeasures.data.models.planning.linear_optimization.device_scheduler()
(the Pyomo implementation), building the LP/MILP directly with the HiGHS
Python API (highspy) instead. The Pyomo implementation is the semantic
reference: any change to the variables, constraints or objective in
device_scheduler MUST be mirrored here (and vice versa), and the
equivalence tests in tests/test_highspy_equivalence.py should be
extended accordingly. This trade-off (a second model to maintain) was
accepted because bypassing the Pyomo layer cuts roughly a second (single
device) to several seconds (multiple devices) of model construction and
solution-ingestion overhead per scheduling job, while the direct build
takes milliseconds.
Deviations from the Pyomo implementation (all verified against the behavior of
the appsi_highs path):
ems_flow_commitment_equalitiesis not built. On the Pyomo path this constraint family returns(None, expr, None), i.e. a constraint without bounds, which ends up as a free (vacuous) row in HiGHS. We skip building the free rows altogether.Rows whose computed bounds are impossible to satisfy for any finite value (upper bound of -inf, or lower bound of +inf, as happens when a commitment quantity is +/-inf) are skipped. On the Pyomo path such rows are rejected by HiGHS’
addRow(called by appsi) and thereby silently dropped, with the same net effect.Solver results and model objects are lightweight shims (see
HighspySolverResultsandHighspyModel) that expose the attributes callers actually consume, rather than Pyomo objects.
Functions
- flexmeasures.data.models.planning.highspy_optimization.device_scheduler_highspy(device_constraints: list[DataFrame], ems_constraints: DataFrame | list[DataFrame], commitment_quantities: list[Series] | None = None, commitment_downwards_deviation_price: list[Series] | list[float] | None = None, commitment_upwards_deviation_price: list[Series] | list[float] | None = None, commitments: list[DataFrame] | list[Commitment] | None = None, initial_stock: float | list[float] = 0, stock_groups: dict[int, list[int]] | None = None, ems_constraint_groups: list[list[int]] | None = None, device_power_bands: list[list[tuple[float, float]] | None] | None = None) tuple[list[Series], float, HighspySolverResults, HighspyModel]
Direct HiGHS implementation of
device_scheduler.Same inputs and same return contract as
flexmeasures.data.models.planning.linear_optimization.device_scheduler(), which also documents the semantics of all arguments; the third and fourth returned objects are lightweight shims rather than Pyomo objects (seeHighspySolverResultsandHighspyModel).
Classes
- class flexmeasures.data.models.planning.highspy_optimization.HighspyModel
Small stand-in for the Pyomo
ConcreteModelreturned bydevice_scheduler.Exposes the attributes that callers and tests consume:
commitment_costs: dict of realized costs per (original) commitmentcommodity_costs: dict of realized costs per commoditycosts: the objective value (a float;pyomo.environ.value()passes floats through unchanged, sovalue(model.costs)keeps working)dandj: the device and datetime index rangesems_power,device_power_up,device_power_down,device_power_sign: indexed variable views supportingvar[d, j].valueandvar.extract_values()
- __init__()