Skip to content

Commit

Permalink
Merge pull request #103 from SCIP-Interfaces/rs/single_var_obj
Browse files Browse the repository at this point in the history
Support SingleVariable objective
  • Loading branch information
rschwarz committed Mar 3, 2019
2 parents 3f60770 + f6472e6 commit 0558de2
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 1 deletion.
22 changes: 21 additions & 1 deletion src/MOI_wrapper/objective.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
# objective function & sense
# Objective function & sense.
#
# SCIP only supports affine objectives. For quadratic or nonlinear objectives,
# the solver will depend on bridges with auxiliary variables. Single variable
# objectives are also accepted, but the type is not correctly remembered.

MOI.supports(::Optimizer, ::MOI.ObjectiveSense) = true
MOI.supports(::Optimizer, ::MOI.ObjectiveFunction{SAF}) = true
MOI.supports(::Optimizer, ::MOI.ObjectiveFunction{SVF}) = true

function MOI.set(o::Optimizer, ::MOI.ObjectiveFunction{SAF}, obj::SAF)
allow_modification(o)
Expand All @@ -24,6 +29,11 @@ function MOI.set(o::Optimizer, ::MOI.ObjectiveFunction{SAF}, obj::SAF)
return nothing
end

function MOI.set(o::Optimizer, ::MOI.ObjectiveFunction{SVF}, obj::SVF)
aff_obj = SAF([AFF_TERM(1.0, obj.variable)], 0.0)
return MOI.set(o, MOI.ObjectiveFunction{SAF}(), aff_obj)
end

function MOI.get(o::Optimizer, ::MOI.ObjectiveFunction{SAF})
terms = AFF_TERM[]
for vr = keys(o.mscip.vars)
Expand All @@ -35,6 +45,16 @@ function MOI.get(o::Optimizer, ::MOI.ObjectiveFunction{SAF})
return SAF(terms, constant)
end

function MOI.get(o::Optimizer, ::MOI.ObjectiveFunction{SVF})
aff_obj = MOI.get(o, MOI.ObjectiveFunction{SAF}())
if (length(aff_obj.terms) != 1
|| aff_obj.terms[1].coefficient != 1.0
|| aff_obj.constant != 0.0)
error("Objective is not single variable: $aff_obj !")
end
return SVF(aff_obj.terms[1].variable_index)
end

function MOI.set(o::Optimizer, ::MOI.ObjectiveSense, sense::MOI.OptimizationSense)
allow_modification(o)
if sense == MOI.MIN_SENSE
Expand Down
50 changes: 50 additions & 0 deletions test/MINLPTests/run_minlptests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ const DUALTOL = NaN # to disable the query
end

@testset "MINLPTests - nlp cvx" begin
@testset "nlp_cvx_001_010" begin
MINLPTests.nlp_cvx_001_010(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
termination_target = MOI.OPTIMAL)
end

@testset "nlp_cvx_002_010" begin
MINLPTests.nlp_cvx_002_010(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
termination_target = MOI.OPTIMAL)
Expand All @@ -29,6 +34,16 @@ end
termination_target = MOI.OPTIMAL)
end

@testset "nlp_cvx_101_012" begin
MINLPTests.nlp_cvx_101_012(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
termination_target = MOI.OPTIMAL)
end

@testset "nlp_cvx_102_010" begin
MINLPTests.nlp_cvx_102_010(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
termination_target = MOI.OPTIMAL)
end

@testset "nlp_cvx_102_011" begin
MINLPTests.nlp_cvx_102_011(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
termination_target = MOI.OPTIMAL)
Expand All @@ -39,6 +54,16 @@ end
termination_target = MOI.OPTIMAL)
end

@testset "nlp_cvx_103_010" begin
MINLPTests.nlp_cvx_103_010(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
termination_target = MOI.OPTIMAL)
end

@testset "nlp_cvx_103_011" begin
MINLPTests.nlp_cvx_103_011(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
termination_target = MOI.OPTIMAL)
end

@testset "nlp_cvx_103_012" begin
MINLPTests.nlp_cvx_103_012(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
termination_target = MOI.OPTIMAL)
Expand All @@ -49,6 +74,16 @@ end
termination_target = MOI.OPTIMAL)
end

@testset "nlp_cvx_103_014" begin
MINLPTests.nlp_cvx_103_014(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
termination_target = MOI.OPTIMAL)
end

@testset "nlp_cvx_104_010" begin
MINLPTests.nlp_cvx_104_010(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
termination_target = MOI.OPTIMAL)
end

@testset "nlp_cvx_105_010" begin
MINLPTests.nlp_cvx_105_010(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
termination_target = MOI.OPTIMAL)
Expand Down Expand Up @@ -79,6 +114,16 @@ end
termination_target = MOI.OPTIMAL)
end

@testset "nlp_cvx_202_010" begin
MINLPTests.nlp_cvx_202_010(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
termination_target = MOI.OPTIMAL)
end

@testset "nlp_cvx_202_011" begin
MINLPTests.nlp_cvx_202_011(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
termination_target = MOI.OPTIMAL)
end

@testset "nlp_cvx_202_012" begin
MINLPTests.nlp_cvx_202_012(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
termination_target = MOI.OPTIMAL)
Expand All @@ -104,6 +149,11 @@ end
termination_target = MOI.OPTIMAL)
end

@testset "nlp_cvx_205_010" begin
MINLPTests.nlp_cvx_205_010(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
termination_target = MOI.OPTIMAL)
end

# Wrong solution?!
# @testset "nlp_cvx_206_010" begin
# MINLPTests.nlp_cvx_206_010(OPTIMIZER, OBJTOL, PRIMALTOL, DUALTOL;
Expand Down
22 changes: 22 additions & 0 deletions test/MOI_additional.jl
Original file line number Diff line number Diff line change
Expand Up @@ -366,3 +366,25 @@ end
# fail to delete them in wrong order
@test_throws ErrorException MOI.delete(optimizer, x)
end

@testset "single variable objective" begin
optimizer = SCIP.Optimizer()

# Happy Path: add objective and retrieve it.
x = MOI.add_variable(optimizer)
obj = MOI.SingleVariable(x)
MOI.set(optimizer, MOI.ObjectiveFunction{MOI.SingleVariable}(), obj)
MOI.set(optimizer, MOI.ObjectiveSense(), MOI.MAX_SENSE)
@test MOI.get(optimizer, MOI.ObjectiveFunction{MOI.SingleVariable}()) == obj
@test MOI.get(optimizer, MOI.ObjectiveSense()) == MOI.MAX_SENSE

MOI.empty!(optimizer)

# Error with type mismatch
x = MOI.add_variable(optimizer)
y = MOI.add_variable(optimizer)
aff_obj = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 3.0)
MOI.set(optimizer, MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(), aff_obj)
MOI.set(optimizer, MOI.ObjectiveSense(), MOI.MAX_SENSE)
@test_throws ErrorException MOI.get(optimizer, MOI.ObjectiveFunction{MOI.SingleVariable}())
end

0 comments on commit 0558de2

Please sign in to comment.