Skip to content

Commit e26ff8b

Browse files
authored
Add support for vector-valued MOI.set when setting new ConstraintSet (#196)
1 parent dbbc82c commit e26ff8b

File tree

2 files changed

+230
-0
lines changed

2 files changed

+230
-0
lines changed

src/MOI_wrapper.jl

+60
Original file line numberDiff line numberDiff line change
@@ -1427,6 +1427,41 @@ function MOI.set(
14271427
return
14281428
end
14291429

1430+
function MOI.set(
1431+
model::Optimizer,
1432+
::MOI.ConstraintSet,
1433+
c::Vector{MOI.ConstraintIndex{MOI.VariableIndex,S}},
1434+
s::Vector{S},
1435+
) where {S<:_SCALAR_SETS}
1436+
if length(c) != length(s)
1437+
msg = "number of constraints does not match number of sets"
1438+
throw(DimensionMismatch(msg))
1439+
end
1440+
for ci in c
1441+
MOI.throw_if_not_valid(model, ci)
1442+
end
1443+
N = length(c)
1444+
columns, lower, upper = zeros(Cint, N), zeros(Cdouble, N), zeros(Cdouble, N)
1445+
for (i, (ci, si)) in enumerate(zip(c, s))
1446+
info = _info(model, ci)
1447+
columns[i] = info.column
1448+
l, u = _bounds(si)
1449+
if S == MOI.LessThan{Float64}
1450+
info.upper = u
1451+
lower[i], upper[i] = info.lower, u
1452+
elseif S == MOI.GreaterThan{Float64}
1453+
info.lower = l
1454+
lower[i], upper[i] = l, info.upper
1455+
else
1456+
lower[i], upper[i] = l, u
1457+
info.lower, info.upper = l, u
1458+
end
1459+
end
1460+
ret = Highs_changeColsBoundsBySet(model, N, columns, lower, upper)
1461+
_check_ret(ret)
1462+
return
1463+
end
1464+
14301465
function MOI.supports(
14311466
::Optimizer,
14321467
::MOI.ConstraintName,
@@ -1603,6 +1638,31 @@ function MOI.set(
16031638
return
16041639
end
16051640

1641+
function MOI.set(
1642+
model::Optimizer,
1643+
::MOI.ConstraintSet,
1644+
c::Vector{MOI.ConstraintIndex{MOI.ScalarAffineFunction{Float64},S}},
1645+
s::Vector{S},
1646+
) where {S<:_SCALAR_SETS}
1647+
if length(c) != length(s)
1648+
msg = "number of constraints does not match number of sets"
1649+
throw(DimensionMismatch(msg))
1650+
end
1651+
for ci in c
1652+
MOI.throw_if_not_valid(model, ci)
1653+
end
1654+
N = length(c)
1655+
rows, lower, upper = zeros(Cint, N), zeros(Cdouble, N), zeros(Cdouble, N)
1656+
for (i, (ci, si)) in enumerate(zip(c, s))
1657+
info = _info(model, ci)
1658+
rows[i] = info.row
1659+
lower[i], upper[i] = info.lower, info.upper = _bounds(si)
1660+
end
1661+
ret = Highs_changeRowsBoundsBySet(model, N, rows, lower, upper)
1662+
_check_ret(ret)
1663+
return
1664+
end
1665+
16061666
function MOI.get(
16071667
model::Optimizer,
16081668
::MOI.ConstraintFunction,

test/MOI_wrapper.jl

+170
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,176 @@ function test_quadratic_diagonal_modification()
543543
return
544544
end
545545

546+
function test_change_col_bounds_by_set_dimension_mismatch()
547+
model = HiGHS.Optimizer()
548+
MOI.set(model, MOI.Silent(), true)
549+
x = MOI.add_variables(model, 3)
550+
c = MOI.add_constraint.(model, x, MOI.GreaterThan.(1.0:3.0))
551+
@test_throws(
552+
DimensionMismatch,
553+
MOI.set(model, MOI.ConstraintSet(), c, MOI.GreaterThan.([4.0, 5.0])),
554+
)
555+
return
556+
end
557+
558+
function test_change_col_bounds_by_set_invalid()
559+
model = HiGHS.Optimizer()
560+
MOI.set(model, MOI.Silent(), true)
561+
x = MOI.add_variable(model)
562+
c = MOI.add_constraint(model, x, MOI.GreaterThan(0.0))
563+
c_invalid = typeof(c)(-123456)
564+
sets = MOI.GreaterThan.(1.0:2.0)
565+
@test_throws(
566+
MOI.InvalidIndex(c_invalid),
567+
MOI.set(model, MOI.ConstraintSet(), [c, c_invalid], sets),
568+
)
569+
return
570+
end
571+
572+
function test_change_col_bounds_by_set_greater_than()
573+
model = HiGHS.Optimizer()
574+
MOI.set(model, MOI.Silent(), true)
575+
x = MOI.add_variables(model, 3)
576+
c = MOI.add_constraint.(model, x, MOI.GreaterThan.(1.0:3.0))
577+
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
578+
f = 1.0 * x[1] + x[2] + x[3]
579+
MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f)
580+
MOI.optimize!(model)
581+
@test (MOI.get(model, MOI.ObjectiveValue()), 6; atol = 1e-6)
582+
MOI.set(
583+
model,
584+
MOI.ConstraintSet(),
585+
[c[1], c[3]],
586+
MOI.GreaterThan.([4.0, 5.0]),
587+
)
588+
MOI.optimize!(model)
589+
@test (MOI.get(model, MOI.ObjectiveValue()), 11; atol = 1e-6)
590+
@test MOI.get(model, MOI.ConstraintSet(), c) ==
591+
MOI.GreaterThan.([4.0, 2.0, 5.0])
592+
return
593+
end
594+
595+
function test_change_col_bounds_by_set_less_than()
596+
model = HiGHS.Optimizer()
597+
MOI.set(model, MOI.Silent(), true)
598+
x = MOI.add_variables(model, 3)
599+
c = MOI.add_constraint.(model, x, MOI.LessThan.(1.0:3.0))
600+
MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE)
601+
f = 1.0 * x[1] + x[2] + x[3]
602+
MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f)
603+
MOI.optimize!(model)
604+
@test (MOI.get(model, MOI.ObjectiveValue()), 6; atol = 1e-6)
605+
MOI.set(model, MOI.ConstraintSet(), [c[1], c[3]], MOI.LessThan.([4.0, 5.0]))
606+
MOI.optimize!(model)
607+
@test (MOI.get(model, MOI.ObjectiveValue()), 11; atol = 1e-6)
608+
@test MOI.get(model, MOI.ConstraintSet(), c) ==
609+
MOI.LessThan.([4.0, 2.0, 5.0])
610+
return
611+
end
612+
613+
function test_change_col_bounds_by_set_equal_to()
614+
model = HiGHS.Optimizer()
615+
MOI.set(model, MOI.Silent(), true)
616+
x = MOI.add_variables(model, 3)
617+
c = MOI.add_constraint.(model, x, MOI.EqualTo.(1.0:3.0))
618+
MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE)
619+
f = 1.0 * x[1] + x[2] + x[3]
620+
MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f)
621+
MOI.optimize!(model)
622+
@test (MOI.get(model, MOI.ObjectiveValue()), 6; atol = 1e-6)
623+
MOI.set(model, MOI.ConstraintSet(), [c[1], c[3]], MOI.EqualTo.([4.0, 5.0]))
624+
MOI.optimize!(model)
625+
@test (MOI.get(model, MOI.ObjectiveValue()), 11; atol = 1e-6)
626+
@test MOI.get(model, MOI.ConstraintSet(), c) ==
627+
MOI.EqualTo.([4.0, 2.0, 5.0])
628+
return
629+
end
630+
631+
function test_change_row_bounds_by_set_dimension_mismatch()
632+
model = HiGHS.Optimizer()
633+
MOI.set(model, MOI.Silent(), true)
634+
x = MOI.add_variables(model, 3)
635+
c = MOI.add_constraint.(model, 1.0 .* x, MOI.GreaterThan.(1.0:3.0))
636+
@test_throws(
637+
DimensionMismatch,
638+
MOI.set(model, MOI.ConstraintSet(), c, MOI.GreaterThan.([4.0, 5.0])),
639+
)
640+
return
641+
end
642+
643+
function test_change_row_bounds_by_set_invalid()
644+
model = HiGHS.Optimizer()
645+
MOI.set(model, MOI.Silent(), true)
646+
x = MOI.add_variable(model)
647+
c = MOI.add_constraint(model, 1.0 .* x, MOI.GreaterThan(0.0))
648+
c_invalid = typeof(c)(-123456)
649+
sets = MOI.GreaterThan.(1.0:2.0)
650+
@test_throws(
651+
MOI.InvalidIndex(c_invalid),
652+
MOI.set(model, MOI.ConstraintSet(), [c, c_invalid], sets),
653+
)
654+
return
655+
end
656+
657+
function test_change_row_bounds_by_set_greater_than()
658+
model = HiGHS.Optimizer()
659+
MOI.set(model, MOI.Silent(), true)
660+
x = MOI.add_variables(model, 3)
661+
c = MOI.add_constraint.(model, 1.0 .* x, MOI.GreaterThan.(1.0:3.0))
662+
MOI.set(model, MOI.ObjectiveSense(), MOI.MIN_SENSE)
663+
f = 1.0 * x[1] + x[2] + x[3]
664+
MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f)
665+
MOI.optimize!(model)
666+
@test (MOI.get(model, MOI.ObjectiveValue()), 6; atol = 1e-6)
667+
MOI.set(
668+
model,
669+
MOI.ConstraintSet(),
670+
[c[1], c[3]],
671+
MOI.GreaterThan.([4.0, 5.0]),
672+
)
673+
MOI.optimize!(model)
674+
@test (MOI.get(model, MOI.ObjectiveValue()), 11; atol = 1e-6)
675+
@test MOI.get(model, MOI.ConstraintSet(), c) ==
676+
MOI.GreaterThan.([4.0, 2.0, 5.0])
677+
return
678+
end
679+
680+
function test_change_row_bounds_by_set_less_than()
681+
model = HiGHS.Optimizer()
682+
MOI.set(model, MOI.Silent(), true)
683+
x = MOI.add_variables(model, 3)
684+
c = MOI.add_constraint.(model, 1.0 .* x, MOI.LessThan.(1.0:3.0))
685+
MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE)
686+
f = 1.0 * x[1] + x[2] + x[3]
687+
MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f)
688+
MOI.optimize!(model)
689+
@test (MOI.get(model, MOI.ObjectiveValue()), 6; atol = 1e-6)
690+
MOI.set(model, MOI.ConstraintSet(), [c[1], c[3]], MOI.LessThan.([4.0, 5.0]))
691+
MOI.optimize!(model)
692+
@test (MOI.get(model, MOI.ObjectiveValue()), 11; atol = 1e-6)
693+
@test MOI.get(model, MOI.ConstraintSet(), c) ==
694+
MOI.LessThan.([4.0, 2.0, 5.0])
695+
return
696+
end
697+
698+
function test_change_row_bounds_by_set_equal_to()
699+
model = HiGHS.Optimizer()
700+
MOI.set(model, MOI.Silent(), true)
701+
x = MOI.add_variables(model, 3)
702+
c = MOI.add_constraint.(model, 1.0 .* x, MOI.EqualTo.(1.0:3.0))
703+
MOI.set(model, MOI.ObjectiveSense(), MOI.MAX_SENSE)
704+
f = 1.0 * x[1] + x[2] + x[3]
705+
MOI.set(model, MOI.ObjectiveFunction{typeof(f)}(), f)
706+
MOI.optimize!(model)
707+
@test (MOI.get(model, MOI.ObjectiveValue()), 6; atol = 1e-6)
708+
MOI.set(model, MOI.ConstraintSet(), [c[1], c[3]], MOI.EqualTo.([4.0, 5.0]))
709+
MOI.optimize!(model)
710+
@test (MOI.get(model, MOI.ObjectiveValue()), 11; atol = 1e-6)
711+
@test MOI.get(model, MOI.ConstraintSet(), c) ==
712+
MOI.EqualTo.([4.0, 2.0, 5.0])
713+
return
714+
end
715+
546716
end
547717

548718
TestMOIHighs.runtests()

0 commit comments

Comments
 (0)