Skip to content

Commit 3cdd7c4

Browse files
committed
Improve test coverage of the MOI wrapper
1 parent 888a3a0 commit 3cdd7c4

File tree

5 files changed

+87
-27
lines changed

5 files changed

+87
-27
lines changed

src/MOI_wrapper.jl

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -484,17 +484,6 @@ function MOI.get(
484484
return attributes
485485
end
486486

487-
# MOI.ListOfOptimizerAttributesSet
488-
489-
function MOI.get(::Optimizer, ::MOI.ListOfOptimizerAttributesSet)
490-
attributes = MOI.ListOfOptimizerAttributesSet[]
491-
timelim = MOI.get(o, MOI.TimeLimitSec())
492-
if timelim !== nothing
493-
push!(attributes, MOI.TimeLimitSec())
494-
end
495-
return attributes
496-
end
497-
498487
include(joinpath("MOI_wrapper", "variable.jl"))
499488
include(joinpath("MOI_wrapper", "constraints.jl"))
500489
include(joinpath("MOI_wrapper", "linear_constraints.jl"))

src/MOI_wrapper/HeuristicCallback.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ end
1515
mutable struct HeuristicCb <: Heuristic
1616
scipd::SCIPData
1717
heurcallback::Function
18+
19+
HeuristicCb(scipd::SCIPData, cb = cb_data -> nothing) = new(scipd, cb)
1820
end
1921

20-
# If no cut callback is given, the cut callback does nothing.
21-
HeuristicCb(scipd::SCIPData) = HeuristicCb(scipd, cb_data -> nothing)
2222

2323
"""
2424
Used for an argument to the heuristic callback, which in turn uses that argument to

src/MOI_wrapper/UserCutCallback.jl

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,11 @@ end
2929
mutable struct CutCbSeparator <: AbstractSeparator
3030
scipd::SCIPData
3131
cutcallback::Function
32+
33+
CutCbSeparator(scipd::SCIPData, cb = cb_data -> nothing) = new(scipd, cb)
3234
end
3335

3436
# If no cut callback is given, the cut callback does nothing.
35-
CutCbSeparator(scipd::SCIPData) = CutCbSeparator(scipd, cb_data -> nothing)
3637

3738
"""
3839
Used for an argument to the cut callback, which in turn uses that argument to

src/MOI_wrapper/quadratic_constraints.jl

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,6 @@ function MOI.add_constraint(
5050
return ci
5151
end
5252

53-
function MOI.set(
54-
o::SCIP.Optimizer,
55-
::MOI.ConstraintSet,
56-
ci::MOI.ConstraintIndex{MOI.ScalarQuadraticFunction{Float64},S},
57-
set::S,
58-
) where {S<:BOUNDS}
59-
allow_modification(o)
60-
lhs, rhs = bounds(o, set)
61-
@SCIP_CALL SCIPchgLhsQuadratic(o, cons(o, ci), lhs)
62-
@SCIP_CALL SCIPchgRhsQuadratic(o, cons(o, ci), rhs)
63-
return nothing
64-
end
65-
6653
function MOI.get(
6754
o::Optimizer,
6855
::MOI.ConstraintFunction,

test/MOI_tests.jl

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -730,6 +730,7 @@ function _test_presolving(presolving)
730730
),
731731
)
732732
MOI.set(optimizer, MOI.ObjectiveSense(), MOI.MAX_SENSE)
733+
@test MOI.supports(optimizer, SCIP.Presolving())
733734
@test MOI.get(optimizer, SCIP.Presolving()) == true
734735
MOI.set(optimizer, SCIP.Presolving(), presolving)
735736
@test MOI.get(optimizer, SCIP.Presolving()) == presolving
@@ -865,9 +866,11 @@ function test_heuristic_callback()
865866
values[findmax(x_frac)[2]] = 1.0
866867
values[1] = 1.0
867868
values[2] = 1.0
869+
@test MOI.supports(o, MOI.HeuristicSolution(callback_data))
868870
MOI.submit(o, MOI.HeuristicSolution(callback_data), x, values)
869871
global ncalls[] += 1
870872
end
873+
@test MOI.supports(o, MOI.HeuristicCallback())
871874
MOI.set(o, MOI.HeuristicCallback(), heuristic_callback)
872875
MOI.optimize!(o)
873876
@test ncalls[] > 0
@@ -1195,6 +1198,7 @@ function test_obtaining_the_LP_solution()
11951198
)
11961199
calls += 1
11971200
end
1201+
@test MOI.supports(optimizer, MOI.UserCutCallback())
11981202
MOI.set(optimizer, MOI.UserCutCallback(), cutcallback)
11991203
# solve the problem
12001204
MOI.optimize!(optimizer)
@@ -1237,6 +1241,7 @@ function test_cutting_one_optimal_solution()
12371241
MOI.set(optimizer, MOI.ObjectiveSense(), MOI.MAX_SENSE)
12381242
calls = 0
12391243
function cutcallback(cb_data)
1244+
@test MOI.supports(optimizer, MOI.UserCut{SCIP.CutCbData}(cb_data))
12401245
MOI.submit(
12411246
optimizer,
12421247
MOI.UserCut{SCIP.CutCbData}(cb_data),
@@ -1500,6 +1505,84 @@ function test_AddSingleCut_too_strong_cut()
15001505
return
15011506
end
15021507

1508+
function test_ScalarFunctionConstantNotZero_quadratic()
1509+
model = SCIP.Optimizer()
1510+
x = MOI.add_variable(model)
1511+
f = 1.0 * x * x + 2.0
1512+
@test_throws(
1513+
MOI.ScalarFunctionConstantNotZero,
1514+
MOI.add_constraint(model, f, MOI.LessThan(3.0)),
1515+
)
1516+
return
1517+
end
1518+
1519+
function test_ListOfSupportedNonlinearOperators()
1520+
model = SCIP.Optimizer()
1521+
op = MOI.get(model, MOI.ListOfSupportedNonlinearOperators())
1522+
@test op isa Vector{Symbol}
1523+
@test length(op) == 11
1524+
return
1525+
end
1526+
1527+
function test_nonlinear_epigraph_functions()
1528+
op(f, args...) = MOI.ScalarNonlinearFunction(f, Any[args...])
1529+
default_set = MOI.Interval(1.0, 2.0)
1530+
for (fn, set, t_value) in [
1531+
(x -> op(:exp, 1.0 * x + 2.0), default_set, exp(3)),
1532+
(x -> op(:exp, 1.0 * x * x + 2.0), default_set, exp(3)),
1533+
(x -> op(:exp, 1.0 * x * x + 2.0 * x + 3.0), default_set, exp(6)),
1534+
# :/
1535+
(x -> op(:/, 2, x), MOI.Interval(1.0, 2.0), 1.0),
1536+
(x -> op(:/, 2, x), MOI.Interval(1.0, 1.5), 4 / 3),
1537+
# :abs
1538+
(x -> op(:abs, x), MOI.Interval(1.0, 2.0), 1.0),
1539+
(x -> op(:abs, x), MOI.Interval(-2.0, 2.0), 0.0),
1540+
(x -> op(:abs, x), MOI.Interval(-2.0, -1.3), 1.3),
1541+
# :exp
1542+
(x -> op(:exp, x), MOI.Interval(-2.0, -1.3), exp(-2)),
1543+
(x -> op(:exp, x), MOI.Interval(2.0, 3.0), exp(2)),
1544+
# :log
1545+
(x -> op(:-, op(:log, x)), MOI.Interval(2.0, 3.0), -log(3)),
1546+
# :sin
1547+
(x -> op(:sin, x), MOI.Interval(pi, 2 * pi), -1.0),
1548+
(x -> op(:sin, x), MOI.Interval(0.0, pi), 0.0),
1549+
# :cos
1550+
(x -> op(:cos, x), MOI.Interval(pi, 2 * pi), -1.0),
1551+
(x -> op(:cos, x), MOI.Interval(0.0, pi), -1.0),
1552+
(x -> op(:cos, x), MOI.Interval(-pi / 2, pi / 2), 0.0),
1553+
# :sqrt
1554+
(x -> op(:-, op(:sqrt, x)), MOI.Interval(2.0, 3.0), -sqrt(3)),
1555+
]
1556+
model = SCIP.Optimizer()
1557+
MOI.set(model, MOI.Silent(), true)
1558+
x, _ = MOI.add_constrained_variable(model, set)
1559+
t = MOI.add_variable(model)
1560+
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
1561+
F = MOI.ScalarAffineFunction{Float64}
1562+
MOI.set(model, MOI.ObjectiveFunction{F}(), 1.0 * t)
1563+
MOI.add_constraint(model, op(:-, t, fn(x)), MOI.GreaterThan(0.0))
1564+
MOI.optimize!(model)
1565+
@test (MOI.get(model, MOI.VariablePrimal(), t), t_value; atol = 1e-4)
1566+
end
1567+
return
1568+
end
1569+
1570+
function test_unsupported_nonlinear_operator()
1571+
model = SCIP.Optimizer()
1572+
x = MOI.add_variable(model)
1573+
f = MOI.ScalarNonlinearFunction(:foo, Any[x])
1574+
@test_throws(
1575+
MOI.UnsupportedNonlinearOperator(:foo),
1576+
MOI.add_constraint(model, f, MOI.GreaterThan(0.0)),
1577+
)
1578+
f = MOI.ScalarNonlinearFunction(:^, Any[x, x])
1579+
@test_throws(
1580+
MOI.UnsupportedNonlinearOperator(:^),
1581+
MOI.add_constraint(model, f, MOI.GreaterThan(0.0)),
1582+
)
1583+
return
1584+
end
1585+
15031586
end # module TestMOIWrapper
15041587

15051588
TestMOIWrapper.runtests()

0 commit comments

Comments
 (0)