diff --git a/src/Bridges/Objective/slack.jl b/src/Bridges/Objective/slack.jl index a395c40b29..308a0e6db5 100644 --- a/src/Bridges/Objective/slack.jl +++ b/src/Bridges/Objective/slack.jl @@ -131,11 +131,16 @@ function MOI.get( return obj_slack_constant + slack - constant end +_constant_term(set::MOI.LessThan) = set.upper +_constant_term(set::MOI.GreaterThan) = set.lower + function MOI.get( model::MOI.ModelLike, ::MOI.ObjectiveFunction{G}, bridge::SlackBridge{T,F,G}, ) where {T,F,G<:MOI.AbstractScalarFunction} func = MOI.get(model, MOI.ConstraintFunction(), bridge.constraint) - return MOIU.convert_approx(G, MOIU.remove_variable(func, bridge.slack)) + set = MOI.get(model, MOI.ConstraintSet(), bridge.constraint) + f = MOIU.operate(-, T, func, _constant_term(set)) + return MOIU.convert_approx(G, MOIU.remove_variable(f, bridge.slack)) end diff --git a/test/Bridges/Objective/functionize.jl b/test/Bridges/Objective/functionize.jl index 1f1f90ecdd..56c105bead 100644 --- a/test/Bridges/Objective/functionize.jl +++ b/test/Bridges/Objective/functionize.jl @@ -1,25 +1,35 @@ +module TestObjectiveFunctionize + using Test using MathOptInterface const MOI = MathOptInterface -const MOIT = MathOptInterface.DeprecatedTest -const MOIU = MathOptInterface.Utilities -const MOIB = MathOptInterface.Bridges - -include("../utilities.jl") -mock = MOIU.MockOptimizer(MOIU.Model{Float64}()) -config = MOIT.Config() +function runtests() + for name in names(@__MODULE__; all = true) + if startswith("$(name)", "test_") + @testset "$(name)" begin + getfield(@__MODULE__, name)() + end + end + end + return +end -bridged_mock = MOIB.Objective.Functionize{Float64}(mock) +include("../utilities.jl") -@testset "solve_singlevariable_obj" begin - MOIU.set_mock_optimize!( +function test_solve_singlevariable_obj() + mock = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + bridged_mock = MOI.Bridges.Objective.Functionize{Float64}(mock) + MOI.Utilities.set_mock_optimize!( mock, - (mock::MOIU.MockOptimizer) -> - MOIU.mock_optimize!(mock, [1.0], MOI.FEASIBLE_POINT), + (mock::MOI.Utilities.MockOptimizer) -> + MOI.Utilities.mock_optimize!(mock, [1.0], MOI.FEASIBLE_POINT), + ) + MOI.Test.test_objective_ObjectiveFunction_SingleVariable( + bridged_mock, + MOI.Test.Config(), ) - MOIT.solve_singlevariable_obj(bridged_mock, config) @test MOI.get(mock, MOI.ObjectiveFunctionType()) == MOI.ScalarAffineFunction{Float64} @test MOI.get(bridged_mock, MOI.ObjectiveFunctionType()) == @@ -38,14 +48,15 @@ bridged_mock = MOIB.Objective.Functionize{Float64}(mock) @test MOI.get(mock, MOI.ObjectiveSense()) == MOI.MAX_SENSE @test MOI.get(bridged_mock, MOI.ObjectiveSense()) == MOI.MAX_SENSE _test_delete_objective(bridged_mock, 1, tuple()) + return end -# Tests that the `ObjectiveValue` attribute passed has the correct -# `result_index`. -@testset "solve_result_index" begin - MOIU.set_mock_optimize!( +function test_solve_result_index() + mock = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + bridged_mock = MOI.Bridges.Objective.Functionize{Float64}(mock) + MOI.Utilities.set_mock_optimize!( mock, - (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!( + (mock::MOI.Utilities.MockOptimizer) -> MOI.Utilities.mock_optimize!( mock, MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0]), @@ -53,5 +64,9 @@ end (MOI.SingleVariable, MOI.GreaterThan{Float64}) => [1.0], ), ) - MOIT.solve_result_index(bridged_mock, config) + return MOI.Test.test_solve_result_index(bridged_mock, MOI.Test.Config()) end + +end # module + +TestObjectiveFunctionize.runtests() diff --git a/test/Bridges/Objective/map.jl b/test/Bridges/Objective/map.jl index f9194dd3a7..f2b0c8cd61 100644 --- a/test/Bridges/Objective/map.jl +++ b/test/Bridges/Objective/map.jl @@ -1,42 +1,65 @@ +module TestObjectiveMap + using Test + using MathOptInterface const MOI = MathOptInterface -const MOIB = MOI.Bridges -struct ObjectiveDummyBridge <: MOIB.Objective.AbstractBridge +function runtests() + for name in names(@__MODULE__; all = true) + if startswith("$(name)", "test_") + @testset "$(name)" begin + getfield(@__MODULE__, name)() + end + end + end + return +end + +struct ObjectiveDummyBridge <: MOI.Bridges.Objective.AbstractBridge id::Int end -function test_empty(map) +function _test_empty(map) @test isempty(map) @test length(map) == 0 @test isempty(values(map)) @test iterate(map) === nothing - @test MOIB.Objective.function_type(map) === nothing + @test MOI.Bridges.Objective.function_type(map) === nothing end -map = MOIB.Objective.Map() -test_empty(map) -@test sprint(MOIB.print_num_bridges, map) == "\nwith 0 objective bridges" - -x = MOI.VariableIndex(1) -fx = MOI.SingleVariable(x) -MOIB.Objective.add_key_for_bridge(map, ObjectiveDummyBridge(1), fx) -@test MOIB.Objective.root_bridge(map) == ObjectiveDummyBridge(1) -@test sprint(MOIB.print_num_bridges, map) == "\nwith 1 objective bridge" -func = 1.0fx -MOIB.Objective.add_key_for_bridge(map, ObjectiveDummyBridge(2), func) -@test MOIB.Objective.root_bridge(map) == ObjectiveDummyBridge(2) -@test sprint(MOIB.print_num_bridges, map) == "\nwith 2 objective bridges" - -empty!(map) -test_empty(map) -@test sprint(MOIB.print_num_bridges, map) == "\nwith 0 objective bridges" - -@testset "EmptyMap" begin - map = MOIB.Objective.EmptyMap() - test_empty(map) +function test_Map() + map = MOI.Bridges.Objective.Map() + _test_empty(map) + @test sprint(MOI.Bridges.print_num_bridges, map) == + "\nwith 0 objective bridges" + x = MOI.VariableIndex(1) + fx = MOI.SingleVariable(x) + MOI.Bridges.Objective.add_key_for_bridge(map, ObjectiveDummyBridge(1), fx) + @test MOI.Bridges.Objective.root_bridge(map) == ObjectiveDummyBridge(1) + @test sprint(MOI.Bridges.print_num_bridges, map) == + "\nwith 1 objective bridge" + func = 1.0fx + MOI.Bridges.Objective.add_key_for_bridge(map, ObjectiveDummyBridge(2), func) + @test MOI.Bridges.Objective.root_bridge(map) == ObjectiveDummyBridge(2) + @test sprint(MOI.Bridges.print_num_bridges, map) == + "\nwith 2 objective bridges" empty!(map) - test_empty(map) - @test sprint(MOIB.print_num_bridges, map) == "" + _test_empty(map) + @test sprint(MOI.Bridges.print_num_bridges, map) == + "\nwith 0 objective bridges" + return end + +function test_EmptyMap() + map = MOI.Bridges.Objective.EmptyMap() + _test_empty(map) + empty!(map) + _test_empty(map) + @test sprint(MOI.Bridges.print_num_bridges, map) == "" + return +end + +end # module + +TestObjectiveMap.runtests() diff --git a/test/Bridges/Objective/slack.jl b/test/Bridges/Objective/slack.jl index c506755789..c4bdb0c986 100644 --- a/test/Bridges/Objective/slack.jl +++ b/test/Bridges/Objective/slack.jl @@ -1,54 +1,240 @@ +module TestObjectiveSlack + using Test using MathOptInterface const MOI = MathOptInterface -const MOIT = MathOptInterface.DeprecatedTest -const MOIU = MathOptInterface.Utilities -const MOIB = MathOptInterface.Bridges + +function runtests() + for name in names(@__MODULE__; all = true) + if startswith("$(name)", "test_") + @testset "$(name)" begin + getfield(@__MODULE__, name)() + end + end + end + return +end include("../utilities.jl") -mock = MOIU.MockOptimizer(MOIU.Model{Float64}()) -config = MOIT.Config() +function test_SlackBridge_ObjectiveSense_error() + inner = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + model = MOI.Bridges.Objective.Slack{Float64}(inner) + x = MOI.add_variable(model) + f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.1, x)], 1.2) + @test_throws( + ErrorException( + "Set `MOI.ObjectiveSense` before `MOI.ObjectiveFunction` when" * + " using `MOI.Bridges.Objective.SlackBridge`.", + ), + MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f), + ) + return +end + +function test_SlackBridge_ObjectiveSense_modify() + inner = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + model = MOI.Bridges.Objective.Slack{Float64}(inner) + x = MOI.add_variable(model) + f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.1, x)], -1.2) + MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE) + MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f) + @test_throws( + ArgumentError, + MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE), + ) + MOI.set(model, MOI.ObjectiveSense(), MOI.FEASIBILITY_SENSE) + MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE) + MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f) + @test MOI.get(model, MOI.ObjectiveFunction{typeof(f)}()) ≈ f + return +end -bridged_mock = MOIB.Objective.Slack{Float64}(mock) +function test_SlackBridge_ObjectiveFunction_modify() + inner = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + model = MOI.Bridges.Objective.Slack{Float64}(inner) + x = MOI.add_variable(model) + f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.1, x)], -1.2) + MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE) + MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f) + @test MOI.get(model, MOI.ObjectiveFunction{typeof(f)}()) ≈ f + g = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(-1.1, x)], 1.2) + MOI.set(model, MOI.ObjectiveFunction{typeof(g)}(), g) + @test MOI.get(model, MOI.ObjectiveFunction{typeof(g)}()) ≈ g + return +end + +function test_SlackBridge_get_ObjectiveFunction_MIN() + inner = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + model = MOI.Bridges.Objective.Slack{Float64}(inner) + x = MOI.add_variable(model) + f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.1, x)], -1.2) + MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE) + MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f) + @test MOI.get(model, MOI.ObjectiveFunction{typeof(f)}()) ≈ f + return +end + +function test_SlackBridge_get_ObjectiveFunction_MAX() + inner = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + model = MOI.Bridges.Objective.Slack{Float64}(inner) + x = MOI.add_variable(model) + f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.1, x)], -1.2) + MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE) + MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f) + @test MOI.get(model, MOI.ObjectiveFunction{typeof(f)}()) ≈ f + return +end + +function test_SlackBridge_get_ObjectiveSense() + inner = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + model = MOI.Bridges.Objective.Slack{Float64}(inner) + MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE) + @test MOI.get(model, MOI.ObjectiveSense()) == MOI.MIN_SENSE + MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE) + @test MOI.get(model, MOI.ObjectiveSense()) == MOI.MAX_SENSE + return +end + +function test_SlackBridge_NumberOfVariables() + inner = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + model = MOI.Bridges.Objective.Slack{Float64}(inner) + x = MOI.add_variable(model) + f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.1, x)], 1.2) + MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE) + MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f) + @test MOI.get(model, MOI.NumberOfVariables()) == 1 + @test MOI.get(inner, MOI.NumberOfVariables()) == 2 + MOI.set(model, MOI.ObjectiveSense(), MOI.FEASIBILITY_SENSE) + @test MOI.get(model, MOI.NumberOfVariables()) == 1 + @test MOI.get(inner, MOI.NumberOfVariables()) == 1 + return +end -@testset "Set objective before sense" begin - err = ErrorException( - "Set `MOI.ObjectiveSense` before `MOI.ObjectiveFunction` when" * - " using `MOI.Bridges.Objective.SlackBridge`.", +function test_SlackBridge_ListOfModelAttributesSet() + inner = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + model = MOI.Bridges.Objective.Slack{Float64}(inner) + x = MOI.add_variable(model) + f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.1, x)], 1.2) + MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE) + MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f) + attr = MOI.get(model, MOI.ListOfModelAttributesSet()) + @test length(attr) == 2 + @test MOI.ObjectiveSense() in attr + @test MOI.ObjectiveFunction{typeof(f)}() in attr + attr = MOI.get(inner, MOI.ListOfModelAttributesSet()) + @test length(attr) == 2 + @test MOI.ObjectiveSense() in attr + @test MOI.ObjectiveFunction{MOI.SingleVariable}() in attr + return +end + +function test_SlackBridge_ListOfVariableIndices() + inner = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + model = MOI.Bridges.Objective.Slack{Float64}(inner) + x = MOI.add_variable(model) + f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.1, x)], 1.2) + MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE) + MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f) + @test MOI.get(model, MOI.ListOfVariableIndices()) == [x] + @test length(MOI.get(inner, MOI.ListOfVariableIndices())) == 2 + MOI.set(model, MOI.ObjectiveSense(), MOI.FEASIBILITY_SENSE) + @test MOI.get(model, MOI.ListOfVariableIndices()) == [x] + @test MOI.get(inner, MOI.ListOfVariableIndices()) == [x] + return +end + +function test_SlackBridge_ListOfConstraintTypesPresent() + inner = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + model = MOI.Bridges.Objective.Slack{Float64}(inner) + x = MOI.add_variable(model) + f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.1, x)], 1.2) + MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE) + MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f) + @test MOI.get(model, MOI.ListOfConstraintTypesPresent()) == [] + @test MOI.get(inner, MOI.ListOfConstraintTypesPresent()) == + [(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64})] + MOI.set(model, MOI.ObjectiveSense(), MOI.FEASIBILITY_SENSE) + @test MOI.get(model, MOI.ListOfConstraintTypesPresent()) == [] + @test MOI.get(inner, MOI.ListOfConstraintTypesPresent()) == [] + return +end + +function test_SlackBridge_ListOfConstraintIndices() + inner = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + model = MOI.Bridges.Objective.Slack{Float64}(inner) + x = MOI.add_variable(model) + f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.1, x)], 1.2) + MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE) + MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f) + attr = MOI.ListOfConstraintIndices{ + MOI.ScalarAffineFunction{Float64}, + MOI.GreaterThan{Float64}, + }() + @test MOI.get(model, attr) == [] + @test length(MOI.get(inner, attr)) == 1 + attr = MOI.ListOfConstraintIndices{ + MOI.ScalarAffineFunction{Float64}, + MOI.LessThan{Float64}, + }() + @test MOI.get(model, attr) == [] + @test length(MOI.get(inner, attr)) == 0 + MOI.set(model, MOI.ObjectiveSense(), MOI.FEASIBILITY_SENSE) + @test MOI.get(model, attr) == [] + @test length(MOI.get(inner, attr)) == 0 + return +end + +function test_SlackBridge_ObjectiveFunctionValue() + inner = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + model = MOI.Bridges.Objective.Slack{Float64}(inner) + x = MOI.add_variable(model) + MOI.add_constraint(model, MOI.SingleVariable(x), MOI.GreaterThan(2.0)) + f = MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.1, x)], -1.2) + MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE) + MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f) + MOI.Utilities.set_mock_optimize!( + inner, + mock -> MOI.Utilities.mock_optimize!(mock, [2.0, 1.0]), ) - F = MOI.ScalarAffineFunction{Float64} - @test_throws err MOI.set(bridged_mock, MOI.ObjectiveFunction{F}(), zero(F)) + MOI.optimize!(model) + @test MOI.get(model, MOI.ObjectiveValue()) ≈ 1.0 + return end -@testset "solve_qp_edge_cases" begin - MOIU.set_mock_optimize!( +function test_original() + mock = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + bridged_mock = MOI.Bridges.Objective.Slack{Float64}(mock) + MOI.Utilities.set_mock_optimize!( mock, - (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!( + (mock::MOI.Utilities.MockOptimizer) -> MOI.Utilities.mock_optimize!( mock, MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0, 2.0, 5.0]), ), - (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!( + (mock::MOI.Utilities.MockOptimizer) -> MOI.Utilities.mock_optimize!( mock, MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0, 2.0, 7.0]), ), - (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!( + (mock::MOI.Utilities.MockOptimizer) -> MOI.Utilities.mock_optimize!( mock, MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0, 2.0, 2.0]), ), - (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!( + (mock::MOI.Utilities.MockOptimizer) -> MOI.Utilities.mock_optimize!( mock, MOI.OPTIMAL, (MOI.FEASIBLE_POINT, [1.0, 2.0, 7.0]), ), ) - MOIT.solve_qp_edge_cases(bridged_mock, config) + MOI.Test.test_objective_qp_ObjectiveFunction_edge_cases( + bridged_mock, + MOI.Test.Config(), + ) - @test MOIB.is_objective_bridged(bridged_mock) + @test MOI.Bridges.is_objective_bridged(bridged_mock) @test MOI.get(bridged_mock, MOI.ObjectiveFunctionType()) == MOI.ScalarQuadraticFunction{Float64} @test MOI.get(bridged_mock, MOI.ListOfModelAttributesSet()) == [ @@ -59,62 +245,56 @@ end var_names = ["x", "y"] xy = MOI.get(bridged_mock, MOI.ListOfVariableIndices()) MOI.set(bridged_mock, MOI.VariableName(), xy, var_names) - @testset "Test mock model" begin - abs = MOI.get(mock, MOI.ListOfVariableIndices()) - @test length(abs) == 3 - MOI.set(mock, MOI.VariableName(), abs[3], "s") - cquad = MOI.get( - mock, - MOI.ListOfConstraintIndices{ - MOI.ScalarQuadraticFunction{Float64}, - MOI.LessThan{Float64}, - }(), - ) - MOI.set(bridged_mock, MOI.ConstraintName(), cquad[1], "quad") - - s = """ - variables: x, y, s - x >= 1.0 - y >= 2.0 - quad: 1.0 * x * x + 1.0 * x * y + 1.0 * y * y + -1.0 * s <= 0.0 - minobjective: s - """ - model = MOIU.Model{Float64}() - MOIU.loadfromstring!(model, s) - MOIU.test_models_equal( - mock, - model, - [var_names; "s"], - ["quad"], - [ - ("x", MOI.GreaterThan{Float64}(1.0)), - ("y", MOI.GreaterThan{Float64}(2.0)), - ], - ) - end + abs = MOI.get(mock, MOI.ListOfVariableIndices()) + @test length(abs) == 3 + MOI.set(mock, MOI.VariableName(), abs[3], "s") + cquad = MOI.get( + mock, + MOI.ListOfConstraintIndices{ + MOI.ScalarQuadraticFunction{Float64}, + MOI.LessThan{Float64}, + }(), + ) + MOI.set(bridged_mock, MOI.ConstraintName(), cquad[1], "quad") + s = """ + variables: x, y, s + x >= 1.0 + y >= 2.0 + quad: 1.0 * x * x + 1.0 * x * y + 1.0 * y * y + -1.0 * s <= 0.0 + minobjective: s + """ + model = MOI.Utilities.Model{Float64}() + MOI.Utilities.loadfromstring!(model, s) + MOI.Utilities.test_models_equal( + mock, + model, + [var_names; "s"], + ["quad"], + [ + ("x", MOI.GreaterThan{Float64}(1.0)), + ("y", MOI.GreaterThan{Float64}(2.0)), + ], + ) bridged_var_names = ["x", "y"] - @testset "Test bridged model" begin - s = """ - variables: x, y - x >= 1.0 - y >= 2.0 - minobjective: 1.0 * x * x + 1.0 * x * y + 1.0 * y * y - """ - model = MOIU.Model{Float64}() - MOIU.loadfromstring!(model, s) - MOIU.test_models_equal( - bridged_mock, - model, - var_names, - String[], - [ - ("x", MOI.GreaterThan{Float64}(1.0)), - ("y", MOI.GreaterThan{Float64}(2.0)), - ], - ) - end - + s = """ + variables: x, y + x >= 1.0 + y >= 2.0 + minobjective: 1.0 * x * x + 1.0 * x * y + 1.0 * y * y + """ + model = MOI.Utilities.Model{Float64}() + MOI.Utilities.loadfromstring!(model, s) + MOI.Utilities.test_models_equal( + bridged_mock, + model, + var_names, + String[], + [ + ("x", MOI.GreaterThan{Float64}(1.0)), + ("y", MOI.GreaterThan{Float64}(2.0)), + ], + ) err = ArgumentError( "Objective bridge of type `$(MathOptInterface.Bridges.Objective.SlackBridge{Float64,MathOptInterface.ScalarQuadraticFunction{Float64},MathOptInterface.ScalarQuadraticFunction{Float64}})`" * " does not support modifying the objective sense. As a workaround, set" * @@ -127,7 +307,7 @@ end MOI.ObjectiveFunction{MOI.ScalarQuadraticFunction{Float64}}(), ) MOI.set(bridged_mock, MOI.ObjectiveSense(), MOI.FEASIBILITY_SENSE) - @test !MOIB.is_objective_bridged(bridged_mock) + @test !MOI.Bridges.is_objective_bridged(bridged_mock) @test MOI.get(bridged_mock, MOI.ObjectiveSense()) == MOI.FEASIBILITY_SENSE @test MOI.get(bridged_mock, MOI.ListOfModelAttributesSet()) == [MOI.ObjectiveSense()] @@ -137,62 +317,55 @@ end MOI.ObjectiveFunction{MOI.ScalarQuadraticFunction{Float64}}(), obj, ) + abs = MOI.get(mock, MOI.ListOfVariableIndices()) + @test length(abs) == 3 + MOI.set(mock, MOI.VariableName(), abs[3], "s") + cquad = MOI.get( + mock, + MOI.ListOfConstraintIndices{ + MOI.ScalarQuadraticFunction{Float64}, + MOI.GreaterThan{Float64}, + }(), + ) + MOI.set(bridged_mock, MOI.ConstraintName(), cquad[1], "quad") - @testset "Test mock model" begin - abs = MOI.get(mock, MOI.ListOfVariableIndices()) - @test length(abs) == 3 - MOI.set(mock, MOI.VariableName(), abs[3], "s") - cquad = MOI.get( - mock, - MOI.ListOfConstraintIndices{ - MOI.ScalarQuadraticFunction{Float64}, - MOI.GreaterThan{Float64}, - }(), - ) - MOI.set(bridged_mock, MOI.ConstraintName(), cquad[1], "quad") - - s = """ - variables: x, y, s - x >= 1.0 - y >= 2.0 - quad: 1.0 * x * x + 1.0 * x * y + 1.0 * y * y + -1.0 * s >= 0.0 - maxobjective: s - """ - model = MOIU.Model{Float64}() - MOIU.loadfromstring!(model, s) - MOIU.test_models_equal( - mock, - model, - [var_names; "s"], - ["quad"], - [ - ("x", MOI.GreaterThan{Float64}(1.0)), - ("y", MOI.GreaterThan{Float64}(2.0)), - ], - ) - end - - @testset "Test bridged model" begin - s = """ - variables: x, y - x >= 1.0 - y >= 2.0 - maxobjective: 1.0 * x * x + 1.0 * x * y + 1.0 * y * y - """ - model = MOIU.Model{Float64}() - MOIU.loadfromstring!(model, s) - MOIU.test_models_equal( - bridged_mock, - model, - var_names, - String[], - [ - ("x", MOI.GreaterThan{Float64}(1.0)), - ("y", MOI.GreaterThan{Float64}(2.0)), - ], - ) - end - + s = """ + variables: x, y, s + x >= 1.0 + y >= 2.0 + quad: 1.0 * x * x + 1.0 * x * y + 1.0 * y * y + -1.0 * s >= 0.0 + maxobjective: s + """ + model = MOI.Utilities.Model{Float64}() + MOI.Utilities.loadfromstring!(model, s) + MOI.Utilities.test_models_equal( + mock, + model, + [var_names; "s"], + ["quad"], + [ + ("x", MOI.GreaterThan{Float64}(1.0)), + ("y", MOI.GreaterThan{Float64}(2.0)), + ], + ) + s = """ + variables: x, y + x >= 1.0 + y >= 2.0 + maxobjective: 1.0 * x * x + 1.0 * x * y + 1.0 * y * y + """ + model = MOI.Utilities.Model{Float64}() + MOI.Utilities.loadfromstring!(model, s) + MOI.Utilities.test_models_equal( + bridged_mock, + model, + var_names, + String[], + [ + ("x", MOI.GreaterThan{Float64}(1.0)), + ("y", MOI.GreaterThan{Float64}(2.0)), + ], + ) _test_delete_objective( bridged_mock, 2, @@ -201,54 +374,73 @@ end (MOI.ScalarQuadraticFunction{Float64}, MOI.LessThan{Float64}, 0), ), ) + return end -@testset "QP" begin - @testset "QP1" begin - MOIU.set_mock_optimize!( +function test_quadratic_integration() + mock = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + bridged_mock = MOI.Bridges.Objective.Slack{Float64}(mock) + MOI.Utilities.set_mock_optimize!( + mock, + (mock::MOI.Utilities.MockOptimizer) -> MOI.Utilities.mock_optimize!( mock, - (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!( - mock, - [4 / 7, 3 / 7, 6 / 7, 13 / 7], - (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [5 / 7, 6 / 7], - ), - ) - MOIT.qp1test(bridged_mock, config) - end - @testset "QP2" begin - MOIU.set_mock_optimize!( + [4 / 7, 3 / 7, 6 / 7, 13 / 7], + (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => + [5 / 7, 6 / 7], + ), + ) + MOI.Test.test_quadratic_integration(bridged_mock, MOI.Test.Config()) + return +end + +function test_quadratic_duplicate_terms() + mock = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + bridged_mock = MOI.Bridges.Objective.Slack{Float64}(mock) + MOI.Utilities.set_mock_optimize!( + mock, + (mock::MOI.Utilities.MockOptimizer) -> MOI.Utilities.mock_optimize!( mock, - (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!( - mock, - [4 / 7, 3 / 7, 6 / 7, 13 / 7], - (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [5 / 7, 6 / 7], - ), - (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!( - mock, - [4 / 7, 3 / 7, 6 / 7, -2 * 13 / 7], - (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [10 / 7, 12 / 7], - ), - ) - MOIT.qp2test(bridged_mock, config) - end - @testset "QP3" begin - MOIU.set_mock_optimize!( + [4 / 7, 3 / 7, 6 / 7, 13 / 7], + (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => + [5 / 7, 6 / 7], + ), + (mock::MOI.Utilities.MockOptimizer) -> MOI.Utilities.mock_optimize!( mock, - (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!( - mock, - [1 / 4, 3 / 4, 2.875], - (MOI.ScalarAffineFunction{Float64}, MOI.EqualTo{Float64}) => - [11 / 4], - (MOI.ScalarQuadraticFunction{Float64}, MOI.LessThan{Float64}) => [-1.0], - ), - (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!( - mock, - [1.0, 0.0, 3.0], - (MOI.ScalarAffineFunction{Float64}, MOI.EqualTo{Float64}) => - [-2.0], - (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [1.0], - ), - ) - MOIT.qp3test(bridged_mock, config) - end + [4 / 7, 3 / 7, 6 / 7, -2 * 13 / 7], + (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => + [10 / 7, 12 / 7], + ), + ) + MOI.Test.test_quadratic_duplicate_terms(bridged_mock, MOI.Test.Config()) + return +end + +function test_quadratic_nonhomogeneous() + mock = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + bridged_mock = MOI.Bridges.Objective.Slack{Float64}(mock) + MOI.Utilities.set_mock_optimize!( + mock, + (mock::MOI.Utilities.MockOptimizer) -> MOI.Utilities.mock_optimize!( + mock, + [1 / 4, 3 / 4, 2.875], + (MOI.ScalarAffineFunction{Float64}, MOI.EqualTo{Float64}) => + [11 / 4], + (MOI.ScalarQuadraticFunction{Float64}, MOI.LessThan{Float64}) => + [-1.0], + ), + (mock::MOI.Utilities.MockOptimizer) -> MOI.Utilities.mock_optimize!( + mock, + [1.0, 0.0, 3.0], + (MOI.ScalarAffineFunction{Float64}, MOI.EqualTo{Float64}) => + [-2.0], + (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => + [1.0], + ), + ) + MOI.Test.test_quadratic_nonhomogeneous(bridged_mock, MOI.Test.Config()) + return end + +end # module + +TestObjectiveSlack.runtests()