Question about SDDP.jl

Hello,

I am new to SDDP.jl, so my question may be naive.

I currently have a working SDDP model in which the generation profits are computed using a fixed hydraulic head effect (so the efficiency does not depend on the reservoir volume).

I would now like these profits to depend on the hydraulic head, which itself is a function of the volume stored in the reservoir. My idea was to recompute the profits at each stage using the incoming storage (`V.in`), since this storage corresponds to the volume resulting from the decision taken at the previous stage.

Concretely, this would look something like:

function create_ucd_profitsSDDP(model, ep::EtudeParameters, pdt::Int, scenario::Int)

(; T, lac_index) = get_time_step_dimensions(ep, pdt)



model\[:ucd_profits\] = Dict(

    u => \[

        \[
            ucd_profit( get_ucd(ep, u), ep, pdt, scenario,g,t,  V\[lac_index\].in,) for t ∈ T \]

        for g ∈ groups(get_ucd(ep, u))

    \]

    for u ∈ ucd_energetic_range(ep)

)



return nothing

end

```

However, this does not work because `V[lac_index].in` is a `JuMP.VariableRef` and not a `Float64`. The functions used to compute efficiencies and profits expect numerical values, not decision variables.

My questions are therefore the following:

* Is it possible in SDDP.jl to access the numerical value of `V.in` during the construction or update of a subproblem?

* Or does the SDDP framework completely prevent this kind of dependence of the objective coefficients on the value of the state variable?

* If this is not possible directly, what would be the recommended approach to model an efficiency that depends on the storage level (and therefore a hydraulic head that depends on reservoir volume)?

What confuses me is that when I inspect the LPs exported during a simulation, I see lines such as:

Bounds
V_1__in = 0
V_1__out free
V_2__in = 53.2514
V_2__out free

This gives me the impression that at some point `V.in` does have a numerical value. I do not understand at which stage of the algorithm this value becomes available, nor whether it is possible to use it to update the profits.

I could approximate the hydraulic head effect with additional piecewise-linear constraints, but the function ucd_profits is complex and this would make the model considerably larger, so I am wondering whether there is a more direct approach in SDDP.jl. Note that I assume that the hydraulic head effect remains constant during a given transition step and only depends on V.in

Thank you in advance for your help!

Hi @david-hri!

Is it possible in SDDP.jl to access the numerical value of `V.in` during the construction or update of a subproblem?

Nope.

Or does the SDDP framework completely prevent this kind of dependence of the objective coefficients on the value of the state variable?

Correct. We make the incoming state variables a JuMP decision variable so that you cannot write problems with a numeric dependence on the incoming values.

If this is not possible directly, what would be the recommended approach to model an efficiency that depends on the storage level (and therefore a hydraulic head that depends on reservoir volume)?

The underlying problem is that doing so makes the problem non-convex, and one of the assumptions behind SDDP is that the value functions are convex.

There are a few options.

  1. Write a non-convex nonlinear subproblem, for example, by adding a bilinear quadratic term:

    power == flow * V.in
    

    the downside of this approach is that you need a solver that supports non-convex quadratic constraints, and the resulting policy you get from SDDP loses any guarantee of solution quality. It might work well, or it might be even worse than your fixed head approximation.

  2. The second approach is to model it using some binary variables. See Approximating nonlinear functions · JuMP. There are various papers in the literature that investigate different models for modelling head effects. SDDP.jl supports binary variables in the subproblems, and there are various settings you can enable (How to add integrality · SDDP.jl). But the downside is that the resulting policy is not guaranteed to be optimal. The value function is, however, a valid bound on the optimal solution, so you can compare the lower bound against the simulated policy (which will use the integer variables) to see if the policy is acceptable to you. This still may be better or worse than your fixed head model.

Thanks, that was very helpful!

Indeed, I was aware that this would introduce non-convexities, but we wanted to understand how SDDP.jl could handle this type of problem.

My reasoning was that V.in comes from the solution of the previous stage, so I thought it might be possible to treat it as a fixed value rather than a decision variable and thus avoid introducing binary variables.

Thank you very much for your explanation. I’ll stick with my previous formulation then.

David