From 0006ae9c9cb881d24de0e7fd0d77b00ad4241a48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Fri, 25 Oct 2019 12:13:28 +0200 Subject: [PATCH 1/3] bridged 0 test --- test/MOI_wrapper_bridged.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/MOI_wrapper_bridged.jl b/test/MOI_wrapper_bridged.jl index 3e9c1a9d..238dd56b 100644 --- a/test/MOI_wrapper_bridged.jl +++ b/test/MOI_wrapper_bridged.jl @@ -45,6 +45,7 @@ end @testset "MOI Integer Linear" begin excluded = String[] MOIT.intlineartest(BRIDGED, CONFIG, excluded) + MOIT.indicator3_test(BRIDGED, CONFIG) end @testset "MOI Integer Conic" begin From 12b81e48cc4aef9dc7cf2ab8caa00237a81d5a69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Fri, 25 Oct 2019 12:13:38 +0200 Subject: [PATCH 2/3] added constant term in indicator --- src/MOI_wrapper/indicator_constraints.jl | 4 +- test/MOI_wrapper_direct.jl | 80 ++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/src/MOI_wrapper/indicator_constraints.jl b/src/MOI_wrapper/indicator_constraints.jl index 90e96902..c63ca6a0 100644 --- a/src/MOI_wrapper/indicator_constraints.jl +++ b/src/MOI_wrapper/indicator_constraints.jl @@ -10,8 +10,10 @@ function MOI.add_constraint(o::Optimizer, func::MOI.VectorAffineFunction{T}, set y = VarRef(first_index_terms[1].variable_index.value) x = [VarRef(vi.variable_index.value) for vi in scalar_index_terms] a = [vi.coefficient for vi in scalar_index_terms] + b = func.constants[2] + # a^T x + b <= c ===> a^T <= c - b - cr = add_indicator_constraint(o.mscip, y, x, a, MOI.constant(set.set)) + cr = add_indicator_constraint(o.mscip, y, x, a, MOI.constant(set.set) - b) ci = CI{MOI.VectorAffineFunction{T}, MOI.IndicatorSet{MOI.ACTIVATE_ON_ONE, LT}}(cr.val) register!(o, ci) register!(o, cons(o, ci), cr) diff --git a/test/MOI_wrapper_direct.jl b/test/MOI_wrapper_direct.jl index 72c34d68..e1065dd4 100644 --- a/test/MOI_wrapper_direct.jl +++ b/test/MOI_wrapper_direct.jl @@ -50,6 +50,85 @@ end MOIT.ncqcp2test(OPTIMIZER, CONFIG) end +function indicator4_test(model::MOI.ModelLike, config) + atol = config.atol + rtol = config.rtol + # equivalent to indicator1_test with left-hand-side partially in LHS constant + # linear problem with indicator constraint and + # max 2x1 + 3x2 + # s.t. x1 + x2 <= 10 + # z1 ==> x2 - 1 <= 7 + # z2 ==> x2 + x1/5 + 1 <= 10 + # z1 + z2 >= 1 + + + MOI.empty!(model) + @test MOI.is_empty(model) + + @test MOI.supports(model, MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}()) + @test MOI.supports(model, MOI.ObjectiveSense()) + @test MOI.supports_constraint(model, MOI.SingleVariable, MOI.ZeroOne) + @test MOI.supports_constraint(model, MOI.SingleVariable, MOI.Interval{Float64}) + @test MOI.supports_constraint(model, MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}) + @test MOI.supports_constraint(model, MOI.VectorAffineFunction{Float64}, MOI.IndicatorSet{MOI.ACTIVATE_ON_ONE, MOI.LessThan{Float64}}) + x1 = MOI.add_variable(model) + x2 = MOI.add_variable(model) + z1 = MOI.add_variable(model) + z2 = MOI.add_variable(model) + MOI.add_constraint(model, z1, MOI.ZeroOne()) + MOI.add_constraint(model, z2, MOI.ZeroOne()) + f1 = MOI.VectorAffineFunction( + [MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, z1)), + MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(1.0, x2)), + ], + [0.0, -1.0] + ) + iset1 = MOI.IndicatorSet{MOI.ACTIVATE_ON_ONE}(MOI.LessThan(7.0)) + MOI.add_constraint(model, f1, iset1) + + f2 = MOI.VectorAffineFunction( + [MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, z2)), + MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(0.2, x1)), + MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(1.0, x2)), + ], + [0.0, 1.0], + ) + iset2 = MOI.IndicatorSet{MOI.ACTIVATE_ON_ONE}(MOI.LessThan(10.0)) + + MOI.add_constraint(model, f2, iset2) + + # Additional regular constraint. + MOI.add_constraint(model, + MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x1), MOI.ScalarAffineTerm(1.0, x2)], 0.0), + MOI.LessThan(10.0), + ) + + # Disjunction z1 ⋁ z2 + MOI.add_constraint(model, + MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, z1), MOI.ScalarAffineTerm(1.0, z2)], 0.0), + MOI.GreaterThan(1.0), + ) + + MOI.set(model, MOI.ObjectiveFunction{MOI.ScalarAffineFunction{Float64}}(), + MOI.ScalarAffineFunction(MOI.ScalarAffineTerm.([2.0, 3.0], [x1, x2]), 0.0) + ) + MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE) + + if config.solve + @test MOI.get(model, MOI.TerminationStatus()) == MOI.OPTIMIZE_NOT_CALLED + + MOI.optimize!(model) + + @test MOI.get(model, MOI.TerminationStatus()) == MOI.OPTIMAL + @test MOI.get(model, MOI.PrimalStatus()) == MOI.FEASIBLE_POINT + @test MOI.get(model, MOI.ObjectiveValue()) ≈ 28.75 atol=atol rtol=rtol + @test MOI.get(model, MOI.VariablePrimal(), x1) ≈ 1.25 atol=atol rtol=rtol + @test MOI.get(model, MOI.VariablePrimal(), x2) ≈ 8.75 atol=atol rtol=rtol + @test MOI.get(model, MOI.VariablePrimal(), z1) ≈ 0.0 atol=atol rtol=rtol + @test MOI.get(model, MOI.VariablePrimal(), z2) ≈ 1.0 atol=atol rtol=rtol + end +end + @testset "MOI Integer Linear" begin # MOIT.intlineartest(OPTIMIZER, CONFIG) @@ -60,5 +139,6 @@ end MOIT.int3test(OPTIMIZER, CONFIG) MOIT.indicator1_test(OPTIMIZER, CONFIG) MOIT.indicator2_test(OPTIMIZER, CONFIG) + indicator4_test(OPTIMIZER, CONFIG) # MOIT.indicator3_test(OPTIMIZER, CONFIG) # no support for ACTIVATE_ON_ZERO end From f28d6911f9eafc80d6dcc5bc2453f1ad6e1ec7fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20Besan=C3=A7on?= Date: Fri, 25 Oct 2019 12:16:01 +0200 Subject: [PATCH 3/3] indication to replace --- test/MOI_wrapper_direct.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/MOI_wrapper_direct.jl b/test/MOI_wrapper_direct.jl index e1065dd4..96702d36 100644 --- a/test/MOI_wrapper_direct.jl +++ b/test/MOI_wrapper_direct.jl @@ -139,6 +139,7 @@ end MOIT.int3test(OPTIMIZER, CONFIG) MOIT.indicator1_test(OPTIMIZER, CONFIG) MOIT.indicator2_test(OPTIMIZER, CONFIG) + # replace with MOIT when MathOptInterface.jl#929 merged indicator4_test(OPTIMIZER, CONFIG) # MOIT.indicator3_test(OPTIMIZER, CONFIG) # no support for ACTIVATE_ON_ZERO end