From 4078f293fbdee9ee60601cff43748f455ef9960b Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Wed, 9 Sep 2026 11:40:55 +1200 Subject: [PATCH] [Utilities] fix deleting variables and constraints in MockOptimizer --- src/Utilities/mockoptimizer.jl | 24 ++++++++++-------- test/Utilities/test_mockoptimizer.jl | 38 ++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 11 deletions(-) diff --git a/src/Utilities/mockoptimizer.jl b/src/Utilities/mockoptimizer.jl index 401df2b21e..00c833b04e 100644 --- a/src/Utilities/mockoptimizer.jl +++ b/src/Utilities/mockoptimizer.jl @@ -865,15 +865,15 @@ end function MOI.delete(mock::MockOptimizer, index::MOI.VariableIndex) if !mock.delete_allowed throw(MOI.DeleteNotAllowed(index)) - end - if !MOI.is_valid(mock, index) + elseif !MOI.is_valid(mock, index) # The index thrown by `mock.inner_model` would be xored throw(MOI.InvalidIndex(index)) end - MOI.delete(mock.inner_model, xor_index(index)) - delete!(mock.variable_primal, index) - delete!(mock.callback_variable_primal, index) - delete!(mock.variable_basis_status, index) + xored = xor_index(index) + MOI.delete(mock.inner_model, xored) + delete!(mock.variable_primal, xored) + delete!(mock.callback_variable_primal, xored) + delete!(mock.variable_basis_status, xored) return end @@ -885,8 +885,9 @@ function MOI.delete(mock::MockOptimizer, indices::Vector{MOI.VariableIndex}) # The index thrown by `mock.inner_model` would be xored MOI.throw_if_not_valid(mock, index) end - MOI.delete(mock.inner_model, xor_index.(indices)) - for index in indices + xored = xor_index.(indices) + MOI.delete(mock.inner_model, xored) + for index in xored delete!(mock.variable_primal, index) delete!(mock.callback_variable_primal, index) delete!(mock.variable_basis_status, index) @@ -902,9 +903,10 @@ function MOI.delete(mock::MockOptimizer, index::MOI.ConstraintIndex) # The index thrown by `mock.inner_model` would be xored throw(MOI.InvalidIndex(index)) end - MOI.delete(mock.inner_model, xor_index(index)) - delete!(mock.constraint_dual, index) - delete!(mock.constraint_basis_status, index) + xored = xor_index(index) + MOI.delete(mock.inner_model, xored) + delete!(mock.constraint_dual, xored) + delete!(mock.constraint_basis_status, xored) return end diff --git a/test/Utilities/test_mockoptimizer.jl b/test/Utilities/test_mockoptimizer.jl index 8cb2b56786..c2550d3a12 100644 --- a/test/Utilities/test_mockoptimizer.jl +++ b/test/Utilities/test_mockoptimizer.jl @@ -307,6 +307,44 @@ function test_empty_constructor() return end +function test_delete_mock_variable() + model = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + x = MOI.add_variables(model, 3) + MOI.set.(model, MOI.VariablePrimal(), x, [1.0, 2.0, 3.0]) + MOI.delete(model, x[2]) + @test length(model.variable_primal) == 2 + @test haskey(model.variable_primal, MOI.Utilities.xor_index(x[1])) + @test !haskey(model.variable_primal, MOI.Utilities.xor_index(x[2])) + @test haskey(model.variable_primal, MOI.Utilities.xor_index(x[3])) + return +end + +function test_delete_mock_variable_vector() + model = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + x = MOI.add_variables(model, 3) + MOI.set.(model, MOI.VariablePrimal(), x, [1.0, 2.0, 3.0]) + MOI.delete(model, x[1:2]) + @test length(model.variable_primal) == 1 + @test !haskey(model.variable_primal, MOI.Utilities.xor_index(x[1])) + @test !haskey(model.variable_primal, MOI.Utilities.xor_index(x[2])) + @test haskey(model.variable_primal, MOI.Utilities.xor_index(x[3])) + return +end + +function test_delete_mock_constraint() + model = MOI.Utilities.MockOptimizer(MOI.Utilities.Model{Float64}()) + x = MOI.add_variables(model, 3) + c = MOI.add_constraint.(model, x, MOI.EqualTo(1.0)) + @test isempty(model.constraint_dual) + MOI.set.(model, MOI.ConstraintDual(), c, [1.0, 2.0, 3.0]) + MOI.delete(model, c[2]) + @test length(model.constraint_dual) == 2 + @test haskey(model.constraint_dual, MOI.Utilities.xor_index(c[1])) + @test !haskey(model.constraint_dual, MOI.Utilities.xor_index(c[2])) + @test haskey(model.constraint_dual, MOI.Utilities.xor_index(c[3])) + return +end + end # module TestMockOptimizer.runtests()