diff --git a/src/MOI_wrapper.jl b/src/MOI_wrapper.jl index 7d72ae00..c41d7374 100644 --- a/src/MOI_wrapper.jl +++ b/src/MOI_wrapper.jl @@ -601,6 +601,16 @@ function MOI.supports_constraint( ) end +function MOI.get( + model::Optimizer{T}, + ::MOI.ConstraintBridgingCost{MOI.ScalarQuadraticFunction{T},S}, +) where {T,S<:MOI.AbstractSet} + return MOI.get( + model.optimizer, + MOI.ConstraintBridgingCost{MOI.ScalarAffineFunction{T},S}(), + ) +end + function MOI.supports_constraint( model::Optimizer, ::Type{MOI.VectorQuadraticFunction{T}}, @@ -613,6 +623,16 @@ function MOI.supports_constraint( ) end +function MOI.get( + model::Optimizer{T}, + ::MOI.ConstraintBridgingCost{MOI.VectorQuadraticFunction{T},S}, +) where {T,S<:MOI.AbstractSet} + return MOI.get( + model.optimizer, + MOI.ConstraintBridgingCost{MOI.VectorAffineFunction{T},S}(), + ) +end + function MOI.supports( model::Optimizer, attr::MOI.ConstraintName, diff --git a/test/test_MathOptInterface.jl b/test/test_MathOptInterface.jl index c82dc0e1..3995f025 100644 --- a/test/test_MathOptInterface.jl +++ b/test/test_MathOptInterface.jl @@ -2111,6 +2111,47 @@ function test_constrained_variables() return end +function test_constraint_bridging_cost_quadratic() + # POI rewrites `Vector/ScalarQuadraticFunction` constraints into their + # affine counterparts at solve time, so `supports_constraint` for the + # quadratic variant delegates to the affine one. `ConstraintBridgingCost` + # must do the same: otherwise `LazyBridgeOptimizer` sees + # `supports = true, cost = Inf` and treats the node as unreachable when + # building the bridge graph. + optimizer = POI.Optimizer(SCS.Optimizer) + for S in (MOI.Zeros, MOI.Nonnegatives, MOI.SecondOrderCone) + @test MOI.supports_constraint( + optimizer, + MOI.VectorQuadraticFunction{Float64}, + S, + ) + @test MOI.get( + optimizer, + MOI.ConstraintBridgingCost{MOI.VectorQuadraticFunction{Float64},S}(), + ) == MOI.get( + optimizer, + MOI.ConstraintBridgingCost{MOI.VectorAffineFunction{Float64},S}(), + ) + end + optimizer = POI.Optimizer(HiGHS.Optimizer) + for S in + (MOI.LessThan{Float64}, MOI.GreaterThan{Float64}, MOI.EqualTo{Float64}) + @test MOI.supports_constraint( + optimizer, + MOI.ScalarQuadraticFunction{Float64}, + S, + ) + @test MOI.get( + optimizer, + MOI.ConstraintBridgingCost{MOI.ScalarQuadraticFunction{Float64},S}(), + ) == MOI.get( + optimizer, + MOI.ConstraintBridgingCost{MOI.ScalarAffineFunction{Float64},S}(), + ) + end + return +end + function test_parameter_index_error() model = POI.Optimizer(MOI.Utilities.Model{Float64}()) POI._add_variable(model, MOI.VariableIndex(1))