Skip to content

Commit

Permalink
Add support for vector-valued MOI.set when setting new variable bounds
Browse files Browse the repository at this point in the history
  • Loading branch information
odow committed Jan 23, 2024
1 parent a17bcfd commit 5842d04
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 0 deletions.
35 changes: 35 additions & 0 deletions src/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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

Check warning on line 1403 in src/MOI_wrapper.jl

View check run for this annotation

Codecov / codecov/patch

src/MOI_wrapper.jl#L1402-L1403

Added lines #L1402 - L1403 were not covered by tests
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,
Expand Down
85 changes: 85 additions & 0 deletions test/MOI_wrapper.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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()

0 comments on commit 5842d04

Please sign in to comment.