Module ml4opf.formulations.ac
ACOPF
Sub-modules
ml4opf.formulations.ac.model
-
Base class for ACOPF proxy models
ml4opf.formulations.ac.problem
-
ACOPF Problem data class
ml4opf.formulations.ac.violation
-
Class interface for ACOPF constraints, objective, etc.
Classes
class ACModel
-
OPFModel
for ACOPFAncestors
- OPFModel
- abc.ABC
Subclasses
Class variables
var problem : ACProblem
var violation : ACViolation
Methods
def evaluate_model(self, reduction: str | None = None, inner_reduction: str | None = None) ‑> dict[str, torch.Tensor]
-
Evaluate the model on the test data.
Args
reduction
:str
, optional- Reduction method for the metrics. Defaults to None. Must be one of "mean", "sum","max", "none". If specified, each value in the returned dictionary will be a scalar. Otherwise, they are arrays of shape (n_test_samples,)
inner_reduction
:str
, optional- Reduction method for turning metrics calculated per component to per sample. Defaults to None. Must be one of "mean", "sum","max", "none".
Returns
dict[str, Tensor]
-
Dictionary containing Tensor metrics of the model's performance.
vm_lower
: Lower bound on the voltage magnitude.vm_upper
: Upper bound on the voltage magnitude.pg_lower
: Lower bound on the real power generation.pg_upper
: Upper bound on the real power generation.qg_lower
: Lower bound on the reactive power generation.qg_upper
: Upper bound on the reactive power generation.thrm_1
: Thermal limit violation fromthrm_2
: Thermal limit violation top_balance
: Active power balance violation.q_balance
: Reactive power balance violation.pg_mae
: Mean absolute error of the real power generation.qg_mae
: Mean absolute error of the reactive power generation.vm_mae
: Mean absolute error of the voltage magnitude.va_mae
: Mean absolute error of the voltage angle. (if not bus-wise and va not in predictions, skipped)dva_mae
: Mean absolute error of the angle difference. (only if not bus-wise)obj_mape
: Mean absolute percent error of the objective value.
def predict(self, pd: torch.Tensor, qd: torch.Tensor) ‑> dict[str, torch.Tensor]
-
Predict the ACOPF primal solution for a given set of loads.
Args
pd
:Tensor
- Active power demand per load.
qd
:Tensor
- Reactive power demand per load.
Returns
dict[str, Tensor]
-
Dictionary containing the predicted primal solution.
pg
: Active power generation per generator or per bus.qg
: Reactive power generation per generator or per bus.vm
: Voltage magnitude per bus.va
: Voltage angle per bus.
Inherited members
class ACProblem (data_directory: str, dataset_name: str = 'ACOPF', **parse_kwargs)
-
OPFProblem
for ACOPFAncestors
- OPFProblem
- abc.ABC
Instance variables
prop default_combos : dict[str, list[str]]
-
Default combos for ACOPF:
-
input: pd, qd
-
target: pg, qg, vm, va
-
prop default_order : list[str]
-
Default order for ACOPF: input, target
prop feasibility_check : dict[str, str]
-
Default feasibility check for ACOPF:
-
termination_status: "LOCALLY_SOLVED"
-
primal_status: "FEASIBLE_POINT"
-
dual_status: "FEASIBLE_POINT"
-
prop violation : ACViolation
-
ACPViolation
object, created upon first access.
Inherited members
class ACViolation (data: dict[str, torch.Tensor])
-
OPFViolation
for ACOPFInitialize internal Module state, shared by both nn.Module and ScriptModule.
Ancestors
- OPFViolation
- torch.nn.modules.module.Module
- abc.ABC
Methods
def angle_difference(self, va: torch.Tensor) ‑> torch.Tensor
-
Compute the angle differences per branch given the voltage angles per bus.
\text{dva} = \boldsymbol{\theta}_{f} - \boldsymbol{\theta}_{t}
Args
va
:Tensor
- Voltage angles per bus ( \boldsymbol{\theta} ). (batch_size, nbus)
Returns
Tensor
- Angle differences per branch. (batch_size, nbranch)
def balance_residual(self,
pd: torch.Tensor,
qd: torch.Tensor,
pg: torch.Tensor,
qg: torch.Tensor,
vm: torch.Tensor,
pf: torch.Tensor,
pt: torch.Tensor,
qf: torch.Tensor,
qt: torch.Tensor,
clamp: bool = False,
embed_method: str = 'pad') ‑> tuple[torch.Tensor, torch.Tensor]-
Calculate the power balance residual.
Component-wise tensors are first embedded to the bus level using
embed_method
.The shunt parameters g_s, b_s are assumed to be constant, matching the reference case.
\text{p_viol} = \text{pg_bus} - \text{pd_bus} - \text{pt_bus} - \text{pf_bus} - \text{gs_bus} \times \text{vm}^2 \text{q_viol} = \text{qg_bus} - \text{qd_bus} - \text{qt_bus} - \text{qf_bus} + \text{bs_bus} \times \text{vm}^2
Args
pd
:Tensor
- Active power demand per bus. (batch_size, nbus)
qd
:Tensor
- Reactive power demand per bus. (batch_size, nbus)
pg
:Tensor
- Active power generation per generator. (batch_size, ngen)
qg
:Tensor
- Reactive power generation per generator. (batch_size, ngen)
vm
:Tensor
- Voltage magnitude per bus. (batch_size, nbus)
pf
:Tensor
- Active power flow from bus per branch. (batch_size, nbranch)
pt
:Tensor
- Active power flow to bus per branch. (batch_size, nbranch)
qf
:Tensor
- Reactive power flow from bus per branch. (batch_size, nbranch)
qt
:Tensor
- Reactive power flow to bus per branch. (batch_size, nbranch)
clamp
:bool
, optional- Apply an absolute value to the residual. Defaults to False.
embed_method
:str
, optional- Embedding method for bus-level components. Defaults to 'pad'. Must be one of 'pad', 'dense_matrix', or 'matrix. See
IncidenceMixin.*_to_bus
.
Returns
Tensor
- Power balance residual for active power. (batch_size, nbus)
Tensor
- Power balance residual for reactive power. (batch_size, nbus)
def calc_violations(self,
pd: torch.Tensor,
qd: torch.Tensor,
pg: torch.Tensor,
qg: torch.Tensor,
vm: torch.Tensor,
va: torch.Tensor | None = None,
dva: torch.Tensor | None = None,
flows: tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor] | None = None,
reduction: str | None = 'mean',
clamp: bool = True) ‑> dict[str, torch.Tensor]-
Calculate the violation of all the constraints.
The reduction is applied across the component dimension - e.g., 'mean' will do violation.mean(dim=1) where each violation is (batch, components)
Args
pd
:Tensor
- Real power demand. (batch, loads)
qd
:Tensor
- Reactive power demand. (batch, loads)
pg
:Tensor
- Real power generation. (batch, gens)
qg
:Tensor
- Reactive power generation. (batch, gens)
vm
:Tensor
- Voltage magnitude. (batch, buses)
va
:Tensor
, optional- Voltage angle. (batch, buses)
dva
:Tensor
, optional- Voltage angle difference. (batch, branches)
flows
:tuple[Tensor, Tensor, Tensor, Tensor]
, optional- Power flows. (pf, pt, qf, qt)
reduction
:str
, optional- Reduction method. Defaults to 'mean'. Must be one of 'mean', 'sum', 'none'.
clamp
:bool
, optional- Clamp the residual to be non-negative (extract violations). Defaults to True.
Returns
- dict[str, Tensor]: Dictionary of violations.
vm_lower
: Voltage magnitude lower bound violation.vm_upper
: Voltage magnitude upper bound violation.pg_lower
: Real power generation lower bound violation.pg_upper
: Real power generation upper bound violation.qg_lower
: Reactive power generation lower bound violation.qg_upper
: Reactive power generation upper bound violation.thrm_1
: Thermal limit from violation.thrm_2
: Thermal limit to violation.p_balance
: Real power balance violation.q_balance
: Reactive power balance violation.dva_lower
: Voltage angle difference lower bound violation.dva_upper
: Voltage angle difference upper bound violation. def dva_bound_residual(self, dva: torch.Tensor, clamp: bool = False) ‑> tuple[torch.Tensor, torch.Tensor]
-
Calculate the voltage angle difference bound residual.
g_{\text{lower}} = \text{angmin} - \text{dva} g_{\text{upper}} = \text{dva} - \text{angmax}
Args
dva
:Tensor
- Voltage angle difference per branch. (batch_size, nbranch)
clamp
:bool
, optional- Clamp the residual to be non-negative (extract violations). Defaults to False.
Returns
Tensor
- Lower bound residual. (batch_size, nbranch)
Tensor
- Upper bound residual. (batch_size, nbranch)
def flows_from_voltage(self, vm: torch.Tensor, dva: torch.Tensor) ‑> tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor]
-
Compute the power flows given the voltage magnitude and angle differences.
Args
vm
:Tensor
- Voltage magnitude per bus ( \mathbf{v} ). (batch_size, nbus)
dva
:Tensor
- Angle differences per branch ( \boldsymbol{\theta}_f - \boldsymbol{\theta}_t ). (batch_size, nbranch)
Returns
Tensor
- Real power flow per branch ( \mathbf{p}_f ). (batch_size, nbranch)
Tensor
- Real power flow per branch ( \mathbf{p}_t ). (batch_size, nbranch)
Tensor
- Reactive power flow per branch ( \mathbf{q}_f ). (batch_size, nbranch)
Tensor
- Reactive power flow per branch ( \mathbf{q}_t ). (batch_size, nbranch)
def flows_from_voltage_bus(self, vm: torch.Tensor, va: torch.Tensor) ‑> tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor]
-
Compute the power flows given the voltage magnitude per bus and voltage angles per bus.
This function computes angle differences then calls
ACPViolation.flows_from_voltage
. See the docstring ofACPViolation.flows_from_voltage
for more details.Args
vm
:Tensor
- Voltage magnitude per bus ( \mathbf{v} ). (batch_size, nbus)
va
:Tensor
- Voltage angle per bus ( \boldsymbol{\theta} ). (batch_size, nbus)
Returns
Tensor
- Real power flow per branch ( \mathbf{p}_f ). (batch_size, nbranch)
Tensor
- Real power flow per branch ( \mathbf{p}_t ). (batch_size, nbranch)
Tensor
- Reactive power flow per branch ( \mathbf{q}_f ). (batch_size, nbranch)
Tensor
- Reactive power flow per branch ( \mathbf{q}_t ). (batch_size, nbranch)
def objective(self, pg: torch.Tensor) ‑> torch.Tensor
-
Compute the objective function given the active power generation per generator.
Args
pg
:Tensor
- Active power generation per generator. (batch_size, ngen)
Returns
Tensor
- Objective function value. (batch_size)
def pg_bound_residual(self, pg: torch.Tensor, clamp: bool = False) ‑> tuple[torch.Tensor, torch.Tensor]
-
Calculate the active power generation bound residual.
g_{\text{lower}} = \text{pmin} - \text{pg} g_{\text{upper}} = \text{pg} - \text{pmax}
Args
pg
:Tensor
- Active power generation per generator. (batch_size, ngen)
clamp
:bool
, optional- Clamp the residual to be non-negative (extract violations). Defaults to False.
Returns
Tensor
- Lower bound residual. (batch_size, ngen)
Tensor
- Upper bound residual. (batch_size, ngen)
def qg_bound_residual(self, qg: torch.Tensor, clamp: bool = False) ‑> tuple[torch.Tensor, torch.Tensor]
-
Calculate the reactive power generation bound residual.
g_{\text{lower}} = \text{qmin} - \text{qg} g_{\text{upper}} = \text{qg} - \text{qmax}
Args
qg
:Tensor
- Reactive power generation per generator. (batch_size, ngen)
clamp
:bool
, optional- Clamp the residual to be non-negative (extract violations). Defaults to False.
Returns
Tensor
- Lower bound residual. (batch_size, ngen)
Tensor
- Upper bound residual. (batch_size, ngen)
def thermal_residual(self,
pf: torch.Tensor,
pt: torch.Tensor,
qf: torch.Tensor,
qt: torch.Tensor,
clamp: bool = False) ‑> tuple[torch.Tensor, torch.Tensor]-
Calculate the thermal limit residual.
g_{\text{thrm}_1} = \text{pf}^2 + \text{qf}^2 - \text{s1max} g_{\text{thrm}_2} = \text{pt}^2 + \text{qt}^2 - \text{s2max}
Args
pf
:Tensor
- Active power flow from bus per branch. (batch_size, nbranch)
pt
:Tensor
- Active power flow to bus per branch. (batch_size, nbranch)
qf
:Tensor
- Reactive power flow from bus per branch. (batch_size, nbranch)
qt
:Tensor
- Reactive power flow to bus per branch. (batch_size, nbranch)
clamp
:bool
, optional- Clamp the residual to be non-negative (extract violations). Defaults to False.
Returns
Tensor
- Thermal limit residual for from branch. (batch_size, nbranch)
Tensor
- Thermal limit residual for to branch. (batch_size, nbranch)
def vm_bound_residual(self, vm: torch.Tensor, clamp: bool = False) ‑> tuple[torch.Tensor, torch.Tensor]
-
Calculate the voltage magnitude bound residual.
g_{\text{lower}} = \text{vmin} - \text{vm} g_{\text{upper}} = \text{vm} - \text{vmax}
Args
vm
:Tensor
- Voltage magnitude per bus. (batch_size, nbus)
clamp
:bool
, optional- Clamp the residual to be non-negative (extract violations). Defaults to False.
Returns
Tensor
- Lower bound residual. (batch_size, nbus)
Tensor
- Upper bound residual. (batch_size, nbus)
Inherited members