From 362544df594f78c830f8be8644bbf4c8525b0700 Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Tue, 9 Apr 2024 20:33:34 +1200 Subject: [PATCH] [Bridges] error on set(_, ::ConstraintSet with variable and constraint bridges (#2472) --- src/Bridges/bridge_optimizer.jl | 4 ++++ test/Bridges/bridge_optimizer.jl | 32 +++++++++++++++++++------------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/Bridges/bridge_optimizer.jl b/src/Bridges/bridge_optimizer.jl index d6ac7787f5..c0ac20bb46 100644 --- a/src/Bridges/bridge_optimizer.jl +++ b/src/Bridges/bridge_optimizer.jl @@ -1444,6 +1444,10 @@ function MOI.set( # mapped through the bridge substitution. This includes moving constants # into the set. if Variable.has_bridges(Variable.bridges(b)) + if is_bridged(b, ci) + # If `ci` is also ConstraintBridged, then we give up as the current code path is known to contain unresolved issues, see https://github.com/jump-dev/MathOptInterface.jl/issues/2452 + throw(MOI.SetAttributeNotAllowed(attr)) + end func = MOI.get(b, MOI.ConstraintFunction(), ci) # Updating the set will not modify the function, so we don't care about # the first argument. We only care about the new set. diff --git a/test/Bridges/bridge_optimizer.jl b/test/Bridges/bridge_optimizer.jl index cd2a227578..50b91fce24 100644 --- a/test/Bridges/bridge_optimizer.jl +++ b/test/Bridges/bridge_optimizer.jl @@ -1232,28 +1232,34 @@ function test_issue_2452_multiple_variable_bridges() index_map = MOI.copy_to(dest, src) set = MOI.get(dest, MOI.ConstraintSet(), index_map[c]) @test set == MOI.EqualTo(3.0) - MOI.set(dest, MOI.ConstraintSet(), index_map[c], set) - @test MOI.get(dest, MOI.ConstraintSet(), index_map[c]) == set - new_set = MOI.EqualTo(2.0) - MOI.set(dest, MOI.ConstraintSet(), index_map[c], new_set) - @test MOI.get(dest, MOI.ConstraintSet(), index_map[c]) == new_set + @test_throws( + MOI.SetAttributeNotAllowed, + MOI.set(dest, MOI.ConstraintSet(), index_map[c], set), + ) return end -function test_issue_2452() +function test_2452() + F, S = MOI.VectorAffineFunction{Float64}, MOI.Zeros src = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()) x = MOI.add_variable(src) MOI.add_constraint(src, x, MOI.GreaterThan(1.0)) - c = MOI.add_constraint(src, 2.0 * x, MOI.EqualTo(3.0)) + set = MOI.EqualTo(3.0) + c = MOI.add_constraint(src, 2.0 * x, set) dest = MOI.instantiate(Model2452{Float64}; with_bridge_type = Float64) index_map = MOI.copy_to(dest, src) - set = MOI.get(dest, MOI.ConstraintSet(), index_map[c]) - @test set == MOI.EqualTo(3.0) - MOI.set(dest, MOI.ConstraintSet(), index_map[c], set) + y = only(MOI.get(dest.model, MOI.ListOfVariableIndices())) + ci = only(MOI.get(dest.model, MOI.ListOfConstraintIndices{F,S}())) @test MOI.get(dest, MOI.ConstraintSet(), index_map[c]) == set - new_set = MOI.EqualTo(2.0) - MOI.set(dest, MOI.ConstraintSet(), index_map[c], new_set) - @test MOI.get(dest, MOI.ConstraintSet(), index_map[c]) == new_set + @test ≈( + MOI.get(dest.model, MOI.ConstraintFunction(), ci), + MOI.Utilities.operate(vcat, Float64, -1.0 + 2.0 * y), + ) + @test MOI.get(dest.model, MOI.ConstraintSet(), ci) == MOI.Zeros(1) + @test_throws( + MOI.SetAttributeNotAllowed, + MOI.set(dest, MOI.ConstraintSet(), index_map[c], set), + ) return end