odow / SDDP.jl

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

multistage process simulation #641

Closed BaiYansong-bys closed 1 year ago

BaiYansong-bys commented 1 year ago

Hi! If I want to simulate an online scheduling process with 20 stages, the SDDP model is built as LinearPolicyGraph ,pw_s is the stochastic variables. the stochastic process happened of 20 stages is as follows, Stage 1 pw_s = [0, 0]; Stage 2 pw_s = [-0.1, -0.3]; Stage 3 pw_s = [-0.2, -0.3]; ....... Stage 20 pw_s = [-0.01, -0.23]; the online simulation code is as follows:

sampling_scheme =
    SDDP.OutOfSampleMonteCarlo(model) do stage
        if stage==1
            return [SDDP.Noise((pw_s = [0, 0]), 1)]
        elseif stage==2
            return [SDDP.Noise((pw_s = [-0.1, -0.3]), 1)]
        elseif stage==3
            return [SDDP.Noise((pw_s = [-0.2, -0.3]), 1)]
       .....
       elseif stage==20
            return [SDDP.Noise((pw_s = [-0.01, -0.23]), 1)]
        end
    end
simulations = SDDP.simulate(model, 1, sampling_scheme = sampling_scheme)

However, the codes above seem to be incorrect, it tells me SDDP.noise()is used incorrect. how can I express the simulation process?

odow commented 1 year ago

How have you defined SDDp.parameterize.

Perhaps you just need return [SDDP.Noise([0, 0], 1)]

BaiYansong-bys commented 1 year ago

Thanks a lot, Oscar. My SDDP.parameterize() is as follows,

        SDDP.parameterize(sp, sce0, Pro0) do omga#sce0,Pro0
                #JuMP.fix.(pw_s, omga)
            #for i in 1:NW
                set_normalized_coefficient(c_stochastic1, uw[1].out, -pw_l[1,stage]*(1+omga[1]))
                set_normalized_coefficient(c_stochastic2, uw[2].out, -pw_l[2,stage]*(1+omga[2]))
                #
            #end
        end
        @constraint(sp, c_stochastic1, pw[1]<=uw[1].out)
        @constraint(sp, c_stochastic2, pw[2]<=uw[2].out)

If I write this below,

sampling_scheme =
    SDDP.OutOfSampleMonteCarlo(model) do stage
        if stage==1
            return [SDDP.Noise([0, 0], 1.0)]
        else
            return [SDDP.Noise([-0.01, -0.23], 1.0)]
        end
    end
simulations = SDDP.simulate(model, 1, sampling_scheme = sampling_scheme)

It tells me the error: ERROR: TypeError: in typeassert, expected Vector{SDDP.Noise{Int64}}, got a value of type Vector{SDDP.Noise{Vector{Float64}}} Stacktrace:

odow commented 1 year ago

What is sce0? You need to make sure that the element type of sce0 is the same type that you pass to `OutOfSample.

In this case, your OutOfSample is being passed a Vector{Float64}, but it expected an Int64.

It's hard to say anything more without a reproducible example.

BaiYansong-bys commented 1 year ago

Sorry, i have not expressed the sce0 clearly. the codes are as follows,

using PowerModels, XLSX, SDDP, Gurobi

NW = 2;
NT = 20;

pw_l = [112.1 108.294 104.89 102.436 101.142 99.996 98.806 97.212 97.63 98.194 98.904 100.054 107.484 115.38 123.82 135.202 141.516 148.648 156.178 169.37; 102.32 99.172 92.428 82.89 75.532 72.61 74.672 83.732 90.016 97.094 103.202 109.412 115.218 129.026 135.84 131.632 129.756 127.258 123.796 121.802]

model = SDDP.LinearPolicyGraph(
    stages = 20,
    sense = :Min,
    lower_bound = -800000,#-800000
    optimizer = Gurobi.Optimizer,
    #integrality_handler=SDDP.LagrangianDuality(),
) do sp, stage
    @variables(sp, begin
        pw[1:NW] >= 0
    end)
    @variable(sp,uw[1:NW],Bin)

    if stage == 1
        @constraint(
            sp,
            [i in 1:NW],
            pw[i] <= pw_l[i, stage] * (1.0) * uw[i]
        )
    elseif stage in collect(2:NT)
        SDDP.parameterize(sp, [[0.2,0.3],[0,-0.1]],[0.5,0.5]) do omga
            for i = 1:NW
                set_normalized_coefficient(
                    c_stochastic[i],
                    uw[i],
                    -pw_l[i, stage] * (1 + omga[i]),
                )
                #
            end
        end
        @constraint(sp, c_stochastic[i in 1:NW], pw[i] <= uw[i])
    end

        @stageobjective(
            sp,
            -sum(pw)
        )
    set_silent(sp)
end

SDDP.train(
    model,
    iteration_limit = 50,
    duality_handler = SDDP.ContinuousConicDuality(),
)#,log_frequency = 100

sampling_scheme = SDDP.OutOfSampleMonteCarlo(model) do stage
    if stage == 1
        return [SDDP.Noise([0.0, 0.0], 1.0)]
    else
        return [SDDP.Noise([-0.01, -0.23], 1.0)]
    end
end
simulations = SDDP.simulate(model, 1, sampling_scheme = sampling_scheme)

The following shows the error report: LoadError: TypeError: in typeassert, expected Vector{SDDP.Noise{Int64}}, got a value of type Vector{SDDP.Noise{Vector{Float64}}} Stacktrace:

odow commented 1 year ago

Your example doesn't have any state variables?

BaiYansong-bys commented 1 year ago

The original code has the state varaibles, I have similified it, the following code has the state variables:

using  Gurobi, SDDP

NW = 2;
NT = 20;
NB = 30;
W_S = [3,16];

pw_l = [112.1 108.294 104.89 102.436 101.142 99.996 98.806 97.212 97.63 98.194 98.904 100.054 107.484 115.38 123.82 135.202 141.516 148.648 156.178 169.37; 102.32 99.172 92.428 82.89 75.532 72.61 74.672 83.732 90.016 97.094 103.202 109.412 115.218 129.026 135.84 131.632 129.756 127.258 123.796 121.802]
ini_ui = zeros(NB);

model = SDDP.LinearPolicyGraph(
    stages = 20,
    sense = :Min,
    lower_bound = -800000,#-800000
    optimizer = Gurobi.Optimizer,
    #integrality_handler=SDDP.LagrangianDuality(),
) do sp, stage
    @variable(sp, uw[1:NW], Bin)

    @variable(sp, pw[1:NW] >= 0)

    @variable(
        sp,
        0 <= ui[i in 1:NB] <= 1,
        SDDP.State,
        Bin,
        initial_value = ini_ui[i]
    )
    @constraint(sp, [i in 1:NW], uw[i] <= ui[W_S[i]].out)
    @constraint(sp, [i in 1:NB], ui[i].out >= ui[i].in)

    if stage == 1
        @constraint(
            sp,
            [i in 1:NW],
            pw[i] <= pw_l[i, stage] * (1.0) * uw[i]
        )
    elseif stage in collect(2:NT)
        SDDP.parameterize(sp, [[0.2,0.3],[0,-0.1]],[0.5,0.5]) do omga
            for i = 1:NW
                set_normalized_coefficient(
                    c_stochastic[i],
                    uw[i],
                    -pw_l[i, stage] * (1 + omga[i]),
                )
                #
            end
        end
        @constraint(sp, c_stochastic[i in 1:NW], pw[i] <= uw[i])
    end

        @stageobjective(
            sp,
            -sum(pw)
        )
    set_silent(sp)
end

SDDP.train(
    model,
    iteration_limit = 50,
    duality_handler = SDDP.ContinuousConicDuality(),
)#,log_frequency = 100

sampling_scheme = SDDP.OutOfSampleMonteCarlo(model) do stage
    if stage == 1
        return [SDDP.Noise([0.0, 0.0], 1.0)]
    else
        return [SDDP.Noise([-0.01, -0.23], 1.0)]
    end
end
simulations = SDDP.simulate(model, 1, sampling_scheme = sampling_scheme)

It can work, but SDDP.Noise has the same error.

odow commented 1 year ago

You need to use

sampling_scheme = SDDP.OutOfSampleMonteCarlo(
    model; 
    use_insample_transition = true,
) do stage
    if stage == 1
        return [SDDP.Noise(nothing, 1.0)]
    else
        return [SDDP.Noise([-0.01, -0.23], 1.0)]
    end
end
BaiYansong-bys commented 1 year ago

Thanks a lot, Oscar. The code can run very well.