diff --git a/src/MOI_wrapper.jl b/src/MOI_wrapper.jl index 06e16ba..9cd6287 100644 --- a/src/MOI_wrapper.jl +++ b/src/MOI_wrapper.jl @@ -1379,6 +1379,41 @@ function MOI.set( return end +function MOI.set( + model::Optimizer, + ::MOI.ConstraintSet, + c::Vector{MOI.ConstraintIndex{MOI.VariableIndex,S}}, + s::Vector{S}, +) where {S<:_SCALAR_SETS} + if length(c) != length(s) + msg = "number of constraints does not match number of sets" + throw(DimensionMismatch(msg)) + end + for ci in c + MOI.throw_if_not_valid(model, ci) + end + N = length(c) + columns, lower, upper = zeros(Cint, N), zeros(Cdouble, N), zeros(Cdouble, N) + for (i, (ci, si)) in enumerate(zip(c, s)) + info = _info(model, ci) + columns[i] = info.column + l, u = _bounds(si) + if S == MOI.LessThan{Float64} + info.upper = u + lower[i], upper[i] = info.lower, u + elseif S == MOI.GreaterThan{Float64} + info.lower = l + lower[i], upper[i] = l, info.upper + else + lower[i], upper[i] = l, u + info.lower, info.upper = l, u + end + end + ret = Highs_changeColsBoundsBySet(model, N, columns, lower, upper) + _check_ret(ret) + return +end + function MOI.supports( ::Optimizer, ::MOI.ConstraintName, diff --git a/test/MOI_wrapper.jl b/test/MOI_wrapper.jl index 650af7c..50084fa 100644 --- a/test/MOI_wrapper.jl +++ b/test/MOI_wrapper.jl @@ -476,6 +476,91 @@ function test_relax_integrality_after_solve() return end +function test_change_col_bounds_by_set_dimension_mismatch() + model = HiGHS.Optimizer() + MOI.set(model, MOI.Silent(), true) + x = MOI.add_variables(model, 3) + c = MOI.add_constraint.(model, x, MOI.GreaterThan.(1.0:3.0)) + @test_throws( + DimensionMismatch, + MOI.set(model, MOI.ConstraintSet(), c, MOI.GreaterThan.([4.0, 5.0])), + ) + return +end + +function test_change_col_bounds_by_set_invalid() + model = HiGHS.Optimizer() + MOI.set(model, MOI.Silent(), true) + x = MOI.add_variable(model) + c = MOI.add_constraint(model, x, MOI.GreaterThan(0.0)) + c_invalid = typeof(c)(-123456) + sets = MOI.GreaterThan.(1.0:2.0) + @test_throws( + MOI.InvalidIndex(c_invalid), + MOI.set(model, MOI.ConstraintSet(), [c, c_invalid], sets), + ) + return +end + +function test_change_col_bounds_by_set_greater_than() + model = HiGHS.Optimizer() + MOI.set(model, MOI.Silent(), true) + x = MOI.add_variables(model, 3) + c = MOI.add_constraint.(model, x, MOI.GreaterThan.(1.0:3.0)) + MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE) + f = 1.0 * x[1] + x[2] + x[3] + MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f) + MOI.optimize!(model) + @test ≈(MOI.get(model, MOI.ObjectiveValue()), 6; atol = 1e-6) + MOI.set( + model, + MOI.ConstraintSet(), + [c[1], c[3]], + MOI.GreaterThan.([4.0, 5.0]), + ) + MOI.optimize!(model) + @test ≈(MOI.get(model, MOI.ObjectiveValue()), 11; atol = 1e-6) + @test MOI.get(model, MOI.ConstraintSet(), c) == + MOI.GreaterThan.([4.0, 2.0, 5.0]) + return +end + +function test_change_col_bounds_by_set_less_than() + model = HiGHS.Optimizer() + MOI.set(model, MOI.Silent(), true) + x = MOI.add_variables(model, 3) + c = MOI.add_constraint.(model, x, MOI.LessThan.(1.0:3.0)) + MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE) + f = 1.0 * x[1] + x[2] + x[3] + MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f) + MOI.optimize!(model) + @test ≈(MOI.get(model, MOI.ObjectiveValue()), 6; atol = 1e-6) + MOI.set(model, MOI.ConstraintSet(), [c[1], c[3]], MOI.LessThan.([4.0, 5.0])) + MOI.optimize!(model) + @test ≈(MOI.get(model, MOI.ObjectiveValue()), 11; atol = 1e-6) + @test MOI.get(model, MOI.ConstraintSet(), c) == + MOI.LessThan.([4.0, 2.0, 5.0]) + return +end + +function test_change_col_bounds_by_set_less_than() + model = HiGHS.Optimizer() + MOI.set(model, MOI.Silent(), true) + x = MOI.add_variables(model, 3) + c = MOI.add_constraint.(model, x, MOI.EqualTo.(1.0:3.0)) + MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE) + f = 1.0 * x[1] + x[2] + x[3] + MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f) + MOI.optimize!(model) + @test ≈(MOI.get(model, MOI.ObjectiveValue()), 6; atol = 1e-6) + MOI.set(model, MOI.ConstraintSet(), [c[1], c[3]], MOI.EqualTo.([4.0, 5.0])) + MOI.optimize!(model) + @test ≈(MOI.get(model, MOI.ObjectiveValue()), 11; atol = 1e-6) + @test MOI.get(model, MOI.ConstraintSet(), c) == + MOI.EqualTo.([4.0, 2.0, 5.0]) + return +end + end TestMOIHighs.runtests()