diff --git a/src/Utilities/matrix_of_constraints.jl b/src/Utilities/matrix_of_constraints.jl index 622a0eafa7..f48b5a0f33 100644 --- a/src/Utilities/matrix_of_constraints.jl +++ b/src/Utilities/matrix_of_constraints.jl @@ -314,3 +314,20 @@ function final_touch(model::MatrixOfConstraints, index_map) empty!(model.caches) return end + +# Users of `MatrixOfConstraints` assume variable indices to be `1:n` where `n` +# is the number of columns so we don't support variable deletion. +function _throw_if_cannot_delete( + ::MatrixOfConstraints, + ::Vector{MOI.VariableIndex}, + vi::MOI.VariableIndex, +) + return throw(MOI.DeleteNotAllowed(vi)) +end +function _throw_if_cannot_delete( + ::MatrixOfConstraints, + vis::Vector{MOI.VariableIndex}, + ::Set{MOI.VariableIndex}, +) + return throw(MOI.DeleteNotAllowed(first(vis))) +end diff --git a/src/Utilities/model.jl b/src/Utilities/model.jl index 614a83af7a..15ab2927d4 100644 --- a/src/Utilities/model.jl +++ b/src/Utilities/model.jl @@ -129,9 +129,11 @@ function _delete_variable( MOI.ConstraintIndex{MOI.SingleVariable,MOI.Semiinteger{T}}(vi.value), ) end +_fast_in(vi1::MOI.VariableIndex, vi2::MOI.VariableIndex) = vi1 == vi2 +_fast_in(vi::MOI.VariableIndex, vis::Set{MOI.VariableIndex}) = vi in vis function MOI.delete(model::AbstractModel, vi::MOI.VariableIndex) vis = [vi] - _throw_if_cannot_delete(model.constraints, vis, vis) + _throw_if_cannot_delete(model.constraints, vis, vi) _delete_variable(model, vi) _deleted_constraints(model.constraints, vi) do ci return delete!(model.con_to_name, ci) diff --git a/src/Utilities/universalfallback.jl b/src/Utilities/universalfallback.jl index ef133ef133..afc38fc224 100644 --- a/src/Utilities/universalfallback.jl +++ b/src/Utilities/universalfallback.jl @@ -204,7 +204,7 @@ end function MOI.delete(uf::UniversalFallback, vi::MOI.VariableIndex) vis = [vi] for constraints in values(uf.constraints) - _throw_if_cannot_delete(constraints, vis, vis) + _throw_if_cannot_delete(constraints, vis, vi) end MOI.delete(uf.model, vi) for d in values(uf.varattr) diff --git a/src/Utilities/vector_of_constraints.jl b/src/Utilities/vector_of_constraints.jl index 0373801163..286a0bbfb6 100644 --- a/src/Utilities/vector_of_constraints.jl +++ b/src/Utilities/vector_of_constraints.jl @@ -186,7 +186,7 @@ function _throw_if_cannot_delete( f = fs[1]::MOI.VectorOfVariables if length(f.variables) > 1 && f.variables != vis for vi in f.variables - if vi in fast_in_vis + if _fast_in(vi, fast_in_vis) # If `supports_dimension_update(S)` then the variable # will be removed in `_filter_variables`. throw_delete_variable_in_vov(vi) diff --git a/test/Utilities/matrix_of_constraints.jl b/test/Utilities/matrix_of_constraints.jl index 33bffbbee6..d235c8fec9 100644 --- a/test/Utilities/matrix_of_constraints.jl +++ b/test/Utilities/matrix_of_constraints.jl @@ -218,6 +218,14 @@ MOIU.@product_of_sets( false, Indexing, ) do optimizer + vis = MOI.get(optimizer, MOI.ListOfVariableIndices()) + @test_throws MOI.DeleteNotAllowed(first(vis)) MOI.delete( + optimizer, + vis, + ) + for vi in vis + @test_throws MOI.DeleteNotAllowed(vi) MOI.delete(optimizer, vi) + end con_types = [ (F, MOI.EqualTo{Float64}), (F, MOI.GreaterThan{Float64}), @@ -234,6 +242,10 @@ MOIU.@product_of_sets( for ci in cis @test MOI.is_valid(optimizer, ci) @test i == MOI.Utilities.rows(optimizer.constraints, ci) + @test_throws MOI.DeleteNotAllowed(ci) MOI.delete( + optimizer, + ci, + ) end end end