Access node in custom_recorders during historical simulation (SDDP.jl)

Hey,

I am calculating the dual values of some constraints during historical simulation, and the constraint index depends on the node in the body of the problem. Therefore, in the simulation part, I need to refer to the node:

simulations = SDDP.simulate(
    main_model,
    1;
    sampling_scheme = SDDP.Historical(Sim),
    custom_recorders = Dict{Symbol, Function}(
        :cons1_shadows => (sp::JuMP.Model) -> Dict(
            i => JuMP.dual(sp[:cons1][i]) for i in block_function(node)
        )
    ),
    skip_undefined_variables = true
)

Here, Sim is my historical data and block_function is a function that takes node as input and returns the correct range for the constraint indices.

My question is: How can I access node inside the custom recorder function?

You have a couple of options.

First, you probably don’t need the node. Use broadcasting and things will probably work:

simulations = SDDP.simulate(
    main_model,
    1;
    sampling_scheme = SDDP.Historical(Sim),
    custom_recorders = Dict{Symbol, Function}(
        :cons1_shadows => (sp::JuMP.Model) -> JuMP.dual.(sp[:cons1]),
    ),
    skip_undefined_variables = true
)

Second, you could store a new :node key in the subproblem

SDDP.LinearPolicyGraph() do sp, node
    sp[:node] = t
end

simulations = SDDP.simulate(
    main_model,
    1;
    sampling_scheme = SDDP.Historical(Sim),
    custom_recorders = Dict{Symbol, Function}(
        :cons1_shadows => (sp::JuMP.Model) -> Dict(
            i => JuMP.dual(sp[:cons1][i]) for i in block_function(sp[:node])
        )
    ),
    skip_undefined_variables = true
)