Skip to content

Commit

Permalink
Fix failed MOI tests (#434)
Browse files Browse the repository at this point in the history
  • Loading branch information
metab0t authored Nov 13, 2021
1 parent fbb1817 commit b20d76a
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 32 deletions.
71 changes: 42 additions & 29 deletions src/MOI_wrapper/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,9 @@ mutable struct Optimizer <: MOI.AbstractOptimizer
# An enum to remember what objective is currently stored in the model.
objective_type::_ObjectiveType

# A flag to keep track of MOI.FEASIBILITY_SENSE, since Gurobi only stores
# MIN_SENSE or MAX_SENSE. This allows us to differentiate between MIN_SENSE
# and FEASIBILITY_SENSE.
is_feasibility::Bool
# track whether objective function is set and the state of objective sense
is_objective_set::Bool
objective_sense::Union{Nothing,MOI.OptimizationSense}

# A mapping from the MOI.VariableIndex to the Gurobi column. _VariableInfo
# also stores some additional fields like what bounds have been added, the
Expand Down Expand Up @@ -401,7 +400,8 @@ function MOI.empty!(model::Optimizer)
end
model.needs_update = false
model.objective_type = _SCALAR_AFFINE
model.is_feasibility = true
model.is_objective_set = false
model.objective_sense = nothing
empty!(model.variable_info)
model.next_column = 1
empty!(model.columns_deleted_since_last_update)
Expand All @@ -428,7 +428,8 @@ end
function MOI.is_empty(model::Optimizer)
model.needs_update && return false
model.objective_type != _SCALAR_AFFINE && return false
model.is_feasibility == false && return false
model.is_objective_set == true && return false
model.objective_sense !== nothing && return false
!isempty(model.variable_info) && return false
!isone(model.next_column) && return false
!isempty(model.columns_deleted_since_last_update) && return false
Expand Down Expand Up @@ -661,19 +662,37 @@ function MOI.get(model::Optimizer, ::MOI.ListOfVariableAttributesSet)
end

function MOI.get(model::Optimizer, ::MOI.ListOfModelAttributesSet)
attributes = Any[MOI.ObjectiveSense()]
typ = MOI.get(model, MOI.ObjectiveFunctionType())
if typ !== nothing
push!(attributes, MOI.ObjectiveFunction{typ}())
if MOI.is_empty(model)
return Any[]
end
attributes = Any[]
if model.objective_sense !== nothing
push!(attributes, MOI.ObjectiveSense())
end
if model.is_objective_set
F = MOI.get(model, MOI.ObjectiveFunctionType())
push!(attributes, MOI.ObjectiveFunction{F}())
end
if MOI.get(model, MOI.Name()) != ""
push!(attributes, MOI.Name())
end
return attributes
end

function MOI.get(model::Optimizer, ::MOI.ListOfConstraintAttributesSet)
return MOI.AbstractConstraintAttribute[MOI.ConstraintName()]
function MOI.get(
model::Optimizer,
::MOI.ListOfConstraintAttributesSet{F,S},
) where {S,F}
ret = MOI.AbstractConstraintAttribute[]
constraint_indices = MOI.get(model, MOI.ListOfConstraintIndices{F,S}())
found_name = any(
!isempty(MOI.get(model, MOI.ConstraintName(), index)) for
index in constraint_indices
)
if found_name
push!(ret, MOI.ConstraintName())
end
return ret
end

function _indices_and_coefficients(
Expand Down Expand Up @@ -1010,34 +1029,25 @@ function MOI.set(
if sense == MOI.MIN_SENSE
ret = GRBsetintattr(model, "ModelSense", 1)
_check_ret(model, ret)
model.is_feasibility = false
elseif sense == MOI.MAX_SENSE
ret = GRBsetintattr(model, "ModelSense", -1)
_check_ret(model, ret)
model.is_feasibility = false
else
@assert sense == MOI.FEASIBILITY_SENSE
_zero_objective(model)
ret = GRBsetintattr(model, "ModelSense", 1)
_check_ret(model, ret)
model.is_feasibility = true
end
model.objective_sense = sense
_require_update(model)
return
end

function MOI.get(model::Optimizer, ::MOI.ObjectiveSense)
_update_if_necessary(model)
sense = Ref{Cint}()
ret = GRBgetintattr(model, "ModelSense", sense)
_check_ret(model, ret)
if model.is_feasibility
return MOI.FEASIBILITY_SENSE
elseif sense[] == -1
return MOI.MAX_SENSE
if model.objective_sense !== nothing
return model.objective_sense
else
@assert sense[] == 1
return MOI.MIN_SENSE
return MOI.FEASIBILITY_SENSE
end
end

Expand All @@ -1052,6 +1062,7 @@ function MOI.set(
convert(MOI.ScalarAffineFunction{Float64}, f),
)
model.objective_type = _SINGLE_VARIABLE
model.is_objective_set = true
return
end

Expand Down Expand Up @@ -1087,7 +1098,9 @@ function MOI.set(
ret = GRBsetdblattr(model, "ObjCon", f.constant)
_check_ret(model, ret)
_require_update(model)
return model.objective_type = _SCALAR_AFFINE
model.objective_type = _SCALAR_AFFINE
model.is_objective_set = true
return
end

function MOI.get(
Expand Down Expand Up @@ -1140,6 +1153,7 @@ function MOI.set(
_check_ret(model, ret)
_require_update(model)
model.objective_type = _SCALAR_QUADRATIC
model.is_objective_set = true
return
end

Expand Down Expand Up @@ -3409,9 +3423,7 @@ function MOI.get(model::Optimizer, ::MOI.ListOfConstraintTypesPresent)
end

function MOI.get(model::Optimizer, ::MOI.ObjectiveFunctionType)
if model.is_feasibility
return nothing
elseif model.objective_type == _SINGLE_VARIABLE
if model.objective_type == _SINGLE_VARIABLE
return MOI.VariableIndex
elseif model.objective_type == _SCALAR_AFFINE
return MOI.ScalarAffineFunction{Float64}
Expand Down Expand Up @@ -3450,6 +3462,7 @@ function MOI.modify(
chg.new_coefficient,
)
_check_ret(model, ret)
model.is_objective_set = true
_require_update(model)
return
end
Expand Down
5 changes: 2 additions & 3 deletions test/MOI/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,9 @@ function test_runtests()
MOI.Test.Config(atol = 1e-3, rtol = 1e-3),
exclude = String[
# TODO(odow): investigate errors
"test_objective_set_via_modify",
"test_model_ListOfConstraintAttributesSet",
# Gurobi Error 10015: Cannot compute IIS on a feasible model
# https://www.gurobi.com/documentation/9.5/refman/error_codes.html
"test_solve_conflict_feasible",
"test_objective_get_ObjectiveFunction_ScalarAffineFunction",
# SecondOrderCone does not return dual solutions. Tested below.
"_SecondOrderCone_",
"test_constraint_PrimalStart_DualStart_SecondOrderCone",
Expand Down

0 comments on commit b20d76a

Please sign in to comment.