Skip to content

Commit

Permalink
Add test for segfault issue (#215)
Browse files Browse the repository at this point in the history
  • Loading branch information
odow authored Apr 24, 2023
1 parent a78e129 commit c61c118
Show file tree
Hide file tree
Showing 3 changed files with 5,851 additions and 2 deletions.
29 changes: 27 additions & 2 deletions src/MOI_wrapper/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ const OptimizerCache = MOI.Utilities.GenericModel{
Optimizer()
Create a new Cbc Optimizer.
## Variable names
By default, Cbc.jl will pass variable names to the C model. In some instances,
this has caused segfaults. Disable names being passed to the C model using
```julia
using JuMP, Cbc
model = Model(
optimizer_with_attributes(Cbc.Optimizer, Cbc.SetVariableNames() => false),
)
```
"""
mutable struct Optimizer <: MOI.AbstractOptimizer
inner::Ptr{Cvoid}
Expand All @@ -63,7 +74,7 @@ mutable struct Optimizer <: MOI.AbstractOptimizer
has_solution::Bool
variable_primal::Union{Nothing,Vector{Float64}}
constraint_primal::Union{Nothing,Vector{Float64}}

set_names::Bool
function Optimizer()
model = new(
Cbc_newModel(),
Expand All @@ -77,6 +88,7 @@ mutable struct Optimizer <: MOI.AbstractOptimizer
false,
nothing,
nothing,
true,
)
finalizer(Cbc_deleteModel, model)
return model
Expand All @@ -90,6 +102,17 @@ function MOI.default_cache(::Optimizer, ::Type{Float64})
return MOI.Utilities.UniversalFallback(OptimizerCache())
end

struct SetVariableNames <: MOI.AbstractOptimizerAttribute end

MOI.supports(::Optimizer, ::SetVariableNames) = true

function MOI.set(model::Optimizer, ::SetVariableNames, flag::Bool)
model.set_names = flag
return
end

MOI.get(model::Optimizer, ::SetVariableNames) = model.set_names

function MOI.supports(::Optimizer, ::MOI.RawOptimizerAttribute)
# TODO(odow): There is no programatical way throught the C API to check if a
# parameter name (or value) is valid. Fix this upstream.
Expand Down Expand Up @@ -487,7 +510,9 @@ function MOI.set(
name::String,
)
@assert isascii(name)
Cbc_setColName(model, Cint(x.value - 1), name)
if MOI.get(model, SetVariableNames())
Cbc_setColName(model, Cint(x.value - 1), name)
end
return
end

Expand Down
18 changes: 18 additions & 0 deletions test/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,24 @@ function test_variable_name()
return
end

"""
This example segfaults if variable names are set. Turn them off and check we get
a feasible solution.
"""
function test_segfault()
src = MOI.FileFormats.MOF.Model()
MOI.read_from_file(src, joinpath(@__DIR__, "segfault.mof.json"))
cbc = Cbc.Optimizer()
@test MOI.supports(cbc, Cbc.SetVariableNames())
@test MOI.get(cbc, Cbc.SetVariableNames()) == true
MOI.set(cbc, Cbc.SetVariableNames(), false)
@test MOI.get(cbc, Cbc.SetVariableNames()) == false
index_map = MOI.copy_to(cbc, src)
MOI.optimize!(cbc)
@test MOI.get(cbc, MOI.TerminationStatus()) == MOI.OPTIMAL
return
end

end

TestMOIWrapper.runtests()
Loading

0 comments on commit c61c118

Please sign in to comment.