Skip to content

flixopt.modeling

Classes

ModelingUtilitiesAbstract

Utility functions for modeling - leveraging xarray for temporal data

Functions

to_binary staticmethod
to_binary(values: DataArray, epsilon: float | None = None, dims: str | list[str] | None = None) -> xr.DataArray

Converts a DataArray to binary {0, 1} values.

Parameters:

Name Type Description Default
values DataArray

Input DataArray to convert to binary

required
epsilon float | None

Tolerance for zero detection (uses CONFIG.Modeling.epsilon if None)

None
dims str | list[str] | None

Dims to keep. Other dimensions are collapsed using .any() -> If any value is 1, all are 1.

None

Returns:

Type Description
DataArray

Binary DataArray with same shape (or collapsed if collapse_non_time=True)

count_consecutive_states staticmethod
count_consecutive_states(binary_values: DataArray | ndarray | list[int, float], dim: str = 'time', epsilon: float | None = None) -> float

Count consecutive steps in the final active state of a binary time series.

This function counts how many consecutive time steps the series remains "on" (non-zero) at the end of the time series. If the final state is "inactive", returns 0.

Parameters:

Name Type Description Default
binary_values DataArray | ndarray | list[int, float]

Binary DataArray with values close to 0 (inactive) or 1 (active).

required
dim str

Dimension along which to count consecutive states.

'time'
epsilon float | None

Tolerance for zero detection. Uses CONFIG.Modeling.epsilon if None.

None

Returns:

Type Description
float

Sum of values in the final consecutive "active" period. Returns 0.0 if the

float

final state is "inactive".

Examples:

>>> arr = xr.DataArray([0, 0, 1, 1, 1, 0, 1, 1], dims=['time'])
>>> ModelingUtilitiesAbstract.count_consecutive_states(arr)
2.0
>>> arr = [0, 0, 1, 0, 1, 1, 1, 1]
>>> ModelingUtilitiesAbstract.count_consecutive_states(arr)
4.0

ModelingUtilities

Functions

compute_consecutive_hours_in_state staticmethod
compute_consecutive_hours_in_state(binary_values: DataArray, hours_per_timestep: int | float, epsilon: float = None) -> float

Computes the final consecutive duration in state 'active' (=1) in hours.

Parameters:

Name Type Description Default
binary_values DataArray

Binary DataArray with 'time' dim, or scalar/array

required
hours_per_timestep int | float

Duration of each timestep in hours

required
epsilon float

Tolerance for zero detection (uses CONFIG.Modeling.epsilon if None)

None

Returns:

Type Description
float

The duration of the final consecutive 'active' period in hours

compute_previous_off_duration staticmethod
compute_previous_off_duration(previous_values: DataArray, hours_per_step: DataArray | float | int) -> float

Compute previous consecutive 'inactive' duration.

Parameters:

Name Type Description Default
previous_values DataArray

DataArray with 'time' dimension

required
hours_per_step DataArray | float | int

Duration of each timestep in hours

required

Returns:

Type Description
float

Previous consecutive inactive duration in hours

get_most_recent_state staticmethod
get_most_recent_state(previous_values: DataArray | None) -> int

Get the most recent binary state from previous values.

Parameters:

Name Type Description Default
previous_values DataArray | None

DataArray with 'time' dimension

required

Returns:

Type Description
int

Most recent binary state (0 or 1)

ModelingPrimitives

Mathematical modeling primitives returning (variables, constraints) tuples

Functions

expression_tracking_variable staticmethod
expression_tracking_variable(model: Submodel, tracked_expression: LinearExpression | Variable, name: str = None, short_name: str = None, bounds: tuple[DataArray, DataArray] = None, coords: str | list[str] | None = None) -> tuple[linopy.Variable, linopy.Constraint]

Creates a variable constrained to equal a given expression.

Mathematical formulation

tracker = expression lower ≤ tracker ≤ upper (if bounds provided)

Parameters:

Name Type Description Default
model Submodel

The submodel to add variables and constraints to

required
tracked_expression LinearExpression | Variable

Expression that the tracker variable must equal

required
name str

Full name for the variable and constraint

None
short_name str

Short name for display purposes

None
bounds tuple[DataArray, DataArray]

Optional (lower_bound, upper_bound) tuple for the tracker variable

None
coords str | list[str] | None

Coordinate dimensions for the variable (None uses all model coords)

None

Returns:

Type Description
tuple[Variable, Constraint]

Tuple of (tracker_variable, tracking_constraint)

consecutive_duration_tracking staticmethod
consecutive_duration_tracking(model: Submodel, state: Variable, name: str = None, short_name: str = None, minimum_duration: DataArray | None = None, maximum_duration: DataArray | None = None, duration_dim: str = 'time', duration_per_step: int | float | DataArray = None, previous_duration: DataArray = 0) -> tuple[dict[str, linopy.Variable], dict[str, linopy.Constraint]]

Creates consecutive duration tracking for a binary state variable.

Tracks how long a binary state has been continuously active (=1). Duration resets to 0 when state becomes inactive (=0).

Mathematical formulation

duration[t] ≤ state[t] · M ∀t duration[t+1] ≤ duration[t] + duration_per_step[t] ∀t duration[t+1] ≥ duration[t] + duration_per_step[t] + (state[t+1] - 1) · M ∀t duration[0] = (duration_per_step[0] + previous_duration) · state[0]

If minimum_duration provided: duration[t] ≥ (state[t-1] - state[t]) · minimum_duration[t-1] ∀t > 0

Where M is a big-M value (sum of all duration_per_step + previous_duration).

Parameters:

Name Type Description Default
model Submodel

The submodel to add variables and constraints to

required
state Variable

Binary state variable (1=active, 0=inactive) to track duration for

required
name str

Full name for the duration variable

None
short_name str

Short name for display purposes

None
minimum_duration DataArray | None

Optional minimum consecutive duration (enforced at state transitions)

None
maximum_duration DataArray | None

Optional maximum consecutive duration (upper bound on duration variable)

None
duration_dim str

Dimension name to track duration along (default 'time')

'time'
duration_per_step int | float | DataArray

Time increment per step in duration_dim

None
previous_duration DataArray

Initial duration value before first timestep (default 0)

0

Returns:

Type Description
dict[str, Variable]

Tuple of (duration_variable, constraints_dict)

dict[str, Constraint]

where constraints_dict contains: 'ub', 'forward', 'backward', 'initial', and optionally 'lb', 'initial_lb'

mutual_exclusivity_constraint staticmethod
mutual_exclusivity_constraint(model: Submodel, binary_variables: list[Variable], tolerance: float = 1, short_name: str = 'mutual_exclusivity') -> linopy.Constraint

Creates mutual exclusivity constraint for binary variables.

Ensures at most one binary variable can be active (=1) at any time.

Mathematical formulation

Σᵢ binary_vars[i] ≤ tolerance ∀t

Parameters:

Name Type Description Default
model Submodel

The submodel to add the constraint to

required
binary_variables list[Variable]

List of binary variables that should be mutually exclusive

required
tolerance float

Upper bound on the sum (default 1, allows slight numerical tolerance)

1
short_name str

Short name for the constraint

'mutual_exclusivity'

Returns:

Type Description
Constraint

Mutual exclusivity constraint

Raises:

Type Description
AssertionError

If fewer than 2 variables provided or variables aren't binary

BoundingPatterns

High-level patterns that compose primitives and return (variables, constraints) tuples

Functions

basic_bounds staticmethod
basic_bounds(model: Submodel, variable: Variable, bounds: tuple[DataArray, DataArray], name: str = None) -> list[linopy.constraints.Constraint]

Creates simple lower and upper bounds for a variable.

Mathematical formulation

lower_bound ≤ variable ≤ upper_bound

Parameters:

Name Type Description Default
model Submodel

The submodel to add constraints to

required
variable Variable

Variable to be bounded

required
bounds tuple[DataArray, DataArray]

Tuple of (lower_bound, upper_bound) absolute bounds

required
name str

Optional name prefix for constraints

None

Returns:

Type Description
list[Constraint]

List of [lower_constraint, upper_constraint]

bounds_with_state staticmethod
bounds_with_state(model: Submodel, variable: Variable, bounds: tuple[DataArray, DataArray], state: Variable, name: str = None) -> list[linopy.Constraint]

Creates bounds controlled by a binary state variable.

Variable is forced to 0 when state=0, bounded when state=1.

Mathematical formulation

state · max(ε, lower_bound) ≤ variable ≤ state · upper_bound

Where ε is a small positive number (CONFIG.Modeling.epsilon) ensuring numerical stability when lower_bound is 0.

Parameters:

Name Type Description Default
model Submodel

The submodel to add constraints to

required
variable Variable

Variable to be bounded

required
bounds tuple[DataArray, DataArray]

Tuple of (lower_bound, upper_bound) absolute bounds when state=1

required
state Variable

Binary variable (0=force variable to 0, 1=allow bounds)

required
name str

Optional name prefix for constraints

None

Returns:

Type Description
list[Constraint]

List of [lower_constraint, upper_constraint] (or [fix_constraint] if lower=upper)

scaled_bounds staticmethod
scaled_bounds(model: Submodel, variable: Variable, scaling_variable: Variable, relative_bounds: tuple[DataArray, DataArray], name: str = None) -> list[linopy.Constraint]

Creates bounds scaled by another variable.

Variable is bounded relative to a scaling variable (e.g., flow rate relative to size).

Mathematical formulation

scaling_variable · lower_factor ≤ variable ≤ scaling_variable · upper_factor

Parameters:

Name Type Description Default
model Submodel

The submodel to add constraints to

required
variable Variable

Variable to be bounded

required
scaling_variable Variable

Variable that scales the bound factors (e.g., equipment size)

required
relative_bounds tuple[DataArray, DataArray]

Tuple of (lower_factor, upper_factor) relative to scaling_variable

required
name str

Optional name prefix for constraints

None

Returns:

Type Description
list[Constraint]

List of [lower_constraint, upper_constraint] (or [fix_constraint] if lower=upper)

scaled_bounds_with_state staticmethod
scaled_bounds_with_state(model: Submodel, variable: Variable, scaling_variable: Variable, relative_bounds: tuple[DataArray, DataArray], scaling_bounds: tuple[DataArray, DataArray], state: Variable, name: str = None) -> list[linopy.Constraint]

Creates bounds scaled by a variable and controlled by a binary state.

Variable is forced to 0 when state=0, bounded relative to scaling_variable when state=1.

Mathematical formulation (Big-M): (state - 1) · M_misc + scaling_variable · rel_lower ≤ variable ≤ scaling_variable · rel_upper state · big_m_lower ≤ variable ≤ state · big_m_upper

Where

M_misc = scaling_max · rel_lower big_m_upper = scaling_max · rel_upper big_m_lower = max(ε, scaling_min · rel_lower)

Parameters:

Name Type Description Default
model Submodel

The submodel to add constraints to

required
variable Variable

Variable to be bounded

required
scaling_variable Variable

Variable that scales the bound factors (e.g., equipment size)

required
relative_bounds tuple[DataArray, DataArray]

Tuple of (lower_factor, upper_factor) relative to scaling_variable

required
scaling_bounds tuple[DataArray, DataArray]

Tuple of (scaling_min, scaling_max) bounds of the scaling_variable

required
state Variable

Binary variable (0=force variable to 0, 1=allow scaled bounds)

required
name str

Optional name prefix for constraints

None

Returns:

Type Description
list[Constraint]

List of [scaling_lower, scaling_upper, binary_lower, binary_upper] constraints

state_transition_bounds staticmethod
state_transition_bounds(model: Submodel, state: Variable, activate: Variable, deactivate: Variable, name: str, previous_state: float | DataArray = 0, coord: str = 'time') -> tuple[linopy.Constraint, linopy.Constraint, linopy.Constraint]

Creates state transition constraints for binary state variables.

Tracks transitions between active (1) and inactive (0) states using separate binary variables for activation and deactivation events.

Mathematical formulation

activate[t] - deactivate[t] = state[t] - state[t-1] ∀t > 0 activate[0] - deactivate[0] = state[0] - previous_state activate[t] + deactivate[t] ≤ 1 ∀t activate[t], deactivate[t] ∈ {0, 1}

Parameters:

Name Type Description Default
model Submodel

The submodel to add constraints to

required
state Variable

Binary state variable (0=inactive, 1=active)

required
activate Variable

Binary variable for transitions from inactive to active (0→1)

required
deactivate Variable

Binary variable for transitions from active to inactive (1→0)

required
name str

Base name for constraints

required
previous_state float | DataArray

State value before first timestep (default 0)

0
coord str

Time dimension name (default 'time')

'time'

Returns:

Type Description
tuple[Constraint, Constraint, Constraint]

Tuple of (transition_constraint, initial_constraint, mutex_constraint)

continuous_transition_bounds staticmethod
continuous_transition_bounds(model: Submodel, continuous_variable: Variable, activate: Variable, deactivate: Variable, name: str, max_change: float | DataArray, previous_value: float | DataArray = 0.0, coord: str = 'time') -> tuple[linopy.Constraint, linopy.Constraint, linopy.Constraint, linopy.Constraint]

Constrains a continuous variable to only change during state transitions.

Ensures a continuous variable remains constant unless a transition event occurs. Uses Big-M formulation to enforce change bounds.

Mathematical formulation

-max_change · (activate[t] + deactivate[t]) ≤ continuous[t] - continuous[t-1] ≤ max_change · (activate[t] + deactivate[t]) ∀t > 0 -max_change · (activate[0] + deactivate[0]) ≤ continuous[0] - previous_value ≤ max_change · (activate[0] + deactivate[0]) activate[t], deactivate[t] ∈ {0, 1}

Behavior
  • When activate=0 and deactivate=0: variable must stay constant
  • When activate=1 or deactivate=1: variable can change within ±max_change

Parameters:

Name Type Description Default
model Submodel

The submodel to add constraints to

required
continuous_variable Variable

Continuous variable to constrain

required
activate Variable

Binary variable for transitions from inactive to active (0→1)

required
deactivate Variable

Binary variable for transitions from active to inactive (1→0)

required
name str

Base name for constraints

required
max_change float | DataArray

Maximum allowed change (Big-M value, should be ≥ actual max change)

required
previous_value float | DataArray

Initial value before first timestep (default 0.0)

0.0
coord str

Time dimension name (default 'time')

'time'

Returns:

Type Description
tuple[Constraint, Constraint, Constraint, Constraint]

Tuple of (transition_upper, transition_lower, initial_upper, initial_lower) constraints

link_changes_to_level_with_binaries(model: Submodel, level_variable: Variable, increase_variable: Variable, decrease_variable: Variable, increase_binary: Variable, decrease_binary: Variable, name: str, max_change: float | DataArray, initial_level: float | DataArray = 0.0, coord: str = 'period') -> tuple[linopy.Constraint, linopy.Constraint, linopy.Constraint, linopy.Constraint, linopy.Constraint]

Link changes to level evolution with binary control and mutual exclusivity.

Creates the complete constraint system for ALL time periods: 1. level[0] = initial_level + increase[0] - decrease[0] 2. level[t] = level[t-1] + increase[t] - decrease[t] ∀t > 0 3. increase[t] <= max_change * increase_binary[t] ∀t 4. decrease[t] <= max_change * decrease_binary[t] ∀t 5. increase_binary[t] + decrease_binary[t] <= 1 ∀t

Parameters:

Name Type Description Default
model Submodel

The submodel to add constraints to

required
increase_variable Variable

Incremental additions for ALL periods (>= 0)

required
decrease_variable Variable

Incremental reductions for ALL periods (>= 0)

required
increase_binary Variable

Binary indicators for increases for ALL periods

required
decrease_binary Variable

Binary indicators for decreases for ALL periods

required
level_variable Variable

Level variable for ALL periods

required
name str

Base name for constraints

required
max_change float | DataArray

Maximum change per period

required
initial_level float | DataArray

Starting level before first period

0.0
coord str

Time coordinate name

'period'

Returns:

Type Description
tuple[Constraint, Constraint, Constraint, Constraint, Constraint]

Tuple of (initial_constraint, transition_constraints, increase_bounds, decrease_bounds, mutual_exclusion)