Skip to content

Constraints

Warning

These functions are not user-facing and are called internally by the optimization methods (see Optimize). They are listed here for reference only. Their API may change without notice.

constraints

Define optimisation constraints from PyPSA networks with Linopy.

Functions:

pypsa.optimization.constraints.define_committability_variables_constraints_with_fixed_upper_limit

define_committability_variables_constraints_with_fixed_upper_limit(n: Network, sns: Index, component: str, attr: str) -> None

Define upper limit constraints for committable unit status variables with fixed limits.

This function sets the upper limit of committable variables (status, start-up, shut-down) for components with fixed upper limits. The upper limit corresponds to:

a) The installed number of modules for committable, non-extendable components with modularity. The number of modules is calculated as: nominal_capacity / module_size (e.g., p_nom / p_nom_mod)

b) The value 1 for all committable components without modularity, regardless of whether they are extendable or not.

For case a), if the number of modules is not an integer, the function raises a ValueError.

Parameters:

  • n (Network) –

    Network instance containing the model and component data

  • sns (Index) –

    Set of snapshots for which to define the constraints

  • component (str) –

    Name of the network component (e.g. "Generator", "Link")

  • attr (str) –

    Name of the capacity attribute (e.g. "p_nom" for nominal power)

Returns:

  • None

Raises:

  • ValueError

    If non-extendable modular components have nominal capacity that is not an integer multiple of their module size

Notes

This function is part of the modular unit commitment formulation that allows committable components to have discrete capacity expansion.

pypsa.optimization.constraints.define_committability_variables_constraints_with_variable_upper_limit

define_committability_variables_constraints_with_variable_upper_limit(n: Network, sns: Index, component: str, attr: str) -> None

Define upper limit constraints for committable unit status variables with variable limits.

This function sets the upper limit of committable variables (status, start-up, shut-down) to the variable n_mod for all committable, extendable, and modular components.

The constraint enforces that the number of committed units cannot exceed the total number of installed modules, which is itself a decision variable in the optimization.

Parameters:

  • n (Network) –

    Network instance containing the model and component data

  • sns (Index) –

    Set of snapshots for which to define the constraints

  • component (str) –

    Name of the network component (e.g. "Generator", "Link")

  • attr (str) –

    Name of the capacity attribute (e.g. "p_nom" for nominal power)

Notes

This function is part of the modular unit commitment formulation that allows committable and extendable components to have discrete capacity expansion. The number of committed units is constrained by the optimized number of modules.

pypsa.optimization.constraints.define_fixed_nominal_constraints

define_fixed_nominal_constraints(n: Network, component: str, attr: str) -> None

Define constraints for fixing component capacities to specified values.

Sets constraints to fix nominal (capacity) variables of components to values specified in the corresponding '_set' attribute.

Applies to Generator (p_nom), Line (s_nom), Transformer (s_nom), Link (p_nom), Store (e_nom), StorageUnit (p_nom).

Parameters:

  • n (Network) –

    Network instance containing the model and component data

  • component (str) –

    Name of the network component (e.g. "Generator", "StorageUnit")

  • attr (str) –

    Name of the capacity attribute (e.g. "p_nom" for nominal power)

Notes

The function only creates constraints for components that have non-NaN values in their '{attr}_set' attribute.

pypsa.optimization.constraints.define_fixed_operation_constraints

define_fixed_operation_constraints(n: Network, sns: Index, component: str, attr: str) -> None

Define constraints for fixing operational variables to specified values.

Sets constraints to fix dispatch variables of components to values specified in the corresponding '_set' attribute.

Applies to Generator (p), Line (s), Transformer (s), Link (p), Store (e), StorageUnit (p_dispatch, p_store, state_of_charge).

Parameters:

  • n (Network) –

    Network instance containing the model and component data

  • sns (Index) –

    Set of snapshots for which to define the constraints

  • component (str) –

    Name of the network component (e.g. "Generator", "StorageUnit")

  • attr (str) –

    Name of the dispatch attribute (e.g. "p" for active power)

Notes

This function is useful for modeling must-run generators, fixed imports/exports, or pre-committed dispatch decisions.

The function only creates constraints for snapshots and components where the '{attr}_set' values are not NaN and the component is active.

For StorageUnit components, if p_set is specified (via attr="p"), the constraint fixes the net power (p_dispatch - p_store) to the given values. Positive p_set means net discharge, negative means net charge.

pypsa.optimization.constraints.define_kirchhoff_voltage_constraints

define_kirchhoff_voltage_constraints(n: Network, sns: Index) -> None

Define Kirchhoff's Voltage Law constraints for networks.

Creates constraints ensuring that the sum of potential differences across branches around all cycles in the network must sum to zero. For each cycle in the network graph, the constraint enforces:

sum_{l in cycle} x_l * s_l = 0

where x_l : series reactance or resistance of branch l (depending on AC/DC) s_l : branch flow variable for branch l in the cycle

Applies to Line, Transformer, and Link (passive branch components).

Parameters:

  • n (Network) –

    Network instance containing the model and component data

  • sns (Index) –

    Set of snapshots for which to define the constraints

Notes

While there are different formulations of KVL, the cycle-based formulation was found to be much faster than other formulations due to its sparsity, as shown in [3]_.

The function first determines the network topology including cycles for each network component (AC and DC sub-networks), then creates constraints for each cycle.

For multi-investment period models, the function creates separate constraints for each investment period, reflecting the changing network topology over time.

The impedances are scaled by 1e5 to improve numerical conditioning.

References

[3] J. Hörsch et al., "Linear optimal power flow using cycle flows," Electric Power Systems Research, vol. 158, pp. 126-135, 2018, https://doi.org/10.1016/j.epsr.2020.106908

pypsa.optimization.constraints.define_modular_constraints

define_modular_constraints(n: Network, component: str, attr: str) -> None

Define constraints for modular capacity expansion.

Sets constraints ensuring that the optimal capacity of a component is an integer multiple of a specified module size. This implements discrete capacity expansion for components with modular units.

For each modular component, the constraint enforces:

capacity = n_modules * module_size

where n_modules is an integer decision variable and module_size is the specified size of each module.

Applies to Generator (p_nom), Line (s_nom), Transformer (s_nom), Link (p_nom), Store (e_nom), StorageUnit (p_nom).

Parameters:

  • n (Network) –

    Network instance containing the model and component data

  • component (str) –

    Name of the network component (e.g. "Generator", "StorageUnit")

  • attr (str) –

    Name of the capacity attribute (e.g. "p_nom" for nominal power)

Notes

This function is used for components where capacity expansion must occur in discrete steps rather than continuous values, reflecting the reality of many energy system technologies.

The function only applies to components that are both extendable and have a positive module size specified in the '{attr}_mod' attribute.

pypsa.optimization.constraints.define_nodal_balance_constraints

define_nodal_balance_constraints(n: Network, sns: Index, transmission_losses: bool | int | dict = False, buses: Sequence | None = None, suffix: str = '') -> None

Define energy balance constraints at each node.

Creates constraints ensuring that the sum of power injections at each node equals the demand at that node for each snapshot. This is the core constraint implementing Kirchhoff's Current Law (KCL) in the power system model. However, the logic is not limited to power networks and spans to other energy carriers.

Using an example of power system, the general form of the constraint is:

sum(power_injections) = sum(power_withdrawals)

where power injections include generation, storage discharge, and incoming branch flows, while power withdrawals include loads, storage charging, and outgoing branch flows.

Applies to Generator (p), Line (s), Transformer (s), Link (p), Process (p), Store (p), Load (p), StorageUnit (p_dispatch, p_store).

Notes
  • StorageUnit net power (p_dispatch - p_store) is calculated after optimization
  • StorageUnit (spill) var is not in the nodal balance - it's handled internally within the storage unit energy balance

Parameters:

  • n (Network) –

    Network instance containing the model and component data

  • sns (Index) –

    Set of snapshots for which to define the constraints

  • transmission_losses (int | dict, default: 0 ) –

    If truthy, transmission losses are considered in the power balance.

  • buses (Sequence | None, default: None ) –

    Subset of buses for which to define constraints; if None, all buses are used

  • suffix (str, default: "" ) –

    Optional suffix to append to constraint names and dimensions

Notes

Link components with multiple buses are handled with their respective efficiency factors for conversion between energy carriers.

Process components are handled with their respective rate factors.

The function raises an error if there's a bus with non-zero load but no connected components to provide power.

pypsa.optimization.constraints.define_nominal_constraints_for_extendables

define_nominal_constraints_for_extendables(n: Network, component: str, attr: str) -> None

Define capacity constraints for extendable components.

Sets capacity expansion constraints for components with extendable capacities. For each component, the constraint enforces:

min_capacity ≤ capacity ≤ max_capacity

where capacity is a decision variable representing the component's optimal capacity.

Applies to Generator (p_nom), Line (s_nom), Transformer (s_nom), Link (p_nom), Process (p_nom), Store (e_nom), StorageUnit (p_nom).

Parameters:

  • n (Network) –

    Network instance containing the model and component data

  • component (str) –

    Name of the network component (e.g. "Generator", "StorageUnit")

  • attr (str) –

    Name of the capacity attribute (e.g. "p_nom" for nominal power)

Notes

Components with infinite max_capacity values are handled through masking to avoid solver issues, particularly with GLPK which doesn't accept infinite values in constraints.

pypsa.optimization.constraints.define_operational_constraints_for_committables

define_operational_constraints_for_committables(n: Network, sns: Index, component: str) -> None

Define operational constraints for committable components.

Sets operational constraints for components with unit commitment decisions. Supports both fixed-capacity and extendable committable components (using big-M formulation for the latter).

Applies to Components

Generator, Link

Parameters:

  • n (Network) –

    Network instance containing the model and component data

  • sns (Index) –

    Set of snapshots for which to define the constraints

  • component (str) –

    Name of the network component ("Generator" or "Link")

Notes

The linearized approximation of the unit commitment problem is possible with flag n._linearized_uc. Here linearization implies that p_min_pu is fractional, ie component can start up any fraction of its capacity. The linearization is based on [2]_.

For components with equal start-up and shut-down costs, additional tightening constraints are applied to improve the linear relaxation.

References

[2] Y. Hua, C. Liu, J. Zhang, "Representing Operational Flexibility in Generation Expansion Planning Through Convex Relaxation of Unit Commitment," IEEE Transactions on Power Systems, vol. 32, no. 5, pp. 3854-3865, 2017, https://doi.org/10.1109/TPWRS.2017.2735026

pypsa.optimization.constraints.define_operational_constraints_for_extendables

define_operational_constraints_for_extendables(n: Network, sns: Index, component: str, attr: str, transmission_losses: bool | int | dict = False) -> None

Define operational constraints (lower-/upper bound) for extendable components.

Sets operational constraints for extendable components based on their bounds. For each component, the constraint enforces:

lower_bound ≤ dispatch ≤ upper_bound

where lower_bound and upper_bound are computed from the component's nominal capacity and min/max per unit values.

Applies to Generator (p), Line (s), Transformer (s),Process (p), Link (p), Store (e), StorageUnit (p_dispatch, p_store, state_of_charge).

Parameters:

  • n (Network) –

    Network instance containing the model and component data

  • sns (Index) –

    Set of snapshots for which to define the constraints

  • component (str) –

    Name of the network component (e.g. "Generator", "Link")

  • attr (str) –

    Name of the attribute to constrain (e.g. "p" for active power)

  • transmission_losses (int | dict, default: False ) –

    If truthy, transmission losses are considered in the operational constraints for passive branches.

pypsa.optimization.constraints.define_operational_constraints_for_non_extendables

define_operational_constraints_for_non_extendables(n: Network, sns: Index, component: str, attr: str, transmission_losses: bool | int | dict = False) -> None

Define operational constraints (lower-/upper bound).

Sets operational constraints for a subset of non-extendable and non-committable components based on their bounds. For each component, the constraint enforces:

lower_bound ≤ dispatch ≤ upper_bound

where lower_bound and upper_bound are computed from the component's nominal capacity and min/max per unit values.

Applies to Generator (p), Line (s), Transformer (s), Link (p), Process(p), Store (e), StorageUnit (p_dispatch, p_store, state_of_charge).

Parameters:

  • n (Network) –

    Network instance containing the model and component data

  • sns (Index) –

    Set of snapshots for which to define the constraints

  • component (str) –

    Name of the network component (e.g. "Generator", "Link")

  • attr (str) –

    Name of the attribute to constrain (e.g. "p" for active power)

  • transmission_losses (int | dict, default: False ) –

    If truthy, transmission losses are considered in the operational constraints for passive branches.

Notes

For passive branches with transmission losses, the constraint accounts for the losses in both directions, see justification in [1]_.

References

[1] F. Neumann, T. Brown, "Transmission losses in power system optimization models: A comparison of heuristic and exact solution methods," Applied Energy, 2022, https://doi.org/10.1016/j.apenergy.2022.118859

pypsa.optimization.constraints.define_ramp_limit_constraints

define_ramp_limit_constraints(n: Network, sns: Index, component: str, attr: str) -> None

Define ramp rate limit constraints for components.

Sets ramp rate constraints to limit the change in output between consecutive time periods. The constraints are defined for fixed, extendable, and committable components, with different formulations for each case.

Applies to Generator (p), Link (p) and Process (p).

Parameters:

  • n (Network) –

    Network instance containing the model and component data

  • sns (Index) –

    Set of snapshots for which to define the constraints

  • component (str) –

    Name of the network component (e.g. "Generator")

  • attr (str) –

    Name of the dispatch attribute (e.g. "p" for active power)

Notes

For rolling horizon optimization, the function handles linking between optimization windows by including the previous snapshot's dispatch value.

For committable components, ramp constraints incorporate the unit commitment status and special ramp limits for start-up and shut-down periods.

For extendable components, ramp constraints are defined relative to the variable capacity, ensuring consistency in the optimization.

pypsa.optimization.constraints.define_secant_loss_constraints

define_secant_loss_constraints(n: Network, sns: Index, component: str, atol: float = 1, rtol: float = 0.1, max_segments: int = 20) -> None

Approximate transmission losses using piecewise linear secants.

Applies to Line and Transformer (passive branch components when transmission_losses are used).

Creates secant constraints to the quadratic loss curve L(p) = r * p^2 for passive branches. The secant-based approximation overestimates losses and is independent of s_nom_max. The number of segments is determined automatically from the error tolerances. See [1] for details.

Called via n.optimize(transmission_losses=True) or n.optimize(transmission_losses={"mode": "secants", ...}).

Parameters:

  • n (Network) –

    Network instance containing the model and branch data

  • sns (Index) –

    Set of snapshots for which to define the constraints

  • component (str) –

    Name of the passive branch component (e.g. "Line", "Transformer")

  • atol (float, default: 1 ) –

    Absolute error tolerance between the quadratic loss curve and its piecewise linear approximation; controls segment density for small flows

  • rtol (float, default: 0.1 ) –

    Relative error tolerance; controls segment density for large flows where atol alone would produce too many segments

  • max_segments (int, default: 20 ) –

    Safety cap on the number of segments per direction. The total number of constraints may be at most 2 * max_segments per branch.

References

[1] https://github.com/PyPSA/PyPSA/pull/1495

pypsa.optimization.constraints.define_storage_unit_constraints

define_storage_unit_constraints(n: Network, sns: Index) -> None

Define energy balance constraints for storage units.

Creates constraints ensuring energy conservation for storage units over time. For each storage unit and snapshot, the constraint enforces:

soc(t) = standing_eff * soc(t-1) + eff_store * p_store(t) - (1/eff_dispatch) * p_dispatch(t) - spill(t) + inflow(t)

where soc is the state of charge, p_store and p_dispatch are the charging and discharging power variables, and the efficiencies account for energy losses.

Applies to StorageUnit (p_dispatch, p_store, state_of_charge, spill).

Parameters:

  • n (Network) –

    Network instance containing the model and component data

  • sns (Index) –

    Set of snapshots for which to define the constraints

Notes

The function handles different storage operating modes: - Cyclic storage (returning to initial state at the end of the period) - Non-cyclic storage (with specified initial state of charge)

For multi-investment period models, the function supports both cycling within each period and carrying state of charge between periods.

Three key flags control the behavior:

  • C (cyclic_state_of_charge): If True, globally cycle state of charge from the last snapshot back to the first snapshot across all periods.
  • CP (cyclic_state_of_charge_per_period): If True, cycle state of charge within each investment period (last snapshot of period wraps to first).
  • IP (state_of_charge_initial_per_period): If True, reset to initial state_of_charge_initial value at the start of each period.

When CP=True and IP=True simultaneously, CP takes precedence (wrapping behavior).

Standing losses are applied based on the elapsed hours between snapshots.

pypsa.optimization.constraints.define_store_constraints

define_store_constraints(n: Network, sns: Index) -> None

Define energy balance constraints for stores.

Creates constraints ensuring energy conservation for store components over time. For each store and snapshot, the constraint enforces:

e(t) = eff_stand * e(t-1) + p(t) * elapsed_hours

where e(t) : energy level at time t eff_stand : standing efficiency (1 - standing_loss)^elapsed_hours e(t-1) : energy level at previous time step p(t) : energy charging (positive), or discharging (negative) elapsed_hours: duration of the time step

Applies to Store (e, p).

Parameters:

  • n (Network) –

    Network instance containing the model and component data

  • sns (Index) –

    Set of snapshots for which to define the constraints

Notes

Stores differ from storage units in that they have a single power variable that can be positive (charging) or negative (discharging) rather than separate variables for charge and discharge.

The function handles different store operating modes: - Cyclic storage (returning to initial energy level at the end of the period) - Non-cyclic storage (with specified initial energy level)

For multi-investment period models, the function supports both cycling within each period and carrying energy between periods.

Three key flags control the behavior:

  • C (e_cyclic): If True, globally cycle energy level from the last snapshot back to the first snapshot across all periods.
  • CP (e_cyclic_per_period): If True, cycle energy level within each investment period (last snapshot of period wraps to first).
  • IP (e_initial_per_period): If True, reset to initial e_initial value at the start of each period.

When CP=True and IP=True simultaneously, CP takes precedence (wrapping behavior).

Standing losses are applied based on the elapsed hours between snapshots.

pypsa.optimization.constraints.define_tangent_loss_constraints

define_tangent_loss_constraints(n: Network, sns: Index, component: str, segments: int) -> None

Approximate transmission losses using piecewise linear tangents.

Applies to Line and Transformer (passive branch components when transmission_losses are used).

The tangent-based approximation underestimates losses. See equations (39)-(46) in [1] for details.

Called via n.optimize(transmission_losses={"mode": "tangents", "segments": N}).

Parameters:

  • n (Network) –

    Network instance containing the model and branch data

  • sns (Index) –

    Set of snapshots for which to define the constraints

  • component (str) –

    Name of the passive branch component (e.g. "Line", "Transformer")

  • segments (int) –

    Number of tangent segments to use in the piecewise linearization of the quadratic loss function. Higher values increase accuracy but also computational complexity.

References

[1] F. Neumann, T. Brown, "Transmission losses in power system optimization models: A comparison of heuristic and exact solution methods," Applied Energy, 2022, https://doi.org/10.1016/j.apenergy.2022.118859

pypsa.optimization.constraints.define_total_supply_constraints

define_total_supply_constraints(n: Network, sns: Sequence, component: str = 'Generator') -> None

Define energy sum constraints for generators.

Creates constraints limiting the total energy generated by each generator over the specified snapshots. The constraints can enforce both minimum and maximum energy production requirements.

For generators with e_sum_min, the constraint enforces:

sum(p(t) * weighting(t)) ≥ e_sum_min

For generators with e_sum_max, the constraint enforces:

sum(p(t) * weighting(t)) ≤ e_sum_max

where the sum is taken over all snapshots and weighting accounts for the duration of each snapshot.

Applies to Generator (by default, but component parameter can be changed).

Parameters:

  • n (Network) –

    Network instance containing the model and component data

  • sns (Sequence) –

    Set of snapshots for which to define the constraints

  • component (str, default: "Generator" ) –

    Name of the network component to apply the constraints to

Notes

These constraints are useful for modeling: - Minimum energy production requirements (e.g., contracted energy delivery) - Maximum energy production limits (e.g., fuel availability, water reservoir limits) - Must-run generators with flexibility in when to produce

The constraints only apply to generators that have finite e_sum_min or e_sum_max values specified.

global_constraints

Define global constraints for optimisation problems with Linopy.

Functions:

pypsa.optimization.global_constraints.define_growth_limit

define_growth_limit(n: Network, sns: Index) -> None

Constraint new installed capacity per investment period.

Parameters:

  • n (Network) –

    The network to apply constraints to.

  • sns (list - like) –

    Set of snapshots to which the constraint should be applied.

pypsa.optimization.global_constraints.define_nominal_constraints_per_bus_carrier

define_nominal_constraints_per_bus_carrier(n: Network, sns: Index) -> None

Set an capacity expansion limit for assets of the same carrier at the same bus.

The function searches for columns in the buses dataframe matching the pattern "nom_{min/max}{carrier}". In case the constraint should only be defined for one investment period, the column name can be constructed according to "nom{carrier}" where period must be in n.investment_periods.

Parameters:

  • n (Network) –

    The network to apply constraints to.

  • sns (list - like) –

    Set of snapshots to which the constraint should be applied.

pypsa.optimization.global_constraints.define_operational_limit

define_operational_limit(n: Network, sns: Index) -> None

Define operational limit constraints.

It limits the net production of a carrier taking into account generator, storage units and stores.

Parameters:

  • n (Network) –

    The network to apply constraints to.

  • sns (list - like) –

    Set of snapshots to which the constraint should be applied.

pypsa.optimization.global_constraints.define_primary_energy_limit

define_primary_energy_limit(n: Network, sns: Index) -> None

Define primary energy constraints.

It limits the byproducts of primary energy sources (defined by carriers) such as CO2.

Parameters:

  • n (Network) –

    The network to apply constraints to.

  • sns (list - like) –

    Set of snapshots to which the constraint should be applied.

pypsa.optimization.global_constraints.define_tech_capacity_expansion_limit

define_tech_capacity_expansion_limit(n: Network, sns: Sequence) -> None

Define per-carrier and potentially per-bus capacity expansion limits.

Parameters:

  • n (Network) –

    The network to apply constraints to.

  • sns (list - like) –

    Set of snapshots to which the constraint should be applied.

pypsa.optimization.global_constraints.define_transmission_expansion_cost_limit

define_transmission_expansion_cost_limit(n: Network, sns: Index) -> None

Set a limit for line expansion costs.

For the capacity expansion only the carriers 'AC' and 'DC' are considered.

Parameters:

  • n (Network) –

    The network to apply constraints to.

  • sns (list - like) –

    Set of snapshots to which the constraint should be applied.

pypsa.optimization.global_constraints.define_transmission_volume_expansion_limit

define_transmission_volume_expansion_limit(n: Network, sns: Sequence) -> None

Set a limit for line volume expansion.

For the capacity expansion only the carriers 'AC' and 'DC' are considered.

Parameters:

  • n (Network) –

    The network to apply constraints to.

  • sns (list - like) –

    Set of snapshots to which the constraint should be applied.