From 95e16c49273412e0a2bd6ec250ee508d68d596d1 Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Thu, 31 Oct 2024 12:37:06 +1300 Subject: [PATCH] [Utilities] fix adding unsupported constraints to AbstractModel (#2572) --- src/Utilities/model.jl | 28 +++++++++++++++++++++------- test/Utilities/model.jl | 29 +++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/Utilities/model.jl b/src/Utilities/model.jl index 0aa4690640..6586b95e42 100644 --- a/src/Utilities/model.jl +++ b/src/Utilities/model.jl @@ -312,9 +312,16 @@ end function MOI.add_constraint( model::AbstractModel, - func::MOI.AbstractFunction, - set::MOI.AbstractSet, -) + func::F, + set::S, +) where {F<:MOI.AbstractFunction,S<:MOI.AbstractSet} + # We check supports_constraint here because it is a common practice for + # AbstractModels to declare that they do not support particular constraints, + # even though the underlying `.constraints` object does. See, for example, + # the various models in MOI.FileFormats. + if !MOI.supports_constraint(model, F, S) + throw(MOI.UnsupportedConstraint{F,S}()) + end return MOI.add_constraint(model.constraints, func, set) end @@ -328,10 +335,17 @@ end function MOI.add_constraint( model::AbstractModel, - f::MOI.VariableIndex, - s::MOI.AbstractScalarSet, -) - return MOI.add_constraint(model.variables, f, s) + func::MOI.VariableIndex, + set::S, +) where {S<:MOI.AbstractScalarSet} + # We check supports_constraint here because it is a common practice for + # AbstractModels to declare that they do not support particular constraints, + # even though the underlying `.constraints` object does. See, for example, + # the various models in MOI.FileFormats. + if !MOI.supports_constraint(model, MOI.VariableIndex, S) + throw(MOI.UnsupportedConstraint{MOI.VariableIndex,S}()) + end + return MOI.add_constraint(model.variables, func, set) end # MOI.NumberOfConstraints diff --git a/test/Utilities/model.jl b/test/Utilities/model.jl index 0e9817a139..ba52d51f95 100644 --- a/test/Utilities/model.jl +++ b/test/Utilities/model.jl @@ -515,6 +515,35 @@ function test_vector_of_constraints_list_of_constraint_attributes_set() return end +function test_copy_to_unsupported_scalar_variable() + F, S = MOI.VariableIndex, MOI.GreaterThan{Float64} + model = MOI.Utilities.Model{Float64}() + x, _ = MOI.add_constrained_variable(model, MOI.GreaterThan(1.0)) + dest = MOI.FileFormats.CBF.Model() + @test_throws(MOI.UnsupportedConstraint{F,S}, MOI.copy_to(dest, model)) + return +end + +function test_copy_to_unsupported_vector_variables() + F, S = MOI.VectorOfVariables, MOI.AllDifferent + model = MOI.Utilities.Model{Float64}() + x, _ = MOI.add_constrained_variables(model, MOI.AllDifferent(3)) + dest = MOI.FileFormats.CBF.Model() + @test_throws(MOI.UnsupportedConstraint{F,S}, MOI.copy_to(dest, model)) + return +end + +function test_copy_to_unsupported_scalar_function() + F, S = MOI.ScalarNonlinearFunction, MOI.EqualTo{Float64} + model = MOI.Utilities.Model{Float64}() + x = MOI.add_variable(model) + f = MOI.ScalarNonlinearFunction(:log, Any[x]) + MOI.add_constraint(model, f, MOI.EqualTo(0.0)) + dest = MOI.FileFormats.CBF.Model() + @test_throws(MOI.UnsupportedConstraint{F,S}, MOI.copy_to(dest, model)) + return +end + end # module TestModel.runtests()