odow / SDDP.jl

A JuMP extension for Stochastic Dual Dynamic Programming
https://sddp.dev
Other
308 stars 61 forks source link

rhsnoise to SDDP.parametrize #200

Closed roporte closed 5 years ago

roporte commented 5 years ago

Hi,

Im upgrading some old examples to new SDDP. But SDDP.parametrize can only be called once in each subproblem. I have multiple @rhsnoise to sample different noises. How can it be done with SDDP.parametrize?. For example:

@rhsnoise(subproblem, ω = [1, 2, 3], 2x <= ω) @rhsnoise(subproblem, p = [2, 4, 0, 1], z==p)

Thanks!

odow commented 5 years ago

See: https://odow.github.io/SDDP.jl/latest/tutorial/07_advanced_modelling/#Multi-dimensional-noise-terms-1

We should add some utility functions to help this.

@variable(subproblem, x)
@variable(subproblem, ω)
@variable(subproblem, z)
@constraint(subproblem, 2x <= ω)
supports = [(ω=ωi, p=pi) for ωi in [1, 2, 3] for pi in [2, 4, 0, 1]]
probabilities = [ωi * pi for ωi in [1/3, 1/3, 1/3] for pi in [0.25, 0.25, 0.25, 0.25]]
SDDP.parameterize(subproblem, supports, probabilities) do w
    JuMP.fix(ω, w.ω)
    JuMP.fix(z, w.p)    
end

Since the probabilities are uniform, you could also do

@variable(subproblem, x)
@variable(subproblem, z)
supports = [(ω=ωi, p=pi) for ωi in [1, 2, 3] for pi in [2, 4, 0, 1]]
SDDP.parameterize(subproblem, supports) do w
    JuMP.set_upper_bound(x, w.ω / 2)
    JuMP.fix(z, w.p)    
end
odow commented 5 years ago

These docs should be improved: https://github.com/odow/SDDP.jl/blob/master/docs/src/upgrading_guide.md#rhsnoise https://odow.github.io/SDDP.jl/latest/tutorial/07_advanced_modelling/#Multi-dimensional-noise-terms-1

rodripor commented 5 years ago

Thanks for your previous answer, now i have this issue related. To sample a vector of 3 reservoir inflows (3-tuple) i filter from historical data all inflows of the current week of the year associated with a markov_state that represents climate. I obtain a collection of 3-tuples from which i want to sample current inflows. To do this i generate a vector of indexes from 1 to the size of the collection, then i sample an index using SDDP.parameterize. With the value obtained i index the collection but get an error because indexSelected is a JuMP variable.

    #collection[week][markov_state]  is a collection of 3-tuples
    allIndexes= [i for i = 1:length(collection[week][markov_state])] 

    @variable(sp, indexSelected)
    @constraint(sp, inflowRes1== representantesPorEstadoSemana[week][markov_state][indexSelected][1])

      @constraint(sp, inflowRes2== representantesPorEstadoSemana[week][markov_state][indexSelected][2])
     @constraint(sp, inflowRes3== representantesPorEstadoSemana[week][markov_state][indexSelected][3])
    SDDP.parameterize(sp, allIndexes) do j
            JuMP.fix(indexSelected, j)

    end

The idea is to use inflowRes1, inflowRes2, and inflowRes3 in the dynamic.

With rhsnoise i have no problem, but with parameterize i cant solve this issue. Probably is posible to fix inflowRes1, inflowRes2 and inflowRes3 but are dependent of markov_state. I read Markov uncertainty chapter but inflow doesnt depend on stage:

Creating a model using SDDP, GLPK

Ω = [ (inflow = 0.0, fuel_multiplier = 1.5), (inflow = 50.0, fuel_multiplier = 1.0), (inflow = 100.0, fuel_multiplier = 0.75) ]

Thanks!

odow commented 5 years ago

You should do this:

SDDP.parameterize(sp, collection[week][markov_state]) do index_selected
    JuMP.fix(inflowRes1, representantesPorEstadoSemana[week][markov_state][index_selected][1])
    JuMP.fix(inflowRes2, representantesPorEstadoSemana[week][markov_state][index_selected][2])
    JuMP.fix(inflowRes3, representantesPorEstadoSemana[week][markov_state][index_selected][3])        
end

Of course, if you had more reservoirs, you might do something like:

@variable(sp, inflowRes[i=1:3])
SDDP.parameterize(sp, collection[week][markov_state]) do index_selected
    for i in 1:3
        JuMP.fix(inflowRes[i], representantesPorEstadoSemana[week][markov_state][index_selected][i])
    end
end

Yet another approach might be

@variable(sp, inflowRes[i=1:3])
random_inflows = representantesPorEstadoSemana[week][markov_state][
    collection[week][markov_state]]
SDDP.parameterize(sp, random_inflows) do inflow
    JuMP.fix.(inflowRes, inflow)
end