Skip to content

Error when trying to change parameter value #289

@Giovanni3A

Description

@Giovanni3A

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]:1

This 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
 InvalidConstraintRef

and 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions