diff --git a/src/Bridges/Constraint/scalarize.jl b/src/Bridges/Constraint/scalarize.jl index 98dc30fa82..a46deb6320 100644 --- a/src/Bridges/Constraint/scalarize.jl +++ b/src/Bridges/Constraint/scalarize.jl @@ -122,7 +122,7 @@ function MOI.modify(model::MOI.ModelLike, bridge::ScalarizeBridge, nothing end function MOI.set(model::MOI.ModelLike, ::MOI.ConstraintFunction, - bridge::ScalarizeBridge{T}, func) where T + bridge::ScalarizeBridge{T,F,S}, func) where {T,F,S} old_constants = bridge.constants bridge.constants = MOI.constant(func, T) new_func = MOIU.scalarize(func, true) @@ -130,7 +130,7 @@ function MOI.set(model::MOI.ModelLike, ::MOI.ConstraintFunction, new_func) for i in eachindex(bridge.constants) if bridge.constants[i] != old_constants[i] - MOI.set(model, MOI.ConstraintSet(), bridge.scalar_constraints, + MOI.set(model, MOI.ConstraintSet(), bridge.scalar_constraints[i], S(-bridge.constants[i])) end end diff --git a/src/Test/UnitTests/modifications.jl b/src/Test/UnitTests/modifications.jl index 61da17d786..32853fbed6 100644 --- a/src/Test/UnitTests/modifications.jl +++ b/src/Test/UnitTests/modifications.jl @@ -196,6 +196,51 @@ function solve_func_scalaraffine_lessthan(model::MOI.ModelLike, config::TestConf end modificationtests["solve_func_scalaraffine_lessthan"] = solve_func_scalaraffine_lessthan +""" + solve_func_vectoraffine_nonneg(model::MOI.ModelLike, config::TestConfig) + +Test setting the function in a VectorAffineFunction-in-Nonnegatives +constraint. If `config.solve=true` confirm that it solves correctly, and if +`config.duals=true`, check that the duals are computed correctly. +""" +function solve_func_vectoraffine_nonneg(model::MOI.ModelLike, config::TestConfig) + MOI.empty!(model) + MOIU.loadfromstring!(model,""" + variables: x, y + minobjective: 1.0x + 2.0y + c: [1.0x, 2.0y] in Nonnegatives(2) + """) + x = MOI.get(model, MOI.VariableIndex, "x") + y = MOI.get(model, MOI.VariableIndex, "y") + c = MOI.get(model, MOI.ConstraintIndex, "c") + test_model_solution(model, config; + objective_value = 0.0, + variable_primal = [(x, 0.0), (y, 0.0)], + constraint_primal = [(c, [0.0, 0.0])] + ) + MOI.set(model, MOI.ConstraintFunction(), c, + MOI.VectorAffineFunction([ + MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, x)), + MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(2.0, y)) + ], + [-1.0, -1.5] + ) + ) + foo = MOI.get(model, MOI.ConstraintFunction(), c) + @test foo ≈ MOI.VectorAffineFunction([ + MOI.VectorAffineTerm(1, MOI.ScalarAffineTerm(1.0, x)), + MOI.VectorAffineTerm(2, MOI.ScalarAffineTerm(2.0, y)) + ], + [-1.0, -1.5] + ) + test_model_solution(model, config; + objective_value = 2.5, + variable_primal = [(x, 1.0), (y, 0.75)], + constraint_primal = [(c, [0.0, 0.0])] + ) +end +modificationtests["solve_func_vectoraffine_nonneg"] = solve_func_vectoraffine_nonneg + """ solve_const_vectoraffine_nonpos(model::MOI.ModelLike, config::TestConfig) diff --git a/test/Bridges/Constraint/scalarize.jl b/test/Bridges/Constraint/scalarize.jl index a0336e451f..8c91cf0e90 100644 --- a/test/Bridges/Constraint/scalarize.jl +++ b/test/Bridges/Constraint/scalarize.jl @@ -81,6 +81,12 @@ config = MOIT.TestConfig() ((MOI.ScalarAffineFunction{Float64}, MOI.EqualTo{Float64}, 0), (MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}, 0))) + # Test setting VectorAffineFunction with nonzero constants + MOIU.set_mock_optimize!(mock, + (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0.0, 0.0]), + (mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1.0, 0.75])) + MOIT.solve_func_vectoraffine_nonneg(bridged_mock, config) + # VectorOfVariables-in-Nonnegatives # VectorOfVariables-in-Nonpositives # VectorOfVariables-in-Zeros