SDDP: how to use Juniper.jl for optimizer

Hello,

I’m trying to solve MI-NLP problem with SDDP.jl. I would like to use juniper.jl as optimizer:

using SDDP 
using Ipopt
using Juniper

nl_solver = optimizer_with_attributes(Ipopt.Optimizer, "print_level"=>0)
minlp_solver = optimizer_with_attributes(Juniper.Optimizer, "nl_solver"=>nl_solver)
# model = Model(minlp_solver)

# Building the subproblem
model = SDDP.LinearPolicyGraph(
    stages = numtime,
    sense = :Min,
    lower_bound = 0.0,
    optimizer = minlp_solver,
) do sp, node
...
end

But when I train the model, I got error saying:

ArgumentError: MathOptInterface.Utilities.Model{Float64} does not support getting the attribute MathOptInterface.ConstraintDual(1).

Stacktrace:
  [1] get_fallback(model::MathOptInterface.Utilities.Model{Float64}, attr::MathOptInterface.ConstraintDual, #unused#::MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.EqualTo{Float64}})
    @ MathOptInterface ~/.julia/packages/MathOptInterface/RuRWI/src/attributes.jl:367
  [2] get(model::MathOptInterface.Utilities.Model{Float64}, attr::MathOptInterface.ConstraintDual, args::MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.EqualTo{Float64}})
    @ MathOptInterface ~/.julia/packages/MathOptInterface/RuRWI/src/attributes.jl:336
  [3] get(uf::MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}, attr::MathOptInterface.ConstraintDual, ci::MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.EqualTo{Float64}})
    @ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/RuRWI/src/Utilities/universalfallback.jl:393
  [4] get(model::Juniper.Optimizer, attr::MathOptInterface.ConstraintDual, ci::MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.EqualTo{Float64}})
    @ Juniper ~/.julia/packages/Juniper/0Z1vO/src/MOI_wrapper/MOI_wrapper.jl:474
  [5] get(b::MathOptInterface.Bridges.LazyBridgeOptimizer{Juniper.Optimizer}, attr::MathOptInterface.ConstraintDual, ci::MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.EqualTo{Float64}})
    @ MathOptInterface.Bridges ~/.julia/packages/MathOptInterface/RuRWI/src/Bridges/bridge_optimizer.jl:1303
  [6] get(model::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Bridges.LazyBridgeOptimizer{Juniper.Optimizer}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}, attr::MathOptInterface.ConstraintDual, index::MathOptInterface.ConstraintIndex{MathOptInterface.VariableIndex, MathOptInterface.EqualTo{Float64}})

How can I specify juniper solver appropriately with SDDP.jl?

SDDP.jl isn’t the right tool to use for solving a MINLP. It’s mainly intended for multistage stochastic linear problems.

There’s limited support for continuous nonlinear convex problems, for which you can use Ipopt. There’s also some limited support for integer linear problems, for which you should use Gurobi or HiGHS.

But there is no support for MINLP.

whenever there are multiplication, square root or division, constraints or objectives should be posted as nonlinear?

One of my constraints is defined as (using SDDP.jl):

@NLconstraint(
        sp, 
        flow == (0.685 - 0.19 * n * 0.05 / (level.in - 261)) * 0.5 * n * sqrt(2 * 9.81 * (level.in - 261))
    )

You might want to revisit the theory behind SDDP.jl: Introductory theory · SDDP.jl

It approximates convex functions, so things like 1 / level.in and sqrt(level.in) or nonlinear equality constraints will not work.

SDDP.jl lets you formulate nonlinear models, because in some cases you can formulates and solve convex nonlinear problems, but if you write a non-convex constraint, SDDP.jl will give you a suboptimal answer. If you don’t have integer variables, try solving it with Ipopt, but there is no guarantees on what could go wrong. If you do have integer variables, consider a different solution technique.

As a side note: dealing with head effects in hydro-thermal scheduling is an open question in the literature. A few different solutions have been proposed, but no SDDP-type algorithms adequately deal with the non-convexities. In general, you could consider training on a convex approximation, but then simulate with the non-convexities, but explaining how to do this is quite complicated and probably outside the scope of this forum. It’d be a research/engineering paper in and of itself.

1 Like

Thanks! I will not use integer variable in my case.

Despite of SDDP.jl, is there any other package supported to solve multistage dynamic programming and also MINLP? In my case, I don’t really care about stochasticity, the main issue is about multistage.

If you have a deterministic time-staged MINLP, why not just formulate it as a single large MINLP? Time-staged decomposition methods don’t work well for MINLP due to the non-convexity.

Well, I attempt to formulate my problem as a single large MINLP at the beginning. But it seems to be a little complicated, so I turn to SDDP.jl