Skip to content

Sanitize stageobjective macro #404

@odow

Description

@odow

The @stageobjective macro doesn't really check that the stage objective is well-formed. It accepts anything. But fails with obscure MethodError's if you go too far from reasonable:

julia> using SDDP

julia> SDDP.LinearPolicyGraph(
           stages = 2,
           lower_bound = 0.0,
       ) do sp, node
           @variable(sp, x, SDDP.State, initial_value = 0)
           @stageobjective(sp, [1])
       end
A policy graph with 2 nodes.
 Node indices: 1, 2


julia> SDDP.LinearPolicyGraph(
           stages = 2,
           lower_bound = 0.0,
       ) do sp, node
           @variable(sp, x, SDDP.State, initial_value = 0)
           @stageobjective(sp, [x.in, x.out])
       end
A policy graph with 2 nodes.
 Node indices: 1, 2


julia> SDDP.LinearPolicyGraph(
           stages = 2,
           lower_bound = 0.0,
       ) do sp, node
           @variable(sp, x, SDDP.State, initial_value = 0)
           @stageobjective(sp, [1 2] * [x.in, x.out])
       end
A policy graph with 2 nodes.
 Node indices: 1, 2


julia> SDDP.LinearPolicyGraph(
           stages = 2,
           lower_bound = 0.0,
       ) do sp, node
           @variable(sp, x, SDDP.State, initial_value = 0)
           @stageobjective(sp, x.in + [1 2] * [x.in, x.out])
       end
ERROR: MethodError: no method matching +(::Vector{AffExpr}, ::VariableRef)
Closest candidates are:
  +(::Any, ::Any, ::Any, ::Any...) at operators.jl:560
  +(::Union{MathOptInterface.ScalarAffineFunction{T}, MathOptInterface.ScalarQuadraticFunction{T}}, ::T) where T at /Users/oscar/.julia/packages/MathOptInterface/1EYfq/src/Utilities/functions.jl:1711
  +(::GenericAffExpr{C, V}, ::V) where {C, V<:AbstractVariableRef} at /Users/oscar/.julia/packages/JuMP/Xrr7O/src/operators.jl:175
  ...
Stacktrace:
  [1] muladd(x::Matrix{Int64}, y::Vector{VariableRef}, z::VariableRef)
    @ Base.Math ./math.jl:1152
  [2] add_mul(a::VariableRef, b::Matrix{Int64}, c::Vector{VariableRef})
    @ MutableArithmetics ~/.julia/packages/MutableArithmetics/6pKCK/src/MutableArithmetics.jl:24
  [3] operate(op::typeof(MutableArithmetics.add_mul), x::VariableRef, y::Matrix{Int64}, args::Vector{VariableRef})
    @ MutableArithmetics ~/.julia/packages/MutableArithmetics/6pKCK/src/interface.jl:110
  [4] operate_fallback!(::MutableArithmetics.NotMutable, ::Function, ::VariableRef, ::Matrix{Int64}, ::Vector{VariableRef})
    @ MutableArithmetics ~/.julia/packages/MutableArithmetics/6pKCK/src/interface.jl:407
  [5] operate!(::typeof(MutableArithmetics.add_mul), ::VariableRef, ::Matrix{Int64}, ::Vector{VariableRef})
    @ MutableArithmetics ~/.julia/packages/MutableArithmetics/6pKCK/src/rewrite.jl:83
  [6] macro expansion
    @ ~/.julia/packages/MutableArithmetics/6pKCK/src/rewrite.jl:280 [inlined]
  [7] macro expansion
    @ ~/.julia/packages/SDDP/QO0wO/src/user_interface.jl:806 [inlined]
  [8] (::var"#79#80")(sp::Model, node::Int64)
    @ Main ./REPL[87]:6
  [9] SDDP.PolicyGraph(builder::var"#79#80", graph::SDDP.Graph{Int64}; sense::Symbol, lower_bound::Float64, upper_bound::Float64, optimizer::Nothing, bellman_function::Nothing, direct_mode::Bool, integrality_handler::SDDP.ContinuousRelaxation)
    @ SDDP ~/.julia/packages/SDDP/QO0wO/src/user_interface.jl:641
 [10] #LinearPolicyGraph#11
    @ ~/.julia/packages/SDDP/QO0wO/src/user_interface.jl:502 [inlined]
 [11] top-level scope
    @ REPL[87]:1

x-ref: https://discourse.julialang.org/t/sddp-no-method-matching-float64-sddp-state-variableref/61666/4

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions