Skip to content

Commit a38a1d8

Browse files
committed
Reword and clarify ConstraintBasisStatus in mockoptimizer
1 parent 1b848c6 commit a38a1d8

File tree

5 files changed

+70
-67
lines changed

5 files changed

+70
-67
lines changed

src/Bridges/intervalbridge.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,11 +52,11 @@ function MOI.get(model::MOI.ModelLike, ::MOI.ConstraintBasisStatus, c::SplitInte
5252
lower_stat = MOI.get(model, MOI.ConstraintBasisStatus(), c.lower)
5353
upper_stat = MOI.get(model, MOI.ConstraintBasisStatus(), c.upper)
5454
if lower_stat == MOI.NONBASIC_AT_LOWER
55-
Compat.@warn("Single sided constraints should not have basis status:" *
55+
Compat.@warn("GreaterThan constraints should not have basis status:" *
5656
" NONBASIC_AT_LOWER, instead use NONBASIC.")
5757
end
5858
if upper_stat == MOI.NONBASIC_AT_UPPER
59-
Compat.@warn("Single sided constraints should not have basis status:" *
59+
Compat.@warn("LessThan constraints should not have basis status:" *
6060
" NONBASIC_AT_UPPER, instead use NONBASIC.")
6161
end
6262
if lower_stat == MOI.NONBASIC
@@ -66,7 +66,7 @@ function MOI.get(model::MOI.ModelLike, ::MOI.ConstraintBasisStatus, c::SplitInte
6666
return MOI.NONBASIC_AT_UPPER
6767
end
6868
if lower_stat != upper_stat
69-
Compat.@warn("Basis status of lower ($lower_stat) and upper ($upper_stat) constraint are inconsistent," *
69+
Compat.@warn("Basis status of lower (`$lower_stat`) and upper (`$upper_stat`) constraint are inconsistent," *
7070
" both should be basic or super basic.")
7171
end
7272
return lower_stat

src/Test/contlinear.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1161,7 +1161,7 @@ function linear10test(model::MOI.ModelLike, config::TestConfig)
11611161
end
11621162

11631163
if config.basis
1164-
# multiple optimal basis, x or y can in the optimal basis
1164+
# There are multiple optimal bases. Either x or y can be in the optimal basis.
11651165
@test (MOI.get(model, MOI.ConstraintBasisStatus(), vc[1]) == MOI.BASIC ||
11661166
MOI.get(model, MOI.ConstraintBasisStatus(), vc[2])== MOI.BASIC)
11671167
@test MOI.get(model, MOI.ConstraintBasisStatus(), c) == MOI.NONBASIC_AT_UPPER
@@ -1186,7 +1186,7 @@ function linear10test(model::MOI.ModelLike, config::TestConfig)
11861186
end
11871187

11881188
if config.basis
1189-
# multiple optimal basis, x or y can in the optimal basis
1189+
# There are multiple optimal bases. Either x or y can be in the optimal basis."
11901190
@test (MOI.get(model, MOI.ConstraintBasisStatus(), vc[1]) == MOI.BASIC ||
11911191
MOI.get(model, MOI.ConstraintBasisStatus(), vc[2])== MOI.BASIC)
11921192
@test MOI.get(model, MOI.ConstraintBasisStatus(), c) == MOI.NONBASIC_AT_LOWER
@@ -1208,7 +1208,7 @@ function linear10test(model::MOI.ModelLike, config::TestConfig)
12081208
@test MOI.get(model, MOI.ConstraintPrimal(), c) 2 atol=atol rtol=rtol
12091209

12101210
if config.basis
1211-
# multiple optimal basis, x or y can in the optimal basis
1211+
# There are multiple optimal bases. Either x or y can be in the optimal basis.
12121212
@test (MOI.get(model, MOI.ConstraintBasisStatus(), vc[1]) == MOI.BASIC ||
12131213
MOI.get(model, MOI.ConstraintBasisStatus(), vc[2])== MOI.BASIC)
12141214
@test MOI.get(model, MOI.ConstraintBasisStatus(), c) == MOI.NONBASIC_AT_LOWER
@@ -1227,7 +1227,7 @@ function linear10test(model::MOI.ModelLike, config::TestConfig)
12271227
@test MOI.get(model, MOI.ConstraintPrimal(), c) 12 atol=atol rtol=rtol
12281228

12291229
if config.basis
1230-
# multiple optimal basis, x or y can in the optimal basis
1230+
# There are multiple optimal bases. Either x or y can be in the optimal basis.
12311231
@test (MOI.get(model, MOI.ConstraintBasisStatus(), vc[1]) == MOI.BASIC ||
12321232
MOI.get(model, MOI.ConstraintBasisStatus(), vc[2])== MOI.BASIC)
12331233
@test MOI.get(model, MOI.ConstraintBasisStatus(), c) == MOI.NONBASIC_AT_UPPER

src/Utilities/mockoptimizer.jl

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ mutable struct MockOptimizer{MT<:MOI.ModelLike} <: MOI.AbstractOptimizer
4141
# constraints having the variable in the function. See `get_fallback`.
4242
eval_variable_constraint_dual::Bool
4343
condual::Dict{MOI.ConstraintIndex,Any}
44-
conbasis::Dict{MOI.ConstraintIndex,MOI.BasisStatusCode}
44+
con_basis::Dict{MOI.ConstraintIndex,MOI.BasisStatusCode}
4545
end
4646

4747
# All user-facing indices are xor'd with this mask to produce unusual indices.
@@ -162,7 +162,7 @@ MOI.set(mock::MockOptimizer, ::MockVariableAttribute, idx::MOI.VariableIndex, va
162162
MOI.set(mock::MockOptimizer, attr::MOI.AbstractConstraintAttribute, idx::MOI.ConstraintIndex, value) = MOI.set(mock.inner_model, attr, xor_index(idx), value)
163163
MOI.set(mock::MockOptimizer, ::MockConstraintAttribute, idx::MOI.ConstraintIndex, value) = (mock.conattribute[xor_index(idx)] = value)
164164
MOI.set(mock::MockOptimizer, ::MOI.ConstraintDual, idx::MOI.ConstraintIndex, value) = (mock.condual[xor_index(idx)] = value)
165-
MOI.set(mock::MockOptimizer, ::MOI.ConstraintBasisStatus, idx::MOI.ConstraintIndex, value) = (mock.conbasis[xor_index(idx)] = value)
165+
MOI.set(mock::MockOptimizer, ::MOI.ConstraintBasisStatus, idx::MOI.ConstraintIndex, value) = (mock.con_basis[xor_index(idx)] = value)
166166

167167
MOI.get(mock::MockOptimizer, attr::MOI.AbstractModelAttribute) = MOI.get(mock.inner_model, attr)
168168
MOI.get(mock::MockOptimizer, attr::Union{MOI.ListOfVariableIndices,
@@ -256,7 +256,7 @@ function MOI.get(mock::MockOptimizer, attr::MOI.ConstraintDual,
256256
end
257257
end
258258
MOI.get(mock::MockOptimizer, ::MockConstraintAttribute, idx::MOI.ConstraintIndex) = mock.conattribute[xor_index(idx)]
259-
MOI.get(mock::MockOptimizer, ::MOI.ConstraintBasisStatus, idx::MOI.ConstraintIndex) = mock.conbasis[xor_index(idx)]
259+
MOI.get(mock::MockOptimizer, ::MOI.ConstraintBasisStatus, idx::MOI.ConstraintIndex) = mock.con_basis[xor_index(idx)]
260260

261261
MOI.supports(mock::MockOptimizer, ::MOI.ObjectiveBound) = true
262262
MOI.get(mock::MockOptimizer, ::MOI.ObjectiveBound) = mock.objectivebound
@@ -282,7 +282,7 @@ function MOI.empty!(mock::MockOptimizer)
282282
mock.dualstatus = MOI.NO_SOLUTION
283283
mock.varprimal = Dict{MOI.VariableIndex,Float64}()
284284
mock.condual = Dict{MOI.ConstraintIndex,Any}()
285-
mock.conbasis = Dict{MOI.ConstraintIndex,MOI.BasisStatusCode}()
285+
mock.con_basis = Dict{MOI.ConstraintIndex,MOI.BasisStatusCode}()
286286
return
287287
end
288288

@@ -322,7 +322,7 @@ function MOI.delete(mock::MockOptimizer, index::MOI.ConstraintIndex)
322322
end
323323
MOI.delete(mock.inner_model, xor_index(index))
324324
delete!(mock.condual, index)
325-
delete!(mock.conbasis, index)
325+
delete!(mock.con_basis, index)
326326
end
327327

328328
function MOI.modify(mock::MockOptimizer, c::CI, change::MOI.AbstractFunctionModification)
@@ -395,17 +395,20 @@ The primal values of the variables in the order returned by `ListOfVariableIndic
395395
If `termstatus` is missing, it is assumed to be `MOI.OPTIMAL`.
396396
If `primstatus` is missing, it is assumed to be `MOI.FEASIBLE_POINT`.
397397
If `dualstatus` is missing, it is assumed to be `MOI.FEASIBLE_POINT` if there is a primal solution and `primstatus` is not `MOI.INFEASIBLE_POINT`, otherwise it is `MOI.INFEASIBILITY_CERTIFICATE`.
398-
The bases status are set to the status specified by `conbasis`. Each pair is of the form `(F,S)=>[...]` where `[...]` is the the vector of basis status for the constraints `F`-in-`S` in the order returned by `ListOfConstraintIndices{F,S}`.
399398
The dual values are set to the values specified by `conduals`. Each pair is of the form `(F,S)=>[...]` where `[...]` is the the vector of dual values for the constraints `F`-in-`S` in the order returned by `ListOfConstraintIndices{F,S}`.
399+
The bases status are set to the status specified by `con_basis`. A vector of pairs, each of the form `(F,S)=>[...]`, where `[...]` is the the vector of basis status for the constraints `F`-in-`S` in the order returned by `ListOfConstraintIndices{F,S}`.
400400
"""
401-
function mock_optimize!(mock::MockOptimizer, termstatus::MOI.TerminationStatusCode, primal, basis_dual...)
401+
function mock_optimize!(mock::MockOptimizer, termstatus::MOI.TerminationStatusCode, primal, dual...; con_basis = [])
402402
MOI.set(mock, MOI.TerminationStatus(), termstatus)
403403
MOI.set(mock, MOI.ResultCount(), 1)
404404
mock_primal!(mock, primal)
405-
mock_dual!(mock, basis_dual...)
405+
mock_dual!(mock, dual...)
406+
for con_basis_pair in con_basis
407+
mock_basis_status!(mock, con_basis_pair)
408+
end
406409
end
407410
# Default termination status
408-
mock_optimize!(mock::MockOptimizer, primdual...) = mock_optimize!(mock, MOI.OPTIMAL, primdual...)
411+
mock_optimize!(mock::MockOptimizer, primal, dual...; con_basis = []) = mock_optimize!(mock, MOI.OPTIMAL, primal, con_basis = con_basis, dual...)
409412
function mock_optimize!(mock::MockOptimizer, termstatus::MOI.TerminationStatusCode)
410413
MOI.set(mock, MOI.TerminationStatus(), termstatus)
411414
MOI.set(mock, MOI.ResultCount(), 0)
@@ -435,15 +438,6 @@ function mock_dual!(mock::MockOptimizer, dualstatus::MOI.ResultStatusCode, condu
435438
MOI.set(mock, MOI.DualStatus(), dualstatus)
436439
mock_condual!(mock, conduals...)
437440
end
438-
# Set the provided constraint basis status
439-
function mock_dual!(mock::MockOptimizer, conbases::Pair{T,Vector{MOI.BasisStatusCode}}, conbases_duals::Pair...) where {T<:Any}
440-
F, S = conbases.first
441-
bases = conbases.second
442-
for (i, ci) in enumerate(MOI.get(mock, MOI.ListOfConstraintIndices{F, S}()))
443-
MOI.set(mock, MOI.ConstraintBasisStatus(), ci, bases[i])
444-
end
445-
mock_dual!(mock, conbases_duals...)
446-
end
447441
# Default dual status
448442
function mock_dual!(mock::MockOptimizer, conduals::Pair...)
449443
status = !mock.hasprimal || MOI.get(mock, MOI.PrimalStatus()) == MOI.INFEASIBLE_POINT ? MOI.INFEASIBILITY_CERTIFICATE : MOI.FEASIBLE_POINT
@@ -464,3 +458,11 @@ function mock_condual!(mock::MockOptimizer, condual::Pair, conduals...)
464458
end
465459
mock_condual!(mock, conduals...)
466460
end
461+
# Set the basis status of the provided constraints.
462+
function mock_basis_status!(mock::MockOptimizer, con_basis::Pair)
463+
F, S = con_basis.first
464+
bases = con_basis.second
465+
for (i, ci) in enumerate(MOI.get(mock, MOI.ListOfConstraintIndices{F, S}()))
466+
MOI.set(mock, MOI.ConstraintBasisStatus(), ci, bases[i])
467+
end
468+
end

test/Test/contlinear.jl

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -25,17 +25,18 @@
2525
MOIT.linear1test(mock, config_no_lhs_modif)
2626
MOIU.set_mock_optimize!(mock,
2727
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1, 0],
28-
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [MOI.NONBASIC],
29-
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.BASIC, MOI.NONBASIC],
30-
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [-1]))
28+
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [-1],
29+
con_basis =
30+
[(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [MOI.NONBASIC],
31+
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.BASIC, MOI.NONBASIC]]))
3132
MOIT.linear2test(mock, config)
3233
MOIU.set_mock_optimize!(mock,
33-
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [3],
34-
(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [MOI.NONBASIC],
35-
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.BASIC]),
36-
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0],
37-
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [MOI.BASIC],
38-
(MOI.SingleVariable, MOI.LessThan{Float64}) => [MOI.NONBASIC]))
34+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [3], con_basis =
35+
[(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [MOI.NONBASIC],
36+
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.BASIC]]),
37+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0], con_basis =
38+
[(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [MOI.BASIC],
39+
(MOI.SingleVariable, MOI.LessThan{Float64}) => [MOI.NONBASIC]]))
3940
MOIT.linear3test(mock, config)
4041
MOIU.set_mock_optimize!(mock,
4142
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0, 0]),
@@ -90,26 +91,26 @@
9091
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, MOI.DUAL_INFEASIBLE))
9192
MOIT.linear8ctest(mock, MOIT.TestConfig(infeas_certificates=false))
9293
MOIU.set_mock_optimize!(mock,
93-
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [650/11, 400/11],
94-
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [MOI.NONBASIC, MOI.NONBASIC],
94+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [650/11, 400/11], con_basis =
95+
[(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [MOI.NONBASIC, MOI.NONBASIC],
9596
(MOI.ScalarAffineFunction{Float64}, MOI.GreaterThan{Float64}) => [MOI.BASIC],
96-
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.BASIC, MOI.BASIC]))
97+
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.BASIC, MOI.BASIC]]))
9798
MOIT.linear9test(mock, config)
9899
MOIU.set_mock_optimize!(mock,
99-
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [5.0, 5.0],
100-
(MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}) => [MOI.NONBASIC_AT_UPPER],
101-
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.BASIC, MOI.BASIC],
100+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [5.0, 5.0], con_basis =
101+
[(MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}) => [MOI.NONBASIC_AT_UPPER],
102+
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.BASIC, MOI.BASIC]],
102103
(MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}) => [-1]),
103-
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [2.5, 2.5],
104-
(MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}) => [MOI.NONBASIC_AT_LOWER],
105-
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.BASIC, MOI.BASIC],
104+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [2.5, 2.5], con_basis =
105+
[(MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}) => [MOI.NONBASIC_AT_LOWER],
106+
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.BASIC, MOI.BASIC]],
106107
(MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}) => [1]),
107-
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1.0, 1.0],
108-
(MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}) => [MOI.NONBASIC_AT_LOWER],
109-
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.BASIC, MOI.BASIC]),
110-
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [6.0, 6.0],
111-
(MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}) => [MOI.NONBASIC_AT_UPPER],
112-
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.BASIC, MOI.BASIC]))
108+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1.0, 1.0], con_basis =
109+
[(MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}) => [MOI.NONBASIC_AT_LOWER],
110+
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.BASIC, MOI.BASIC]]),
111+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [6.0, 6.0], con_basis =
112+
[(MOI.ScalarAffineFunction{Float64}, MOI.Interval{Float64}) => [MOI.NONBASIC_AT_UPPER],
113+
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.BASIC, MOI.BASIC]]))
113114
MOIT.linear10test(mock, config)
114115
MOIU.set_mock_optimize!(mock,
115116
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [1.0, 1.0]),
@@ -129,10 +130,10 @@
129130
(MOI.ScalarAffineFunction{Float64}, MOI.EqualTo{Float64}) => [0]))
130131
MOIT.linear13test(mock, config)
131132
MOIU.set_mock_optimize!(mock,
132-
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0, 1/2, 1],
133-
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [MOI.NONBASIC],
133+
(mock::MOIU.MockOptimizer) -> MOIU.mock_optimize!(mock, [0, 1/2, 1], con_basis =
134+
[(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [MOI.NONBASIC],
134135
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [MOI.NONBASIC, MOI.BASIC, MOI.BASIC],
135-
(MOI.SingleVariable, MOI.LessThan{Float64}) => [MOI.NONBASIC],
136+
(MOI.SingleVariable, MOI.LessThan{Float64}) => [MOI.NONBASIC]],
136137
(MOI.ScalarAffineFunction{Float64}, MOI.LessThan{Float64}) => [-1],
137138
(MOI.SingleVariable, MOI.GreaterThan{Float64}) => [2, 0, 0],
138139
(MOI.SingleVariable, MOI.LessThan{Float64}) => [-2]),

0 commit comments

Comments
 (0)