Skip to content

Adding support for scenerio paths across representative periods #107

Description

@trulsf

There has surfaced a need to better handle operational scenarios across representative periods, e.g. where scenarios represent samples from the same weather year in a consistent manner across representative periods. There is also a need to be more explicit about how constraints across representative periods is handled, e.g. yearly emission restrictions. A related discussion has also been raised in OpenEMPIRE work (ntnuiotenergy/OpenEMPIRE.jl#41).
Ongoing work on automatic decomposition could also need better handling of this, to open up for decomposition e.g. for a weather year.

There is several ways this can be handled and I have explored one of the possibilities (using Claude to prototype). See the branch https://github.com/sintefore/TimeStruct.jl/tree/tf/scenario-paths.

This approach is non-breaking with the existing time structures, but allows RepresentativePeriods to have a scenario pairing that describes how operational scenarios are to be paired when generating the possible scenario paths. The new function scenario_paths returns joint scenario paths, where each path selects one operational scenario per representative period and has an id and a probability. Here is an example using the method diagonal pairing where scenarios are combined based on their index

day = SimpleTimes(24,1)
oscens = OperationalScenarios(5, fill(day, 5), [0.3, 0.3, 0.2, 0.2])
periods = RepresentativePeriods(4, 365, oscens; pairing = DiagonalPairing())
paths = scenario_paths(periods)
prb = probability.(paths)

This would allow for e.g. upholding constraints for each scenario path, in expectation or in a more complex probabilistic sense (e.g. CVaR).

# Indivdual paths (robust)
for path in scenario_paths(periods)
  @constraint(model, sum(emisssion[t] for t in path) <= limit)) 
end

# Expectation
@constraint(model, sum(probability(path) * sum(emission[t] for t in path) for path in paths) <= limit

The tutorial section in the branch has a more complete example (and also scales thing with multiple and duration correctly).

The pairing of scenarios can also be generated in more complex ways and provided explicitly to TimeStruct. I think this is functionality that should reside outside TimeStruct, so I have created a small example package (https://github.com/trulsf/ScenarioGeneration.jl) that showcases some possibilities.

There are clearly things that need to be ironed out and API designs to be discussed, but the overall question is: should we explore this design further and is it something that should reside in TimeStruct at all (is a separate package for all of this better)? Are there better ways to handle this (e.g. allowing flexible nesting of operational scenarios and representative periods)?
@hellemo @JulStraus

Activity

  1. added theissue type on Oct 22, 2026
  2. JulStraus commented on Oct 22, 2026

    @JulStraus
    Collaborator

    I think it is an interesting topic and one, that I also thought of recently. I have not yet checked your implementation thoroughly, but think that it is a good idea to have an approach for it.

    For most of the applications, I actually like the we have representative periods above scenarios as, at least in my opinion, most scenarios are not relevant for covering multiple representative periods (e.g., solar PV generation in the winter representative period is in my opinion no correlated to solar PV generation in the summer representative period). The same should hold true for wind generation or heating demand.

    However, when considering especially hydrological scenarios, I expect that we have a quite strong coupling between scenarios, and hence, would require the coupling of the scenarios. In that respect, it makes sense to allow for it. Personally speaking. I think it should be something that is directly included in TimeStruct and not an extension package, at least the basic pairing approaches. I also think that we could theoretically allow for flexible pairing between operational scenarios and representative periods (i.e., allow for operational scenarios sitting on top of representative periods (new), the opposite (existing), and a combination of both. However, we then run into the problems outlined in #103 regarding the explosion of components.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions