diff --git a/src/Bridges/Constraint/functionize.jl b/src/Bridges/Constraint/functionize.jl index 372c137250..526260d563 100644 --- a/src/Bridges/Constraint/functionize.jl +++ b/src/Bridges/Constraint/functionize.jl @@ -72,20 +72,6 @@ function MOI.delete(model::MOI.ModelLike, c::ScalarFunctionizeBridge) end # Constraints -function MOI.set( - model::MOI.ModelLike, - ::MOI.ConstraintFunction, - c::ScalarFunctionizeBridge{T}, - f::MOI.VariableIndex, -) where {T} - MOI.set( - model, - MOI.ConstraintFunction(), - c.constraint, - MOI.ScalarAffineFunction{T}(f), - ) - return -end function MOI.get( model::MOI.ModelLike, diff --git a/src/Bridges/bridge_optimizer.jl b/src/Bridges/bridge_optimizer.jl index cb7cf23f9b..114f690988 100644 --- a/src/Bridges/bridge_optimizer.jl +++ b/src/Bridges/bridge_optimizer.jl @@ -1120,12 +1120,16 @@ function MOI.set( end # Constraint attributes + function MOI.set( b::AbstractBridgeOptimizer, attr::MOI.ConstraintFunction, ci::MOI.ConstraintIndex{F}, - func::F, + func, ) where {F} + if typeof(func) != F + throw(ArgumentError("Invalid type when setting ConstraintFunction.")) + end if Variable.has_bridges(Variable.bridges(b)) set = MOI.get(b, MOI.ConstraintSet(), ci) func, new_set = bridged_constraint_function(b, func, set) @@ -1159,8 +1163,11 @@ function MOI.set( b::AbstractBridgeOptimizer, attr::MOI.ConstraintSet, ci::MOI.ConstraintIndex{MOI.VariableIndex,S}, - value::S, + value, ) where {S<:MOI.AbstractScalarSet} + if typeof(value) != S + throw(ArgumentError("Invalid type when setting ConstraintSet.")) + end _set_substituted(b, attr, ci, value) return end @@ -1182,11 +1189,14 @@ function MOI.set( b::AbstractBridgeOptimizer, attr::MOI.ConstraintSet, ci::MOI.ConstraintIndex{<:MOI.AbstractScalarFunction,S}, - set::S, + set, ) where {S<:MOI.AbstractScalarSet} + if typeof(set) != S + throw(ArgumentError("Invalid type when setting ConstraintSet.")) + end if Variable.has_bridges(Variable.bridges(b)) func = MOI.get(b, MOI.ConstraintFunction(), ci) - new_func, set = bridged_constraint_function(b, func, set) + _, set = bridged_constraint_function(b, func, set) end _set_substituted(b, attr, ci, set) return @@ -1282,6 +1292,15 @@ function MOI.set( return end +function MOI.set( + ::AbstractBridgeOptimizer, + ::MOI.ConstraintFunction, + ::MOI.ConstraintIndex{MOI.VariableIndex}, + ::MOI.VariableIndex, +) + return throw(MOI.SettingVariableIndexNotAllowed()) +end + ## Getting and Setting names function MOI.get( b::AbstractBridgeOptimizer, diff --git a/src/Test/test_modification.jl b/src/Test/test_modification.jl index bd298942c6..21bb1150c2 100644 --- a/src/Test/test_modification.jl +++ b/src/Test/test_modification.jl @@ -932,3 +932,63 @@ function setup_test( ) return end + +""" + test_modification_incorrect(model::MOI.ModelLike, config::Config) + +Test that constraint sets and functions cannot be set for the wrong type. +""" +function test_modification_incorrect(model::MOI.ModelLike, ::Config) + @requires MOI.supports_constraint( + model, + MOI.ScalarAffineFunction{Float64}, + MOI.EqualTo{Float64}, + ) + x = MOI.add_variable(model) + c = MOI.add_constraint( + model, + MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0), + MOI.EqualTo(1.0), + ) + @test_throws( + ArgumentError, + MOI.set(model, MOI.ConstraintSet(), c, MOI.LessThan(1.0)), + ) + @test_throws(ArgumentError, MOI.set(model, MOI.ConstraintFunction(), c, x)) + return +end + +""" + test_modification_incorrect_VariableIndex( + model::MOI.ModelLike, + config::Config, + ) + +Test that constraint sets cannot be set for the wrong set type, and that +VariableIndex functions cannot be modified. +""" +function test_modification_incorrect_VariableIndex( + model::MOI.ModelLike, + ::Config{T}, +) where {T} + @requires MOI.supports_constraint(model, MOI.VariableIndex, MOI.LessThan{T}) + @requires( + MOI.supports_constraint(model, MOI.VariableIndex, MOI.GreaterThan{T}), + ) + x = MOI.add_variable(model) + c = MOI.add_constraint(model, x, MOI.GreaterThan(zero(T))) + @test_throws( + ArgumentError, + MOI.set(model, MOI.ConstraintSet(), c, MOI.LessThan(one(T))), + ) + @test_throws( + ArgumentError, + MOI.set(model, MOI.ConstraintFunction(), c, one(T) * x), + ) + y = MOI.add_variable(model) + @test_throws( + MOI.SettingVariableIndexNotAllowed(), + MOI.set(model, MOI.ConstraintFunction(), c, y), + ) + return +end diff --git a/src/Test/test_objective.jl b/src/Test/test_objective.jl index 1d02194b9c..87e7921f21 100644 --- a/src/Test/test_objective.jl +++ b/src/Test/test_objective.jl @@ -517,29 +517,3 @@ function test_objective_set_via_modify(model::MOI.ModelLike, config::Config) @test MOI.get(model, MOI.ListOfModelAttributesSet()) == [attr] return end - -""" - test_objective_incorrect_modifications(model::MOI.ModelLike, config::Config) - -Test that constraint sets cannot be set for the wrong set type, and that -VariableIndex functions cannot be modified. -""" -function test_objective_incorrect_modifications(model::MOI.ModelLike, ::Config) - @requires MOI.supports_constraint( - model, - MOI.ScalarAffineFunction{Float64}, - MOI.EqualTo{Float64}, - ) - x = MOI.add_variable(model) - c = MOI.add_constraint( - model, - MOI.ScalarAffineFunction([MOI.ScalarAffineTerm(1.0, x)], 0.0), - MOI.EqualTo(1.0), - ) - @test_throws( - ArgumentError, - MOI.set(model, MOI.ConstraintSet(), c, MOI.LessThan(1.0)), - ) - @test_throws(ArgumentError, MOI.set(model, MOI.ConstraintFunction(), c, x),) - return -end diff --git a/test/Bridges/Constraint/functionize.jl b/test/Bridges/Constraint/functionize.jl index 4db63d07ec..158b3651fa 100644 --- a/test/Bridges/Constraint/functionize.jl +++ b/test/Bridges/Constraint/functionize.jl @@ -27,8 +27,6 @@ function test_scalar_functionize() y = MOI.add_variable(bridged_mock) ci = MOI.add_constraint(bridged_mock, x, MOI.GreaterThan(0.0)) @test MOI.get(bridged_mock, MOI.ConstraintFunction(), ci) ≈ x - MOI.set(bridged_mock, MOI.ConstraintFunction(), ci, y) - @test MOI.get(bridged_mock, MOI.ConstraintFunction(), ci) ≈ y @test MOI.get(bridged_mock, MOI.ConstraintSet(), ci) == MOI.GreaterThan(0.0) MOI.set(bridged_mock, MOI.ConstraintSet(), ci, MOI.GreaterThan(1.0)) @test MOI.get(bridged_mock, MOI.ConstraintSet(), ci) == MOI.GreaterThan(1.0) diff --git a/test/Bridges/bridge_optimizer.jl b/test/Bridges/bridge_optimizer.jl index f9aa41b8ab..79036e32bd 100644 --- a/test/Bridges/bridge_optimizer.jl +++ b/test/Bridges/bridge_optimizer.jl @@ -748,6 +748,20 @@ function test_recursive_model_objective(::Type{T} = Int) where {T} @test MOI.get(b, attr) ≈ x end +function test_invalid_modifications() + model = MOI.Bridges.full_bridge_optimizer( + MOI.Utilities.Model{Float64}(), + Float64, + ) + config = MOI.Test.Config() + MOI.Test.test_modification_set_function_single_variable(model, config) + MOI.empty!(model) + MOI.Test.test_modification_incorrect(model, config) + MOI.empty!(model) + MOI.Test.test_modification_incorrect_VariableIndex(model, config) + return +end + function test_ListOfConstraintAttributesSet() model = MOI.Bridges.Constraint.SplitInterval{Float64}( MOI.Utilities.Model{Float64}(),