diff --git a/src/Utilities/matrix_of_constraints.jl b/src/Utilities/matrix_of_constraints.jl index 503b149110..43d4f80448 100644 --- a/src/Utilities/matrix_of_constraints.jl +++ b/src/Utilities/matrix_of_constraints.jl @@ -707,10 +707,11 @@ function MOI.modify( ci::MOI.ConstraintIndex, change::Union{MOI.ScalarConstantChange,MOI.VectorConstantChange}, ) - try + ret = modify_constants(model.constants, rows(model, ci), change.new_constant) - catch - throw(MOI.ModifyConstraintNotAllowed(ci, change)) + if ret == _ModifyConstantsNotImplemented() + msg = "`modify_constants` is not implemented for `$(typeof(model.constants))`" + throw(MOI.ModifyConstraintNotAllowed(ci, change, msg)) end return end @@ -738,6 +739,15 @@ function MOI.modify( return end +# See https://github.com/jump-dev/MathOptInterface.jl/pull/2976 +# Ideally we would have made it so that `modify_constants` operated like +# `modify_coefficients` and returned a `Bool` indicating success. But we didn't, +# so here's a hacky work-around to catch if the method is not implemented +# without resorting to a try-catch. +struct _ModifyConstantsNotImplemented end + +modify_constants(args...) = _ModifyConstantsNotImplemented() + function modify_constants( b::AbstractVector{T}, row::Integer, diff --git a/test/Utilities/test_matrix_of_constraints.jl b/test/Utilities/test_matrix_of_constraints.jl index 256fb2a931..f545c2b3b9 100644 --- a/test/Utilities/test_matrix_of_constraints.jl +++ b/test/Utilities/test_matrix_of_constraints.jl @@ -763,6 +763,31 @@ function test_modify_vectorsets() return end +function test_modify_constants_bounds_error() + model = _new_VectorSets() + src = MOI.Utilities.Model{Int}() + x = MOI.add_variables(src, 2) + c = MOI.add_constraint( + src, + MOI.VectorAffineFunction{Int}( + MOI.VectorAffineTerm.(1, MOI.ScalarAffineTerm.(1, x)), + [1, 3], + ), + MOI.SecondOrderCone(2), + ) + index_map = MOI.copy_to(model, src) + resize!(model.constraints.constants, 0) + @test_throws( + BoundsError, + MOI.modify( + model.constraints, + index_map[c], + MOI.VectorConstantChange([4, 5]), + ), + ) + return +end + function test_modify_set_constants() model = MOI.Utilities.Model{Float64}() x = MOI.add_variables(model, 3) @@ -789,8 +814,13 @@ function test_modify_set_constants() index_map = MOI.copy_to(cache, model) ci = index_map[p_ref] change = MOI.VectorConstantChange([4.0, 5.0, 6.0]) + constants_type = typeof(cache.constraints.constants) @test_throws( - MOI.ModifyConstraintNotAllowed(ci, change), + MOI.ModifyConstraintNotAllowed( + ci, + change, + "`modify_constants` is not implemented for `$constants_type`", + ), MOI.modify(cache, ci, change), ) return