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 ACOPF

Ancestors

Subclasses

Class variables

var problemACProblem
var violationACViolation

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 from

thrm_2: Thermal limit violation to

p_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 ACOPF

Ancestors

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 violationACViolation

ACPViolation object, created upon first access.

Inherited members

class ACViolation (data: dict[str, torch.Tensor])

OPFViolation for ACOPF

Initialize internal Module state, shared by both nn.Module and ScriptModule.

Ancestors

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 of ACPViolation.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