-
Notifications
You must be signed in to change notification settings - Fork 18
Open
jump-dev/MathOptInterface.jl
#2808Description
@objective
and @constraint
seem to be reformulating x^2
to x*x
in nonlinear expressions, which leads to poorer McCormick relaxations. This isn't an issue when using the legacy macros of @NLobjective
and @NLconstraint
. I suspect this happens somewhere in
EAGO.jl/src/eago_optimizer/moi_wrapper.jl
Lines 74 to 100 in 15bb6cb
function MOI.add_constraint(m::Optimizer, f::F, s::S) where {F<:Union{SAF,SQF,MOI.ScalarNonlinearFunction},S<:INEQ_SETS} | |
check_inbounds!(m, f) | |
ci = CI{F, S}(m._input_problem._constraint_count += 1) | |
if f isa MOI.ScalarNonlinearFunction | |
if isnothing(m._input_problem._nlp_data) | |
model = MOI.Nonlinear.Model() | |
backend = MOI.Nonlinear.SparseReverseMode() | |
vars = MOI.get(m, MOI.ListOfVariableIndices()) | |
evaluator = MOI.Nonlinear.Evaluator(model, backend, vars) | |
m._input_problem._nlp_data = MOI.NLPBlockData(evaluator) | |
end | |
MOI.Nonlinear.add_constraint(m._input_problem._nlp_data.evaluator.model, f, s) | |
constraint_bounds = m._input_problem._nlp_data.constraint_bounds | |
has_objective = m._input_problem._nlp_data.has_objective | |
if s isa MOI.LessThan | |
push!(constraint_bounds, MOI.NLPBoundsPair(-Inf, s.upper)) | |
elseif s isa MOI.GreaterThan | |
push!(constraint_bounds, MOI.NLPBoundsPair(s.lower, Inf)) | |
else | |
push!(constraint_bounds, MOI.NLPBoundsPair(s.value, s.value)) | |
end | |
m._input_problem._nlp_data = MOI.NLPBlockData(constraint_bounds, m._input_problem._nlp_data.evaluator, has_objective) | |
else | |
_constraints(m, F, S)[ci] = (f, s) | |
end | |
return ci | |
end |
EAGO.jl/src/eago_optimizer/moi_wrapper.jl
Lines 277 to 294 in 15bb6cb
function MOI.set(m::Optimizer, ::MOI.ObjectiveFunction{T}, f::T) where T <: Union{VI,SAF,SQF,MOI.ScalarNonlinearFunction} | |
check_inbounds!(m, f) | |
if f isa MOI.ScalarNonlinearFunction | |
if isnothing(m._input_problem._nlp_data) | |
model = MOI.Nonlinear.Model() | |
MOI.Nonlinear.set_objective(model, f) | |
backend = MOI.Nonlinear.SparseReverseMode() | |
vars = MOI.get(m, MOI.ListOfVariableIndices()) | |
evaluator = MOI.Nonlinear.Evaluator(model, backend, vars) | |
m._input_problem._nlp_data = MOI.NLPBlockData(evaluator) | |
else | |
MOI.Nonlinear.set_objective(m._input_problem._nlp_data.evaluator.model, f) | |
m._input_problem._nlp_data = MOI.NLPBlockData(m._input_problem._nlp_data.evaluator) | |
end | |
else | |
m._input_problem._objective = f | |
end | |
end |
Example:
model = JuMP.Model(EAGO.Optimizer)
@variable(model, x[1:2])
@objective(model, Min, x[1]^2 + x[2]^3)
JuMP.optimize!(model)
returns
MathOptInterface.Nonlinear.Expression(
MathOptInterface.Nonlinear.Node[
MathOptInterface.Nonlinear.Node(MathOptInterface.Nonlinear.NODE_CALL_MULTIVARIATE, 2, -1),
MathOptInterface.Nonlinear.Node(MathOptInterface.Nonlinear.NODE_CALL_MULTIVARIATE, 1, 1),
MathOptInterface.Nonlinear.Node(MathOptInterface.Nonlinear.NODE_CALL_MULTIVARIATE, 3, 2),
MathOptInterface.Nonlinear.Node(MathOptInterface.Nonlinear.NODE_MOI_VARIABLE, 1, 3),
MathOptInterface.Nonlinear.Node(MathOptInterface.Nonlinear.NODE_MOI_VARIABLE, 1, 3),
MathOptInterface.Nonlinear.Node(MathOptInterface.Nonlinear.NODE_CALL_MULTIVARIATE, 4, 2),
MathOptInterface.Nonlinear.Node(MathOptInterface.Nonlinear.NODE_MOI_VARIABLE, 2, 6),
MathOptInterface.Nonlinear.Node(MathOptInterface.Nonlinear.NODE_VALUE, 1, 6),
MathOptInterface.Nonlinear.Node(MathOptInterface.Nonlinear.NODE_MOI_VARIABLE, 3, 1)
],
[3.0]
)
model = JuMP.Model(EAGO.Optimizer)
@variable(model, x[1:2])
@NLobjective(model, Min, x[1]^2 + x[2]^3)
JuMP.optimize!(model)
returns
MathOptInterface.Nonlinear.Expression(
MathOptInterface.Nonlinear.Node[
MathOptInterface.Nonlinear.Node(MathOptInterface.Nonlinear.NODE_CALL_MULTIVARIATE, 2, -1),
MathOptInterface.Nonlinear.Node(MathOptInterface.Nonlinear.NODE_CALL_MULTIVARIATE, 1, 1),
MathOptInterface.Nonlinear.Node(MathOptInterface.Nonlinear.NODE_CALL_MULTIVARIATE, 4, 2),
MathOptInterface.Nonlinear.Node(MathOptInterface.Nonlinear.NODE_MOI_VARIABLE, 1, 3),
MathOptInterface.Nonlinear.Node(MathOptInterface.Nonlinear.NODE_VALUE, 1, 3),
MathOptInterface.Nonlinear.Node(MathOptInterface.Nonlinear.NODE_CALL_MULTIVARIATE, 4, 2),
MathOptInterface.Nonlinear.Node(MathOptInterface.Nonlinear.NODE_MOI_VARIABLE, 2, 6),
MathOptInterface.Nonlinear.Node(MathOptInterface.Nonlinear.NODE_VALUE, 2, 6),
MathOptInterface.Nonlinear.Node(MathOptInterface.Nonlinear.NODE_MOI_VARIABLE, 3, 1)
],
[2.0, 3.0]
)
(i.e., x^2 + x^3
, as expected).
Metadata
Metadata
Assignees
Labels
No labels