diff --git a/src/Bridges/Constraint/bridges/vectorize.jl b/src/Bridges/Constraint/bridges/vectorize.jl index cbf572759a..9f60285e28 100644 --- a/src/Bridges/Constraint/bridges/vectorize.jl +++ b/src/Bridges/Constraint/bridges/vectorize.jl @@ -64,6 +64,14 @@ function MOI.supports_constraint( return true end +function MOI.supports_constraint( + ::Type{VectorizeBridge{T}}, + ::Type{MOI.ScalarNonlinearFunction}, + ::Type{<:MOI.Utilities.ScalarLinearSet{T}}, +) where {T} + return false +end + function MOI.Bridges.added_constrained_variable_types(::Type{<:VectorizeBridge}) return Tuple{Type}[] end diff --git a/src/Utilities/functions.jl b/src/Utilities/functions.jl index 4946acdf67..6c2b92d4d5 100644 --- a/src/Utilities/functions.jl +++ b/src/Utilities/functions.jl @@ -1817,28 +1817,56 @@ end ### ScalarNonlinearFunction function promote_operation( - ::typeof(-), - ::Type{T}, + ::Union{typeof(+),typeof(-)}, + ::Type{<:Number}, ::Type{MOI.ScalarNonlinearFunction}, +) + return MOI.ScalarNonlinearFunction +end + +function operate( + ::typeof(-), ::Type{T}, + f::MOI.ScalarNonlinearFunction, ) where {T} - return MOI.ScalarNonlinearFunction + if f.head == :- && length(f.args) == 1 + # A simplification for -(-(f)) into f, but only if f is an SNF. + if f.args[1] isa MOI.ScalarNonlinearFunction + return f.args[1] + end + end + return MOI.ScalarNonlinearFunction(:-, Any[f]) end function promote_operation( - ::typeof(-), + ::Union{typeof(+),typeof(-),typeof(*),typeof(/)}, ::Type{T}, ::Type{MOI.ScalarNonlinearFunction}, - ::Type{MOI.VariableIndex}, -) where {T} + ::Type{S}, +) where { + T<:Number, + S<:Union{ + T, + MOI.VariableIndex, + MOI.ScalarAffineFunction{T}, + MOI.ScalarQuadraticFunction{T}, + MOI.ScalarNonlinearFunction, + }, +} return MOI.ScalarNonlinearFunction end function operate( - op::Union{typeof(+),typeof(-)}, + op::Union{typeof(+),typeof(-),typeof(*),typeof(/)}, ::Type{T}, f::MOI.ScalarNonlinearFunction, - g::ScalarQuadraticLike{T}, + g::Union{ + T, + MOI.VariableIndex, + MOI.ScalarAffineFunction{T}, + MOI.ScalarQuadraticFunction{T}, + MOI.ScalarNonlinearFunction, + }, ) where {T} return MOI.ScalarNonlinearFunction(Symbol(op), Any[f, g]) end diff --git a/test/Bridges/Constraint/flip_sign.jl b/test/Bridges/Constraint/flip_sign.jl index 167c594f1f..9aaaa18cf2 100644 --- a/test/Bridges/Constraint/flip_sign.jl +++ b/test/Bridges/Constraint/flip_sign.jl @@ -337,6 +337,17 @@ function test_runtests() -1.5 * x <= -1.0 """, ) + MOI.Bridges.runtests( + MOI.Bridges.Constraint.GreaterToLessBridge, + """ + variables: x + ScalarNonlinearFunction(1.5 * x) >= 1.0 + """, + """ + variables: x + ScalarNonlinearFunction(-(1.5 * x)) <= -1.0 + """, + ) MOI.Bridges.runtests( MOI.Bridges.Constraint.LessToGreaterBridge, """ @@ -359,6 +370,17 @@ function test_runtests() -1.5 * x >= -1.0 """, ) + MOI.Bridges.runtests( + MOI.Bridges.Constraint.LessToGreaterBridge, + """ + variables: x + ScalarNonlinearFunction(1.5 * x) <= 1.0 + """, + """ + variables: x + ScalarNonlinearFunction(-(1.5 * x)) >= -1.0 + """, + ) MOI.Bridges.runtests( MOI.Bridges.Constraint.NonnegToNonposBridge, """ diff --git a/test/Bridges/Constraint/vectorize.jl b/test/Bridges/Constraint/vectorize.jl index 79c17546d9..e51e6cb398 100644 --- a/test/Bridges/Constraint/vectorize.jl +++ b/test/Bridges/Constraint/vectorize.jl @@ -238,6 +238,28 @@ function test_runtests() return end +MOI.Utilities.@model( + Model2179, + (), + (MOI.GreaterThan, MOI.LessThan), + (), + (), + (), + (MOI.ScalarAffineFunction,), + (), + () +) + +function test_unsupported_ScalarNonlinearFunction() + model = MOI.instantiate(Model2179{Float64}; with_bridge_type = Float64) + MOI.supports_constraint( + model, + MOI.ScalarNonlinearFunction, + MOI.GreaterThan{Float64}, + ) + return +end + end # module TestConstraintVectorize.runtests()