-
Notifications
You must be signed in to change notification settings - Fork 15
Description
The following example, in which I create a very simple problem and add a DiffOpt optimizer, works the first time a parameter is set and optimize! is called:
m = JuMP.Model()
@variable(m, x)
@variable(m, c)
# c variable as MOI.Parameter
@constraint(m, c .∈ MOI.Parameter.(zeros(1)))
# objective function
@objective(m, Min, x*(c+x))
# optimizer from diffopt
new_diff_optimizer =
JuMP.set_optimizer(m, () ->
DiffOpt.diff_optimizer(
Gurobi.Optimizer;
with_parametric_opt_interface = true
)
)
# optimize first time
DiffOpt.set_parameter_value.(c, rand(1))
optimize!(m)but when trying to change the parameter value and optimize again:
# second time -> error
DiffOpt.set_parameter_value.(c, rand(1))
optimize!(m)
>> MathOptInterface.ModifyObjectiveNotAllowed{MathOptInterface.ScalarCoefficientChange{Float64}}: Modifying the objective function with MathOptInterface.ScalarCoefficientChange{Float64}(MOI.VariableIndex(1), 0.7237308297251812) cannot be performed. You may want to use a `CachingOptimizer` in `AUTOMATIC` mode or you may need to call `reset_optimizer` before doing this operation if the `CachingOptimizer` is in `MANUAL` mode.
Stacktrace:
[1] throw_modify_not_allowed(::MathOptInterface.ObjectiveFunction{MathOptInterface.ScalarQuadraticFunction{Float64}}, args::MathOptInterface.ScalarCoefficientChange{Float64})
@ MathOptInterface ~/.julia/packages/MathOptInterface/98sse/src/modifications.jl:64
[2] modify(model::DiffOpt.Optimizer{MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Bridges.LazyBridgeOptimizer{Gurobi.Optimizer}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}, attr::MathOptInterface.ObjectiveFunction{MathOptInterface.ScalarQuadraticFunction{Float64}}, change::MathOptInterface.ScalarCoefficientChange{Float64})
@ MathOptInterface ~/.julia/packages/MathOptInterface/98sse/src/modifications.jl:201
[3] modify(model::DiffOpt.Optimizer{MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Bridges.LazyBridgeOptimizer{Gurobi.Optimizer}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}, attr::MathOptInterface.ObjectiveFunction{MathOptInterface.ScalarQuadraticFunction{Float64}}, changes::Vector{MathOptInterface.ScalarCoefficientChange})
@ MathOptInterface ~/.julia/packages/MathOptInterface/98sse/src/modifications.jl:251
[4] _update_quadratic_objective!(model::ParametricOptInterface.Optimizer{Float64, DiffOpt.Optimizer{MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Bridges.LazyBridgeOptimizer{Gurobi.Optimizer}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}})
@ ParametricOptInterface ~/.julia/packages/ParametricOptInterface/DAcPt/src/update_parameters.jl:264
[5] update_parameters!(model::ParametricOptInterface.Optimizer{Float64, DiffOpt.Optimizer{MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Bridges.LazyBridgeOptimizer{Gurobi.Optimizer}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}})
@ ParametricOptInterface ~/.julia/packages/ParametricOptInterface/DAcPt/src/update_parameters.jl:274
[6] optimize!(model::ParametricOptInterface.Optimizer{Float64, DiffOpt.Optimizer{MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Bridges.LazyBridgeOptimizer{Gurobi.Optimizer}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}})
@ ParametricOptInterface ~/.julia/packages/ParametricOptInterface/DAcPt/src/MOI_wrapper.jl:1528
[7] optimize!
@ ~/.julia/packages/MathOptInterface/98sse/src/Bridges/bridge_optimizer.jl:367 [inlined]
[8] optimize!(m::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Bridges.LazyBridgeOptimizer{ParametricOptInterface.Optimizer{Float64, DiffOpt.Optimizer{MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Bridges.LazyBridgeOptimizer{Gurobi.Optimizer}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}}}}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}})
@ MathOptInterface.Utilities ~/.julia/packages/MathOptInterface/98sse/src/Utilities/cachingoptimizer.jl:379
[9] optimize!(model::JuMP.Model; ignore_optimize_hook::Bool, _differentiation_backend::MathOptInterface.Nonlinear.SparseReverseMode, kwargs::@Kwargs{})
@ JuMP ~/.julia/packages/JuMP/RGIK3/src/optimizer_interface.jl:595
[10] optimize!(model::JuMP.Model)
@ JuMP ~/.julia/packages/JuMP/RGIK3/src/optimizer_interface.jl:546
[11] top-level scope
@ REPL[594]:1This only happens when the objective function contains x^2 AND x*c. If only one of those (or x+c) is present in the objective function, it works as expected.
If I run MOI.Utilities.reset_optimizer(m) between the first optimize! call and setting the parameter value for the second time, it works as expected.
Maybe unrelated, if I use direct_model to build the model, the constraint is recognized as invalid:
m = JuMP.direct_model(
DiffOpt.diff_optimizer(
HiGHS.Optimizer;
with_parametric_opt_interface = true
)
)
@variable(m, x .>= 0)
@variable(m, c)
@constraint(m, c .∈ MOI.Parameter.(zeros(1)))
@objective(m, Min, x*(c+x))
print(m)
>> Min x*c + x²
Subject to
x ≥ 0
InvalidConstraintRefand when trying to set the parameter value, an error Parameter not in the model is raised.
Replacing DiffOpt.set_parameter_value.(c, rand(1)) to MOI.set.(m, POI.ParameterValue(), c, rand(1)) didn't change any of the results.