Skip to content

Commit 0558de2

Browse files
authored
Merge pull request #103 from SCIP-Interfaces/rs/single_var_obj
Support SingleVariable objective
2 parents 3f60770 + f6472e6 commit 0558de2

File tree

3 files changed

+93
-1
lines changed

3 files changed

+93
-1
lines changed

src/MOI_wrapper/objective.jl

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
# objective function & sense
1+
# Objective function & sense.
2+
#
3+
# SCIP only supports affine objectives. For quadratic or nonlinear objectives,
4+
# the solver will depend on bridges with auxiliary variables. Single variable
5+
# objectives are also accepted, but the type is not correctly remembered.
26

37
MOI.supports(::Optimizer, ::MOI.ObjectiveSense) = true
48
MOI.supports(::Optimizer, ::MOI.ObjectiveFunction{SAF}) = true
9+
MOI.supports(::Optimizer, ::MOI.ObjectiveFunction{SVF}) = true
510

611
function MOI.set(o::Optimizer, ::MOI.ObjectiveFunction{SAF}, obj::SAF)
712
allow_modification(o)
@@ -24,6 +29,11 @@ function MOI.set(o::Optimizer, ::MOI.ObjectiveFunction{SAF}, obj::SAF)
2429
return nothing
2530
end
2631

32+
function MOI.set(o::Optimizer, ::MOI.ObjectiveFunction{SVF}, obj::SVF)
33+
aff_obj = SAF([AFF_TERM(1.0, obj.variable)], 0.0)
34+
return MOI.set(o, MOI.ObjectiveFunction{SAF}(), aff_obj)
35+
end
36+
2737
function MOI.get(o::Optimizer, ::MOI.ObjectiveFunction{SAF})
2838
terms = AFF_TERM[]
2939
for vr = keys(o.mscip.vars)
@@ -35,6 +45,16 @@ function MOI.get(o::Optimizer, ::MOI.ObjectiveFunction{SAF})
3545
return SAF(terms, constant)
3646
end
3747

48+
function MOI.get(o::Optimizer, ::MOI.ObjectiveFunction{SVF})
49+
aff_obj = MOI.get(o, MOI.ObjectiveFunction{SAF}())
50+
if (length(aff_obj.terms) != 1
51+
|| aff_obj.terms[1].coefficient != 1.0
52+
|| aff_obj.constant != 0.0)
53+
error("Objective is not single variable: $aff_obj !")
54+
end
55+
return SVF(aff_obj.terms[1].variable_index)
56+
end
57+
3858
function MOI.set(o::Optimizer, ::MOI.ObjectiveSense, sense::MOI.OptimizationSense)
3959
allow_modification(o)
4060
if sense == MOI.MIN_SENSE

test/MINLPTests/run_minlptests.jl

+50
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@ const DUALTOL = NaN # to disable the query
1919
end
2020

2121
@testset "MINLPTests - nlp cvx" begin
22+
@testset "nlp_cvx_001_010" begin
23+
MINLPTests.nlp_cvx_001_010(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
24+
termination_target = MOI.OPTIMAL)
25+
end
26+
2227
@testset "nlp_cvx_002_010" begin
2328
MINLPTests.nlp_cvx_002_010(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
2429
termination_target = MOI.OPTIMAL)
@@ -29,6 +34,16 @@ end
2934
termination_target = MOI.OPTIMAL)
3035
end
3136

37+
@testset "nlp_cvx_101_012" begin
38+
MINLPTests.nlp_cvx_101_012(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
39+
termination_target = MOI.OPTIMAL)
40+
end
41+
42+
@testset "nlp_cvx_102_010" begin
43+
MINLPTests.nlp_cvx_102_010(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
44+
termination_target = MOI.OPTIMAL)
45+
end
46+
3247
@testset "nlp_cvx_102_011" begin
3348
MINLPTests.nlp_cvx_102_011(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
3449
termination_target = MOI.OPTIMAL)
@@ -39,6 +54,16 @@ end
3954
termination_target = MOI.OPTIMAL)
4055
end
4156

57+
@testset "nlp_cvx_103_010" begin
58+
MINLPTests.nlp_cvx_103_010(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
59+
termination_target = MOI.OPTIMAL)
60+
end
61+
62+
@testset "nlp_cvx_103_011" begin
63+
MINLPTests.nlp_cvx_103_011(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
64+
termination_target = MOI.OPTIMAL)
65+
end
66+
4267
@testset "nlp_cvx_103_012" begin
4368
MINLPTests.nlp_cvx_103_012(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
4469
termination_target = MOI.OPTIMAL)
@@ -49,6 +74,16 @@ end
4974
termination_target = MOI.OPTIMAL)
5075
end
5176

77+
@testset "nlp_cvx_103_014" begin
78+
MINLPTests.nlp_cvx_103_014(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
79+
termination_target = MOI.OPTIMAL)
80+
end
81+
82+
@testset "nlp_cvx_104_010" begin
83+
MINLPTests.nlp_cvx_104_010(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
84+
termination_target = MOI.OPTIMAL)
85+
end
86+
5287
@testset "nlp_cvx_105_010" begin
5388
MINLPTests.nlp_cvx_105_010(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
5489
termination_target = MOI.OPTIMAL)
@@ -79,6 +114,16 @@ end
79114
termination_target = MOI.OPTIMAL)
80115
end
81116

117+
@testset "nlp_cvx_202_010" begin
118+
MINLPTests.nlp_cvx_202_010(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
119+
termination_target = MOI.OPTIMAL)
120+
end
121+
122+
@testset "nlp_cvx_202_011" begin
123+
MINLPTests.nlp_cvx_202_011(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
124+
termination_target = MOI.OPTIMAL)
125+
end
126+
82127
@testset "nlp_cvx_202_012" begin
83128
MINLPTests.nlp_cvx_202_012(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
84129
termination_target = MOI.OPTIMAL)
@@ -104,6 +149,11 @@ end
104149
termination_target = MOI.OPTIMAL)
105150
end
106151

152+
@testset "nlp_cvx_205_010" begin
153+
MINLPTests.nlp_cvx_205_010(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
154+
termination_target = MOI.OPTIMAL)
155+
end
156+
107157
# Wrong solution?!
108158
# @testset "nlp_cvx_206_010" begin
109159
# MINLPTests.nlp_cvx_206_010(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;

test/MOI_additional.jl

+22
Original file line numberDiff line numberDiff line change
@@ -366,3 +366,25 @@ end
366366
# fail to delete them in wrong order
367367
@test_throws ErrorException MOI.delete(optimizer, x)
368368
end
369+
370+
@testset "single variable objective" begin
371+
optimizer = SCIP.Optimizer()
372+
373+
# Happy Path: add objective and retrieve it.
374+
x = MOI.add_variable(optimizer)
375+
obj = MOI.SingleVariable(x)
376+
MOI.set(optimizer, MOI.ObjectiveFunction{MOI.SingleVariable}(), obj)
377+
MOI.set(optimizer, MOI.ObjectiveSense(), MOI.MAX_SENSE)
378+
@test MOI.get(optimizer, MOI.ObjectiveFunction{MOI.SingleVariable}()) == obj
379+
@test MOI.get(optimizer, MOI.ObjectiveSense()) == MOI.MAX_SENSE
380+
381+
MOI.empty!(optimizer)
382+
383+
# Error with type mismatch
384+
x = MOI.add_variable(optimizer)
385+
y = MOI.add_variable(optimizer)
386+
aff_obj = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 3.0)
387+
MOI.set(optimizer, MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(), aff_obj)
388+
MOI.set(optimizer, MOI.ObjectiveSense(), MOI.MAX_SENSE)
389+
@test_throws ErrorException MOI.get(optimizer, MOI.ObjectiveFunction{MOI.SingleVariable}())
390+
end

0 commit comments

Comments
 (0)