Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ OpenBLAS32_jll = "656ef2d0-ae68-5445-9ca0-591084a874a2"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[compat]
Cbc_jll = "=200.1000.1200"
Cbc_jll = "=200.1000.1300"
LinearAlgebra = "1"
MathOptInterface = "1.7"
OpenBLAS32_jll = "0.3.10"
Expand Down
8 changes: 0 additions & 8 deletions src/MOI_wrapper/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -393,12 +393,10 @@ function MOI.copy_to(dest::Optimizer, src::OptimizerCache)
end
end
end
any_sos = false
for (S, type) in ((MOI.SOS1{Float64}, 1), (MOI.SOS2{Float64}, 2))
starts, indices, weights = Cint[], Cint[], Float64[]
attr = MOI.ListOfConstraintIndices{MOI.VectorOfVariables,S}()
for ci in MOI.get(src, attr)
any_sos = true
push!(starts, Cint(length(weights)))
f = MOI.get(src, MOI.ConstraintFunction(), ci)
for x in f.variables
Expand All @@ -413,12 +411,6 @@ function MOI.copy_to(dest::Optimizer, src::OptimizerCache)
Cbc_addSOS(dest, N, starts, indices, weights, Cint(type))
end
end
if any_sos && Cbc_getNumIntegers(dest) == 0
@warn(
"There are known correctness issues using Cbc with SOS " *
"constraints and no binary variables.",
)
end
return _index_map(src)
end

Expand Down
206 changes: 4 additions & 202 deletions test/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,17 @@ import Cbc
import MathOptInterface as MOI

function runtests()
for name in names(@__MODULE__; all = true)
if startswith("$(name)", "test_")
@testset "$(name)" begin
getfield(@__MODULE__, name)()
end
end
is_test(name) = startswith("$(name)", "test_")
@testset "$name" for name in filter(is_test, names(@__MODULE__; all = true))
getfield(@__MODULE__, name)()
end
return
end

function test_SolverName()
@test MOI.get(Cbc.Optimizer(), MOI.SolverName()) ==
"COIN Branch-and-Cut (Cbc)"
return
end

function test_supports_incremental_interface()
Expand All @@ -36,10 +34,6 @@ function test_runtests()
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
MOI.instantiate(Cbc.Optimizer; with_bridge_type = Float64),
)
MOI.Bridges.remove_bridge(
model.optimizer,
MOI.Bridges.Variable.ZerosBridge{Float64},
)
MOI.set(model, MOI.Silent(), true)
MOI.Test.runtests(
model,
Expand All @@ -52,11 +46,6 @@ function test_runtests()
],
),
exclude = [
# TODO(odow): upstream bug in Cbc
"test_linear_Indicator_",
"test_linear_SOS1_integration",
"test_linear_SOS2_integration",
"test_solve_SOS2_add_and_delete",
# Can't prove infeasible.
"test_conic_NormInfinityCone_INFEASIBLE",
"test_conic_NormOneCone_INFEASIBLE",
Expand Down Expand Up @@ -199,193 +188,6 @@ function test_issue_187()
return
end

# The test_linear_SOS1_integration test with the additional requirement that all
# variables are integer.
function test_SOS1()
model = MOI.Bridges.full_bridge_optimizer(
MOI.Utilities.CachingOptimizer(
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
Cbc.Optimizer(),
),
Float64,
)
config = MOI.Test.Config()
MOI.set(model, MOI.Silent(), true)
@test MOI.supports_constraint(
model,
MOI.VectorOfVariables,
MOI.SOS1{Float64},
)
@test MOI.supports_constraint(
model,
MOI.VariableIndex,
MOI.LessThan{Float64},
)
v = MOI.add_variables(model, 3)
MOI.add_constraint.(model, v, MOI.Integer())
@test MOI.get(model, MOI.NumberOfVariables()) == 3
vc1 = MOI.add_constraint(model, v[1], MOI.LessThan(1.0))
@test vc1.value == v[1].value
vc2 = MOI.add_constraint(model, v[2], MOI.LessThan(1.0))
@test vc2.value == v[2].value
vc3 = MOI.add_constraint(model, v[3], MOI.LessThan(2.0))
@test vc3.value == v[3].value
c1 = MOI.add_constraint(
model,
MOI.VectorOfVariables([v[1], v[2]]),
MOI.SOS1([1.0, 2.0]),
)
c2 = MOI.add_constraint(
model,
MOI.VectorOfVariables([v[1], v[3]]),
MOI.SOS1([1.0, 2.0]),
)
@test MOI.get(
model,
MOI.NumberOfConstraints{MOI.VectorOfVariables,MOI.SOS1{Float64}}(),
) == 2
#=
To allow for permutations in the sets and variable vectors
we're going to sort according to the weights
=#
cs_sos = MOI.get(model, MOI.ConstraintSet(), c2)
cf_sos = MOI.get(model, MOI.ConstraintFunction(), c2)
p = sortperm(cs_sos.weights)
@test isapprox(cs_sos.weights[p], [1.0, 2.0], config)
@test cf_sos.variables[p] == v[[1, 3]]
objf =
MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([2.0, 1.0, 1.0], v), 0.0)
MOI.set(
model,
MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
objf,
)
MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE)
@test MOI.get(model, MOI.ObjectiveSense()) == MOI.MAX_SENSE
@test MOI.get(model, MOI.TerminationStatus()) == MOI.OPTIMIZE_NOT_CALLED
MOI.optimize!(model)
@test MOI.get(model, MOI.TerminationStatus()) == config.optimal_status
@test MOI.get(model, MOI.ResultCount()) >= 1
@test MOI.get(model, MOI.PrimalStatus()) == MOI.FEASIBLE_POINT
@test isapprox(MOI.get(model, MOI.ObjectiveValue()), 3, config)
@test isapprox(MOI.get(model, MOI.VariablePrimal(), v), [0, 1, 2], config)
MOI.delete(model, c1)
MOI.delete(model, c2)
MOI.optimize!(model)
@test MOI.get(model, MOI.TerminationStatus()) == config.optimal_status
@test MOI.get(model, MOI.ResultCount()) >= 1
@test MOI.get(model, MOI.PrimalStatus()) == MOI.FEASIBLE_POINT
@test isapprox(MOI.get(model, MOI.ObjectiveValue()), 5, config)
@test isapprox(MOI.get(model, MOI.VariablePrimal(), v), [1, 1, 2], config)
return
end

# The test_linear_SOS2_integration test with the additional requirement that all
# variables are integer.
function test_SOS2()
model = MOI.Bridges.full_bridge_optimizer(
MOI.Utilities.CachingOptimizer(
MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()),
Cbc.Optimizer(),
),
Float64,
)
config = MOI.Test.Config()
MOI.set(model, MOI.Silent(), true)
@test MOI.supports_constraint(
model,
MOI.VectorOfVariables,
MOI.SOS1{Float64},
)
@test MOI.supports_constraint(
model,
MOI.VectorOfVariables,
MOI.SOS2{Float64},
)
v = MOI.add_variables(model, 10)
@test MOI.get(model, MOI.NumberOfVariables()) == 10
bin_constraints = []
for i in 1:8
vc = MOI.add_constraint(model, v[i], MOI.Interval(0.0, 2.0))
@test vc.value == v[i].value
push!(bin_constraints, MOI.add_constraint(model, v[i], MOI.ZeroOne()))
@test bin_constraints[i].value == v[i].value
end
MOI.add_constraint(
model,
MOI.ScalarAffineFunction(
MOI.ScalarAffineTerm.([1.0, 2.0, 3.0, -1.0], v[[1, 2, 3, 9]]),
0.0,
),
MOI.EqualTo(0.0),
)
MOI.add_constraint(
model,
MOI.ScalarAffineFunction(
MOI.ScalarAffineTerm.(
[5.0, 4.0, 7.0, 2.0, 1.0, -1.0],
v[[4, 5, 6, 7, 8, 10]],
),
0.0,
),
MOI.EqualTo(0.0),
)
MOI.add_constraint(
model,
MOI.VectorOfVariables(v[[1, 2, 3]]),
MOI.SOS1([1.0, 2.0, 3.0]),
)
vv = MOI.VectorOfVariables(v[[4, 5, 6, 7, 8]])
sos2 = MOI.SOS2([5.0, 4.0, 7.0, 2.0, 1.0])
c = MOI.add_constraint(model, vv, sos2)
#=
To allow for permutations in the sets and variable vectors
we're going to sort according to the weights
=#
cs_sos = MOI.get(model, MOI.ConstraintSet(), c)
cf_sos = MOI.get(model, MOI.ConstraintFunction(), c)
p = sortperm(cs_sos.weights)
@test isapprox(cs_sos.weights[p], [1.0, 2.0, 4.0, 5.0, 7.0], config)
@test cf_sos.variables[p] == v[[8, 7, 5, 4, 6]]
objf = MOI.ScalarAffineFunction(
MOI.ScalarAffineTerm.([1.0, 1.0], [v[9], v[10]]),
0.0,
)
MOI.set(
model,
MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(),
objf,
)
MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE)
@test MOI.get(model, MOI.ObjectiveSense()) == MOI.MAX_SENSE
@test MOI.get(model, MOI.TerminationStatus()) == MOI.OPTIMIZE_NOT_CALLED
MOI.optimize!(model)
@test MOI.get(model, MOI.TerminationStatus()) == config.optimal_status
@test MOI.get(model, MOI.ResultCount()) >= 1
@test MOI.get(model, MOI.PrimalStatus()) == MOI.FEASIBLE_POINT
@test isapprox(MOI.get(model, MOI.ObjectiveValue()), 15.0, config)
@test isapprox(
MOI.get(model, MOI.VariablePrimal(), v),
[0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 3.0, 12.0],
config,
)
for cref in bin_constraints
MOI.delete(model, cref)
end
MOI.add_constraint.(model, v, MOI.Integer())
MOI.optimize!(model)
@test MOI.get(model, MOI.TerminationStatus()) == config.optimal_status
@test MOI.get(model, MOI.ResultCount()) >= 1
@test MOI.get(model, MOI.PrimalStatus()) == MOI.FEASIBLE_POINT
@test isapprox(MOI.get(model, MOI.ObjectiveValue()), 30.0, config)
@test isapprox(
MOI.get(model, MOI.VariablePrimal(), v),
[0.0, 0.0, 2.0, 2.0, 0.0, 2.0, 0.0, 0.0, 6.0, 24.0],
config,
)
return
end

"""
test_VariablePrimalStart()

Expand Down
Loading