Skip to content

flixopt.optimization

This module contains the Optimization functionality for the flixopt framework. It is used to optimize a FlowSystemModel for a given FlowSystem through a solver. There are three different Optimization types: 1. Optimization: Optimizes the FlowSystemModel for the full FlowSystem 2. ClusteredOptimization: Optimizes the FlowSystemModel for the full FlowSystem, but clusters the TimeSeriesData. This simplifies the mathematical model and usually speeds up the solving process. 3. SegmentedOptimization: Solves a FlowSystemModel for each individual Segment of the FlowSystem.

Classes

OptimizationProtocol

Bases: Protocol

Protocol defining the interface that all optimization types should implement.

This protocol ensures type consistency across different optimization approaches without forcing them into an artificial inheritance hierarchy.

Attributes:

Name Type Description
name str

Name of the optimization

flow_system FlowSystem

FlowSystem being optimized

folder Path

Directory where results are saved

results Results | SegmentedResults | None

Results object after solving

durations dict[str, float]

Dictionary tracking time spent in different phases

Attributes

modeled property
modeled: bool

Returns True if the optimization has been modeled.

main_results property
main_results: dict[str, int | float | dict]

Returns main results including objective, effects, and investment decisions.

summary property
summary: dict

Returns summary information about the optimization.

Optimization

Optimization(name: str, flow_system: FlowSystem, active_timesteps: Annotated[DatetimeIndex | None, 'DEPRECATED: Use flow_system.sel(time=...) or flow_system.isel(time=...) instead'] = None, folder: Path | None = None, normalize_weights: bool = True)

Standard optimization that solves the complete problem using all time steps.

This is the default optimization approach that considers every time step, providing the most accurate but computationally intensive solution.

For large problems, consider using ClusteredOptimization (time aggregation) or SegmentedOptimization (temporal decomposition) instead.

Parameters:

Name Type Description Default
name str

name of optimization

required
flow_system FlowSystem

flow_system which should be optimized

required
folder Path | None

folder where results should be saved. If None, then the current working directory is used.

None
normalize_weights bool

Whether to automatically normalize the weights of scenarios to sum up to 1 when solving.

True
active_timesteps Annotated[DatetimeIndex | None, 'DEPRECATED: Use flow_system.sel(time=...) or flow_system.isel(time=...) instead']

Deprecated. Use FlowSystem.sel(time=...) or FlowSystem.isel(time=...) instead.

None

Examples:

Basic usage:

from flixopt import Optimization

opt = Optimization(name='my_optimization', flow_system=energy_system, folder=Path('results'))
opt.do_modeling()
opt.solve(solver=gurobi)
results = opt.results

Functions

fix_sizes
fix_sizes(ds: Dataset | None = None, decimal_rounding: int | None = 5) -> Optimization

Fix the sizes of the optimizations to specified values.

Parameters:

Name Type Description Default
ds Dataset | None

The dataset that contains the variable names mapped to their sizes. If None, the dataset is loaded from the results.

None
decimal_rounding int | None

The number of decimal places to round the sizes to. If no rounding is applied, numerical errors might lead to infeasibility.

5

ClusteredOptimization

ClusteredOptimization(name: str, flow_system: FlowSystem, clustering_parameters: ClusteringParameters, components_to_clusterize: list[Component] | None = None, active_timesteps: Annotated[DatetimeIndex | None, 'DEPRECATED: Use flow_system.sel(time=...) or flow_system.isel(time=...) instead'] = None, folder: Path | None = None, normalize_weights: bool = True)

Bases: Optimization

ClusteredOptimization reduces computational complexity by clustering time series into typical periods.

This optimization approach clusters time series data using techniques from the tsam library to identify representative time periods, significantly reducing computation time while maintaining solution accuracy.

Note

The quality of the solution depends on the choice of aggregation parameters. The optimal parameters depend on the specific problem and the characteristics of the time series data. For more information, refer to the tsam documentation.

Parameters:

Name Type Description Default
name str

Name of the optimization

required
flow_system FlowSystem

FlowSystem to be optimized

required
clustering_parameters ClusteringParameters

Parameters for clustering. See ClusteringParameters class documentation

required
components_to_clusterize list[Component] | None

list of Components to perform aggregation on. If None, all components are aggregated. This equalizes variables in the components according to the typical periods computed in the aggregation

None
active_timesteps Annotated[DatetimeIndex | None, 'DEPRECATED: Use flow_system.sel(time=...) or flow_system.isel(time=...) instead']

DatetimeIndex of timesteps to use for optimization. If None, all timesteps are used

None
folder Path | None

Folder where results should be saved. If None, current working directory is used

None
normalize_weights bool

Whether to automatically normalize the weights of scenarios to sum up to 1 when solving

True

Attributes:

Name Type Description
clustering Clustering | None

Contains the clustered time series data

clustering_model ClusteringModel | None

Contains Variables and Constraints that equalize clusters of the time series data

Functions

calculate_clustering_weights classmethod
calculate_clustering_weights(ds: Dataset) -> dict[str, float]

Calculate weights for all datavars in the dataset. Weights are pulled from the attrs of the datavars.

calculate_aggregation_weights classmethod
calculate_aggregation_weights(ds: Dataset) -> dict[str, float]

Deprecated: Use calculate_clustering_weights instead.

fix_sizes
fix_sizes(ds: Dataset | None = None, decimal_rounding: int | None = 5) -> Optimization

Fix the sizes of the optimizations to specified values.

Parameters:

Name Type Description Default
ds Dataset | None

The dataset that contains the variable names mapped to their sizes. If None, the dataset is loaded from the results.

None
decimal_rounding int | None

The number of decimal places to round the sizes to. If no rounding is applied, numerical errors might lead to infeasibility.

5

SegmentedOptimization

SegmentedOptimization(name: str, flow_system: FlowSystem, timesteps_per_segment: int, overlap_timesteps: int, nr_of_previous_values: int = 1, folder: Path | None = None)

Solve large optimization problems by dividing time horizon into (overlapping) segments.

This class addresses memory and computational limitations of large-scale optimization problems by decomposing the time horizon into smaller overlapping segments that are solved sequentially. Each segment uses final values from the previous segment as initial conditions, ensuring dynamic continuity across the solution.

Key Concepts

Temporal Decomposition: Divides long time horizons into manageable segments Overlapping Windows: Segments share timesteps to improve storage dynamics Value Transfer: Final states of one segment become initial states of the next Sequential Solving: Each segment solved independently but with coupling

Limitations and Constraints

Investment Parameters: InvestParameters are not supported in segmented optimizations as investment decisions must be made for the entire time horizon, not per segment.

Global Constraints: Time-horizon-wide constraints (flow_hours_total_min/max, load_factor_min/max) may produce suboptimal results as they cannot be enforced globally across segments.

Storage Dynamics: While overlap helps, storage optimization may be suboptimal compared to full-horizon solutions due to limited foresight in each segment.

Parameters:

Name Type Description Default
name str

Unique identifier for the calculation, used in result files and logging.

required
flow_system FlowSystem

The FlowSystem to optimize, containing all components, flows, and buses.

required
timesteps_per_segment int

Number of timesteps in each segment (excluding overlap). Must be > 2 to avoid internal side effects. Larger values provide better optimization at the cost of memory and computation time.

required
overlap_timesteps int

Number of additional timesteps added to each segment. Improves storage optimization by providing lookahead. Higher values improve solution quality but increase computational cost.

required
nr_of_previous_values int

Number of previous timestep values to transfer between segments for initialization. Typically 1 is sufficient.

1
folder Path | None

Directory for saving results. Defaults to current working directory + 'results'.

None

Examples:

Annual optimization with monthly segments:

# 8760 hours annual data with monthly segments (730 hours) and 48-hour overlap
segmented_calc = SegmentedOptimization(
    name='annual_energy_system',
    flow_system=energy_system,
    timesteps_per_segment=730,  # ~1 month
    overlap_timesteps=48,  # 2 days overlap
    folder=Path('results/segmented'),
)
segmented_calc.do_modeling_and_solve(solver='gurobi')

Weekly optimization with daily overlap:

# Weekly segments for detailed operational planning
weekly_calc = SegmentedOptimization(
    name='weekly_operations',
    flow_system=industrial_system,
    timesteps_per_segment=168,  # 1 week (hourly data)
    overlap_timesteps=24,  # 1 day overlap
    nr_of_previous_values=1,
)

Large-scale system with minimal overlap:

# Large system with minimal overlap for computational efficiency
large_calc = SegmentedOptimization(
    name='large_scale_grid',
    flow_system=grid_system,
    timesteps_per_segment=100,  # Shorter segments
    overlap_timesteps=5,  # Minimal overlap
)
Design Considerations

Segment Size: Balance between solution quality and computational efficiency. Larger segments provide better optimization but require more memory and time.

Overlap Duration: More overlap improves storage dynamics and reduces end-effects but increases computational cost. Typically 5-10% of segment length.

Storage Systems: Systems with large storage components benefit from longer overlaps to capture charge/discharge cycles effectively.

Investment Decisions: Use Optimization for problems requiring investment optimization, as SegmentedOptimization cannot handle investment parameters.

Common Use Cases
  • Annual Planning: Long-term planning with seasonal variations
  • Large Networks: Spatially or temporally large energy systems
  • Memory-Limited Systems: When full optimization exceeds available memory
  • Operational Planning: Detailed short-term optimization with limited foresight
  • Sensitivity Analysis: Quick approximate solutions for parameter studies
Performance Tips
  • Start with Optimization and use this class if memory issues occur
  • Use longer overlaps for systems with significant storage
  • Monitor solution quality at segment boundaries for discontinuities
Warning

The evaluation of the solution is a bit more complex than Optimization or ClusteredOptimization due to the overlapping individual solutions.

Attributes

start_values_of_segments property
start_values_of_segments: list[dict[str, Any]]

Gives an overview of the start values of all Segments

modeled property
modeled: bool

Returns True if all segments have been modeled.

main_results property
main_results: dict[str, int | float | dict]

Aggregated main results from all segments.

Note

For SegmentedOptimization, results are aggregated from SegmentedResults which handles the overlapping segments properly. Individual segment results should not be summed directly as they contain overlapping timesteps.

The objective value shown is the sum of all segment objectives and includes double-counting from overlapping regions. It does not represent a true full-horizon objective value.

summary property
summary

Summary of the segmented optimization with aggregated information from all segments.

Functions

do_modeling_and_solve
do_modeling_and_solve(solver: _Solver, log_file: Path | None = None, log_main_results: bool = False, show_individual_solves: bool = False) -> SegmentedOptimization

Model and solve all segments of the segmented optimization.

This method creates sub-optimizations for each time segment, then iteratively models and solves each segment. It supports two output modes: a progress bar for compact output, or detailed individual solve information.

Parameters:

Name Type Description Default
solver _Solver

The solver instance to use for optimization (e.g., Gurobi, HiGHS).

required
log_file Path | None

Optional path to the solver log file. If None, defaults to folder/name.log.

None
log_main_results bool

Whether to log main results (objective, effects, etc.) after each segment solve. Defaults to False.

False
show_individual_solves bool

If True, shows detailed output for each segment solve with logger messages. If False (default), shows a compact progress bar with suppressed solver output for cleaner display.

False

Returns:

Type Description
SegmentedOptimization

Self, for method chaining.

Note

The method automatically transfers all start values between segments to ensure continuity of storage states and flow rates across segment boundaries.

Functions