flixopt.modeling
Attributes
Classes
ModelingUtilitiesAbstract
Utility functions for modeling calculations - 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 "off", returns 0.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
binary_values
|
DataArray | ndarray | list[int, float]
|
Binary DataArray with values close to 0 (off) or 1 (on). |
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 "on" period. Returns 0.0 if the |
float
|
final state is "off". |
Examples:
ModelingUtilities
Functions
compute_consecutive_hours_in_state
staticmethod
compute_consecutive_hours_in_state(binary_values: TemporalData, hours_per_timestep: int | float, epsilon: float = None) -> float
Computes the final consecutive duration in state 'on' (=1) in hours.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
binary_values
|
TemporalData
|
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 'on' 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 'off' 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 off duration in hours |
get_most_recent_state
staticmethod
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, name: str = None, short_name: str = None, bounds: tuple[TemporalData, TemporalData] = None, coords: str | list[str] | None = None) -> tuple[linopy.Variable, linopy.Constraint]
Creates variable that equals a given expression.
Mathematical formulation
tracker = expression lower ≤ tracker ≤ upper (if bounds provided)
Returns:
Name | Type | Description |
---|---|---|
variables |
Variable
|
{'tracker': tracker_var} |
constraints |
Constraint
|
{'tracking': constraint} |
consecutive_duration_tracking
staticmethod
consecutive_duration_tracking(model: Submodel, state_variable: Variable, name: str = None, short_name: str = None, minimum_duration: TemporalData | None = None, maximum_duration: TemporalData | None = None, duration_dim: str = 'time', duration_per_step: int | float | TemporalData = None, previous_duration: TemporalData = 0) -> tuple[linopy.Variable, tuple[linopy.Constraint, linopy.Constraint, linopy.Constraint]]
Creates consecutive duration tracking for a binary state variable.
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
Parameters:
Name | Type | Description | Default |
---|---|---|---|
name
|
str
|
Name of the duration variable |
None
|
state_variable
|
Variable
|
Binary state variable to track duration for |
required |
minimum_duration
|
TemporalData | None
|
Optional minimum consecutive duration |
None
|
maximum_duration
|
TemporalData | None
|
Optional maximum consecutive duration |
None
|
previous_duration
|
TemporalData
|
Duration from before first timestep |
0
|
Returns:
Name | Type | Description |
---|---|---|
variables |
Variable
|
{'duration': duration_var} |
constraints |
tuple[Constraint, Constraint, Constraint]
|
{'ub': constraint, 'forward': constraint, 'backward': constraint, ...} |
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.
Mathematical formulation
Σ(binary_vars[i]) ≤ tolerance ∀t
Ensures at most one binary variable can be 1 at any time. Tolerance > 1.0 accounts for binary variable numerical precision.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
binary_variables
|
list[Variable]
|
List of binary variables that should be mutually exclusive |
required |
tolerance
|
float
|
Upper bound |
1
|
short_name
|
str
|
Short name of the constraint |
'mutual_exclusivity'
|
Returns:
Name | Type | Description |
---|---|---|
variables |
Constraint
|
{} (no new variables created) |
constraints |
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[TemporalData, TemporalData], name: str = None) -> list[linopy.constraints.Constraint]
Create simple bounds. variable ∈ [lower_bound, upper_bound]
Mathematical Formulation
lower_bound ≤ variable ≤ upper_bound
Parameters:
Name | Type | Description | Default |
---|---|---|---|
model
|
Submodel
|
The optimization model instance |
required |
variable
|
Variable
|
Variable to be bounded |
required |
bounds
|
tuple[TemporalData, TemporalData]
|
Tuple of (lower_bound, upper_bound) absolute bounds |
required |
Returns:
Type | Description |
---|---|
list[Constraint]
|
List containing lower_bound and upper_bound constraints |
bounds_with_state
staticmethod
bounds_with_state(model: Submodel, variable: Variable, bounds: tuple[TemporalData, TemporalData], variable_state: Variable, name: str = None) -> list[linopy.Constraint]
Constraint a variable to bounds, that can be escaped from to 0 by a binary variable. variable ∈ {0, [max(ε, lower_bound), upper_bound]}
Mathematical Formulation
- variable_state * max(ε, lower_bound) ≤ variable ≤ variable_state * upper_bound
Use Cases
- Investment decisions
- Unit commitment (on/off states)
Parameters:
Name | Type | Description | Default |
---|---|---|---|
model
|
Submodel
|
The optimization model instance |
required |
variable
|
Variable
|
Variable to be bounded |
required |
bounds
|
tuple[TemporalData, TemporalData]
|
Tuple of (lower_bound, upper_bound) absolute bounds |
required |
variable_state
|
Variable
|
Binary variable controlling the bounds |
required |
Returns:
Type | Description |
---|---|
list[Constraint]
|
Tuple containing: - variables (Dict): Empty dict - constraints (Dict[str, linopy.Constraint]): 'ub', 'lb' |
scaled_bounds
staticmethod
scaled_bounds(model: Submodel, variable: Variable, scaling_variable: Variable, relative_bounds: tuple[TemporalData, TemporalData], name: str = None) -> list[linopy.Constraint]
Constraint a variable by scaling bounds, dependent on another variable. variable ∈ [lower_bound * scaling_variable, upper_bound * scaling_variable]
Mathematical Formulation
scaling_variable * lower_factor ≤ variable ≤ scaling_variable * upper_factor
Use Cases
- Flow rates bounded by equipment capacity
- Production levels scaled by plant size
Parameters:
Name | Type | Description | Default |
---|---|---|---|
model
|
Submodel
|
The optimization model instance |
required |
variable
|
Variable
|
Variable to be bounded |
required |
scaling_variable
|
Variable
|
Variable that scales the bound factors |
required |
relative_bounds
|
tuple[TemporalData, TemporalData]
|
Tuple of (lower_factor, upper_factor) relative to scaling variable |
required |
Returns:
Type | Description |
---|---|
list[Constraint]
|
Tuple containing: - variables (Dict): Empty dict - constraints (Dict[str, linopy.Constraint]): 'ub', 'lb' |
scaled_bounds_with_state
staticmethod
scaled_bounds_with_state(model: Submodel, variable: Variable, scaling_variable: Variable, relative_bounds: tuple[TemporalData, TemporalData], scaling_bounds: tuple[TemporalData, TemporalData], variable_state: Variable, name: str = None) -> list[linopy.Constraint]
Constraint a variable by scaling bounds with binary state control.
variable ∈ {0, [max(ε, lower_relative_bound) * scaling_variable, upper_relative_bound * scaling_variable]}
Mathematical Formulation (Big-M): (variable_state - 1) * M_misc + scaling_variable * rel_lower ≤ variable ≤ scaling_variable * rel_upper variable_state * big_m_lower ≤ variable ≤ 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 optimization model instance |
required |
variable
|
Variable
|
Variable to be bounded |
required |
scaling_variable
|
Variable
|
Variable that scales the bound factors |
required |
relative_bounds
|
tuple[TemporalData, TemporalData]
|
Tuple of (lower_factor, upper_factor) relative to scaling variable |
required |
scaling_bounds
|
tuple[TemporalData, TemporalData]
|
Tuple of (scaling_min, scaling_max) bounds of the scaling variable |
required |
variable_state
|
Variable
|
Binary variable for on/off control |
required |
name
|
str
|
Optional name prefix for constraints |
None
|
Returns:
Type | Description |
---|---|
list[Constraint]
|
List[linopy.Constraint]: List of constraint objects |
state_transition_bounds
staticmethod
state_transition_bounds(model: Submodel, state_variable: Variable, switch_on: Variable, switch_off: Variable, name: str, previous_state=0, coord: str = 'time') -> tuple[linopy.Constraint, linopy.Constraint, linopy.Constraint]
Creates switch-on/off variables with state transition logic.
Mathematical formulation
switch_on[t] - switch_off[t] = state[t] - state[t-1] ∀t > 0 switch_on[0] - switch_off[0] = state[0] - previous_state switch_on[t] + switch_off[t] ≤ 1 ∀t switch_on[t], switch_off[t] ∈ {0, 1}
Returns:
Name | Type | Description |
---|---|---|
variables |
Constraint
|
{'switch_on': binary_var, 'switch_off': binary_var} |
constraints |
Constraint
|
{'transition': constraint, 'initial': constraint, 'mutex': constraint} |
continuous_transition_bounds
staticmethod
continuous_transition_bounds(model: Submodel, continuous_variable: Variable, switch_on: Variable, switch_off: 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 when switch variables are active.
Mathematical formulation
-max_change * (switch_on[t] + switch_off[t]) <= continuous[t] - continuous[t-1] <= max_change * (switch_on[t] + switch_off[t]) ∀t > 0 -max_change * (switch_on[0] + switch_off[0]) <= continuous[0] - previous_value <= max_change * (switch_on[0] + switch_off[0]) switch_on[t], switch_off[t] ∈ {0, 1}
This ensures the continuous variable can only change when switch_on or switch_off is 1. When both switches are 0, the variable must stay exactly constant.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
model
|
Submodel
|
The submodel to add constraints to |
required |
continuous_variable
|
Variable
|
The continuous variable to constrain |
required |
switch_on
|
Variable
|
Binary variable indicating when changes are allowed (typically transitions to active state) |
required |
switch_off
|
Variable
|
Binary variable indicating when changes are allowed (typically transitions to inactive state) |
required |
name
|
str
|
Base name for the constraints |
required |
max_change
|
float | DataArray
|
Maximum possible change in the continuous variable (Big-M value) |
required |
previous_value
|
float | DataArray
|
Initial value of the continuous variable before first period |
0.0
|
coord
|
str
|
Coordinate name for time dimension |
'time'
|
Returns:
Type | Description |
---|---|
tuple[Constraint, Constraint, Constraint, Constraint]
|
Tuple of constraints: (transition_upper, transition_lower, initial_upper, initial_lower) |
link_changes_to_level_with_binaries
staticmethod
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) |