From 9c0eb8a2ba9cdf4406f14b0ac8ce2424023abc9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Tue, 22 Apr 2025 12:10:49 +0200 Subject: [PATCH 1/8] Fix SetMapBridge with complex type --- src/Bridges/Constraint/set_map.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bridges/Constraint/set_map.jl b/src/Bridges/Constraint/set_map.jl index 52b0b587e4..f68787bcb5 100644 --- a/src/Bridges/Constraint/set_map.jl +++ b/src/Bridges/Constraint/set_map.jl @@ -51,7 +51,7 @@ function MOI.supports_constraint( ::Type{F}, ::Type{S1}, ) where {T,S1<:MOI.AbstractScalarSet,F<:MOI.AbstractScalarFunction} - return !MOI.Utilities.is_complex(F) + return MOI.Utilities.is_complex(F) == (T <: Complex) end function MOI.supports_constraint( @@ -59,7 +59,7 @@ function MOI.supports_constraint( ::Type{F}, ::Type{S1}, ) where {T,S1<:MOI.AbstractVectorSet,F<:MOI.AbstractVectorFunction} - return !MOI.Utilities.is_complex(F) + return MOI.Utilities.is_complex(F) == (T <: Complex) end function MOI.Bridges.added_constrained_variable_types( From 2eb6a65ff3105b5c46806286f28e254dc8c687fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Wed, 23 Apr 2025 23:51:08 +0200 Subject: [PATCH 2/8] Add tests --- src/Bridges/Bridges.jl | 7 ++--- .../AbstractFunctionConversionBridge.jl | 2 +- .../bridges/InequalityToComplementsBridge.jl | 2 +- .../Constraint/bridges/NormOneBridge.jl | 2 +- .../Constraint/bridges/SetDotScalingBridge.jl | 6 ++--- .../Constraint/bridges/VectorizeBridge.jl | 2 +- src/Bridges/Constraint/set_map.jl | 4 +-- .../Bridges/Constraint/SetDotScalingBridge.jl | 27 +++++++++++++++++++ test/Bridges/lazy_bridge_optimizer.jl | 9 +++++++ 9 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/Bridges/Bridges.jl b/src/Bridges/Bridges.jl index 9e742c8517..197068d51d 100644 --- a/src/Bridges/Bridges.jl +++ b/src/Bridges/Bridges.jl @@ -299,11 +299,12 @@ function _runtests( variable_start = 1.2, constraint_start = 1.2, eltype = Float64, + model_eltype = eltype, print_inner_model::Bool = false, cannot_unbridge::Bool = false, ) # Load model and bridge it - inner = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{eltype}()) + inner = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{model_eltype}()) model = _bridged_model(Bridge{eltype}, inner) input_fn(model) final_touch(model) @@ -313,7 +314,7 @@ function _runtests( print(inner) end Test.@testset "Test outer bridged model appears like the input" begin # COV_EXCL_LINE - test = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{eltype}()) + test = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{model_eltype}()) input_fn(test) _test_structural_identical( test, @@ -322,7 +323,7 @@ function _runtests( ) end Test.@testset "Test inner bridged model appears like the target" begin # COV_EXCL_LINE - target = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{eltype}()) + target = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{model_eltype}()) output_fn(target) _test_structural_identical(target, inner) end diff --git a/src/Bridges/Constraint/bridges/AbstractFunctionConversionBridge.jl b/src/Bridges/Constraint/bridges/AbstractFunctionConversionBridge.jl index d0b9b1ef78..020085427c 100644 --- a/src/Bridges/Constraint/bridges/AbstractFunctionConversionBridge.jl +++ b/src/Bridges/Constraint/bridges/AbstractFunctionConversionBridge.jl @@ -282,7 +282,7 @@ function MOI.supports_constraint( ::Type{G}, ::Type{<:MOI.AbstractSet}, ) where {T,F,G<:MOI.AbstractFunction} - return !MOI.Utilities.is_complex(G) && isfinite(conversion_cost(F, G)) + return MOI.Utilities.is_coefficient_type(G, T) && isfinite(conversion_cost(F, G)) end function concrete_bridge_type( diff --git a/src/Bridges/Constraint/bridges/InequalityToComplementsBridge.jl b/src/Bridges/Constraint/bridges/InequalityToComplementsBridge.jl index c0850f3bcb..abfce26da5 100644 --- a/src/Bridges/Constraint/bridges/InequalityToComplementsBridge.jl +++ b/src/Bridges/Constraint/bridges/InequalityToComplementsBridge.jl @@ -71,7 +71,7 @@ function MOI.supports_constraint( ::Type{F}, ::Type{<:Union{MOI.GreaterThan{T},MOI.LessThan{T},MOI.EqualTo{T}}}, ) where {T,F<:MOI.AbstractScalarFunction} - return !MOI.Utilities.is_complex(F) + return MOI.Utilities.is_coefficient_type(F, T) end function MOI.Bridges.added_constrained_variable_types( diff --git a/src/Bridges/Constraint/bridges/NormOneBridge.jl b/src/Bridges/Constraint/bridges/NormOneBridge.jl index 45872797a4..30a5dc4187 100644 --- a/src/Bridges/Constraint/bridges/NormOneBridge.jl +++ b/src/Bridges/Constraint/bridges/NormOneBridge.jl @@ -56,7 +56,7 @@ function MOI.supports_constraint( ::Type{F}, ::Type{MOI.NormOneCone}, ) where {T,F<:MOI.AbstractVectorFunction} - return !MOI.Utilities.is_complex(F) + return MOI.Utilities.is_coefficient_type(F, T) end function MOI.Bridges.added_constrained_variable_types(::Type{<:NormOneBridge}) diff --git a/src/Bridges/Constraint/bridges/SetDotScalingBridge.jl b/src/Bridges/Constraint/bridges/SetDotScalingBridge.jl index e778d4019b..233f7118b5 100644 --- a/src/Bridges/Constraint/bridges/SetDotScalingBridge.jl +++ b/src/Bridges/Constraint/bridges/SetDotScalingBridge.jl @@ -193,11 +193,11 @@ end # Since the set type is not defined, the default `MOI.supports_constraint` # for `SetMapBridge` does not work function MOI.supports_constraint( - ::Type{<:SetDotScalingBridge}, + ::Type{<:SetDotScalingBridge{T}}, F::Type{<:MOI.AbstractVectorFunction}, S::Type{<:MOI.AbstractVectorSet}, -) - return !MOI.Utilities.is_complex(F) && MOI.is_set_dot_scaled(S) +) where {T} + return MOI.Utilities.is_coefficient_type(F, T) && MOI.is_set_dot_scaled(S) end function MOI.supports_constraint( diff --git a/src/Bridges/Constraint/bridges/VectorizeBridge.jl b/src/Bridges/Constraint/bridges/VectorizeBridge.jl index ee7ae02d11..7d9f7a3601 100644 --- a/src/Bridges/Constraint/bridges/VectorizeBridge.jl +++ b/src/Bridges/Constraint/bridges/VectorizeBridge.jl @@ -64,7 +64,7 @@ function MOI.supports_constraint( ::Type{F}, ::Type{<:MOI.Utilities.ScalarLinearSet{T}}, ) where {T,F<:MOI.AbstractScalarFunction} - return !MOI.Utilities.is_complex(F) + return MOI.Utilities.is_coefficient_type(F, T) end function MOI.Bridges.added_constrained_variable_types(::Type{<:VectorizeBridge}) diff --git a/src/Bridges/Constraint/set_map.jl b/src/Bridges/Constraint/set_map.jl index f68787bcb5..fed3e8f0d7 100644 --- a/src/Bridges/Constraint/set_map.jl +++ b/src/Bridges/Constraint/set_map.jl @@ -51,7 +51,7 @@ function MOI.supports_constraint( ::Type{F}, ::Type{S1}, ) where {T,S1<:MOI.AbstractScalarSet,F<:MOI.AbstractScalarFunction} - return MOI.Utilities.is_complex(F) == (T <: Complex) + return MOI.Utilities.is_coefficient_type(F, T) end function MOI.supports_constraint( @@ -59,7 +59,7 @@ function MOI.supports_constraint( ::Type{F}, ::Type{S1}, ) where {T,S1<:MOI.AbstractVectorSet,F<:MOI.AbstractVectorFunction} - return MOI.Utilities.is_complex(F) == (T <: Complex) + return MOI.Utilities.is_coefficient_type(F, T) end function MOI.Bridges.added_constrained_variable_types( diff --git a/test/Bridges/Constraint/SetDotScalingBridge.jl b/test/Bridges/Constraint/SetDotScalingBridge.jl index 8147e1d113..db91463056 100644 --- a/test/Bridges/Constraint/SetDotScalingBridge.jl +++ b/test/Bridges/Constraint/SetDotScalingBridge.jl @@ -111,6 +111,33 @@ function test_inverse_scaling_quadratic() return end +function test_scaling_complex() + MOI.Bridges.runtests( + MOI.Bridges.Constraint.SetDotScalingBridge, + model -> begin + x, y, z = MOI.add_variables(model, 3) + MOI.add_constraint( + model, + MOI.Utilities.vectorize([(1.0 + 0im) * x, (1.0 * im) * y, (1.0 + 0im) * z]), + MOI.PositiveSemidefiniteConeTriangle(2), + ) + end, + model -> begin + x, y, z = MOI.add_variables(model, 3) + MOI.add_constraint( + model, + MOI.Utilities.vectorize([(1.0 + 0im) * x, (√2 * im) * y, (1.0 + 0im) * z]), + MOI.ScaledPositiveSemidefiniteConeTriangle(2), + ) + end, + eltype = ComplexF64, + model_eltype = Float64, + constraint_start = 1.2 * im + ) + return +end + + function test_set_dot_scaling_constraint_dual_start() inner = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()) model = MOI.Bridges.Constraint.SetDotScaling{Float64}(inner) diff --git a/test/Bridges/lazy_bridge_optimizer.jl b/test/Bridges/lazy_bridge_optimizer.jl index 696aff567d..8c3dea65d4 100644 --- a/test/Bridges/lazy_bridge_optimizer.jl +++ b/test/Bridges/lazy_bridge_optimizer.jl @@ -2253,6 +2253,15 @@ function test_issue_2696() return end +function test_wrong_coefficient() + model = MOI.instantiate(MOI.Utilities.Model{Float64}, with_bridge_type=Float64) + @test !MOI.supports_constraint(model, MOI.VectorAffineFunction{Int}, MOI.Nonnegatives) + @test !MOI.supports_constraint(model, MOI.VectorAffineFunction{Int}, MOI.PositiveSemidefiniteConeTriangle) + @test !MOI.supports_constraint(model, MOI.ScalarAffineFunction{Int}, MOI.EqualTo{Int}) + @test !MOI.supports_constraint(model, MOI.VectorQuadraticFunction{Int}, MOI.Zeros) + return +end + end # module TestBridgesLazyBridgeOptimizer.runtests() From 9930a3111f1cdd4c7fb6073e0b2bfb59528cc5e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Wed, 23 Apr 2025 23:51:46 +0200 Subject: [PATCH 3/8] Fix format --- .../AbstractFunctionConversionBridge.jl | 3 +- .../Bridges/Constraint/SetDotScalingBridge.jl | 15 +++++++--- test/Bridges/lazy_bridge_optimizer.jl | 29 +++++++++++++++---- 3 files changed, 37 insertions(+), 10 deletions(-) diff --git a/src/Bridges/Constraint/bridges/AbstractFunctionConversionBridge.jl b/src/Bridges/Constraint/bridges/AbstractFunctionConversionBridge.jl index 020085427c..6d91ffe695 100644 --- a/src/Bridges/Constraint/bridges/AbstractFunctionConversionBridge.jl +++ b/src/Bridges/Constraint/bridges/AbstractFunctionConversionBridge.jl @@ -282,7 +282,8 @@ function MOI.supports_constraint( ::Type{G}, ::Type{<:MOI.AbstractSet}, ) where {T,F,G<:MOI.AbstractFunction} - return MOI.Utilities.is_coefficient_type(G, T) && isfinite(conversion_cost(F, G)) + return MOI.Utilities.is_coefficient_type(G, T) && + isfinite(conversion_cost(F, G)) end function concrete_bridge_type( diff --git a/test/Bridges/Constraint/SetDotScalingBridge.jl b/test/Bridges/Constraint/SetDotScalingBridge.jl index db91463056..cec348aeb9 100644 --- a/test/Bridges/Constraint/SetDotScalingBridge.jl +++ b/test/Bridges/Constraint/SetDotScalingBridge.jl @@ -118,7 +118,11 @@ function test_scaling_complex() x, y, z = MOI.add_variables(model, 3) MOI.add_constraint( model, - MOI.Utilities.vectorize([(1.0 + 0im) * x, (1.0 * im) * y, (1.0 + 0im) * z]), + MOI.Utilities.vectorize([ + (1.0 + 0im) * x, + (1.0 * im) * y, + (1.0 + 0im) * z, + ]), MOI.PositiveSemidefiniteConeTriangle(2), ) end, @@ -126,18 +130,21 @@ function test_scaling_complex() x, y, z = MOI.add_variables(model, 3) MOI.add_constraint( model, - MOI.Utilities.vectorize([(1.0 + 0im) * x, (√2 * im) * y, (1.0 + 0im) * z]), + MOI.Utilities.vectorize([ + (1.0 + 0im) * x, + (√2 * im) * y, + (1.0 + 0im) * z, + ]), MOI.ScaledPositiveSemidefiniteConeTriangle(2), ) end, eltype = ComplexF64, model_eltype = Float64, - constraint_start = 1.2 * im + constraint_start = 1.2 * im, ) return end - function test_set_dot_scaling_constraint_dual_start() inner = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{Float64}()) model = MOI.Bridges.Constraint.SetDotScaling{Float64}(inner) diff --git a/test/Bridges/lazy_bridge_optimizer.jl b/test/Bridges/lazy_bridge_optimizer.jl index 8c3dea65d4..ca8cee0eb1 100644 --- a/test/Bridges/lazy_bridge_optimizer.jl +++ b/test/Bridges/lazy_bridge_optimizer.jl @@ -2254,11 +2254,30 @@ function test_issue_2696() end function test_wrong_coefficient() - model = MOI.instantiate(MOI.Utilities.Model{Float64}, with_bridge_type=Float64) - @test !MOI.supports_constraint(model, MOI.VectorAffineFunction{Int}, MOI.Nonnegatives) - @test !MOI.supports_constraint(model, MOI.VectorAffineFunction{Int}, MOI.PositiveSemidefiniteConeTriangle) - @test !MOI.supports_constraint(model, MOI.ScalarAffineFunction{Int}, MOI.EqualTo{Int}) - @test !MOI.supports_constraint(model, MOI.VectorQuadraticFunction{Int}, MOI.Zeros) + model = MOI.instantiate( + MOI.Utilities.Model{Float64}, + with_bridge_type = Float64, + ) + @test !MOI.supports_constraint( + model, + MOI.VectorAffineFunction{Int}, + MOI.Nonnegatives, + ) + @test !MOI.supports_constraint( + model, + MOI.VectorAffineFunction{Int}, + MOI.PositiveSemidefiniteConeTriangle, + ) + @test !MOI.supports_constraint( + model, + MOI.ScalarAffineFunction{Int}, + MOI.EqualTo{Int}, + ) + @test !MOI.supports_constraint( + model, + MOI.VectorQuadraticFunction{Int}, + MOI.Zeros, + ) return end From 0302a5656980964f616bc0111bb5993f63573c92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Wed, 23 Apr 2025 23:54:05 +0200 Subject: [PATCH 4/8] Fix format --- src/Bridges/Bridges.jl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Bridges/Bridges.jl b/src/Bridges/Bridges.jl index 197068d51d..91f8beff9a 100644 --- a/src/Bridges/Bridges.jl +++ b/src/Bridges/Bridges.jl @@ -314,7 +314,8 @@ function _runtests( print(inner) end Test.@testset "Test outer bridged model appears like the input" begin # COV_EXCL_LINE - test = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{model_eltype}()) + test = + MOI.Utilities.UniversalFallback(MOI.Utilities.Model{model_eltype}()) input_fn(test) _test_structural_identical( test, @@ -323,7 +324,8 @@ function _runtests( ) end Test.@testset "Test inner bridged model appears like the target" begin # COV_EXCL_LINE - target = MOI.Utilities.UniversalFallback(MOI.Utilities.Model{model_eltype}()) + target = + MOI.Utilities.UniversalFallback(MOI.Utilities.Model{model_eltype}()) output_fn(target) _test_structural_identical(target, inner) end From 8de2d9d5f697f638ebfdde3ca9016a0365f88be4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 24 Apr 2025 08:34:03 +0200 Subject: [PATCH 5/8] Disallow complex for InequalityToComplementsBridge --- src/Bridges/Constraint/bridges/InequalityToComplementsBridge.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bridges/Constraint/bridges/InequalityToComplementsBridge.jl b/src/Bridges/Constraint/bridges/InequalityToComplementsBridge.jl index abfce26da5..f514886615 100644 --- a/src/Bridges/Constraint/bridges/InequalityToComplementsBridge.jl +++ b/src/Bridges/Constraint/bridges/InequalityToComplementsBridge.jl @@ -71,7 +71,7 @@ function MOI.supports_constraint( ::Type{F}, ::Type{<:Union{MOI.GreaterThan{T},MOI.LessThan{T},MOI.EqualTo{T}}}, ) where {T,F<:MOI.AbstractScalarFunction} - return MOI.Utilities.is_coefficient_type(F, T) + return MOI.Utilities.is_coefficient_type(F, T) && !MOI.Utilities.is_complex(F) end function MOI.Bridges.added_constrained_variable_types( From a5e9cc96cd15b791044b7b47f2852ea026b0a6ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Thu, 24 Apr 2025 22:57:18 +0200 Subject: [PATCH 6/8] Fix format --- .../Constraint/bridges/InequalityToComplementsBridge.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Bridges/Constraint/bridges/InequalityToComplementsBridge.jl b/src/Bridges/Constraint/bridges/InequalityToComplementsBridge.jl index f514886615..db82ca9afb 100644 --- a/src/Bridges/Constraint/bridges/InequalityToComplementsBridge.jl +++ b/src/Bridges/Constraint/bridges/InequalityToComplementsBridge.jl @@ -71,7 +71,8 @@ function MOI.supports_constraint( ::Type{F}, ::Type{<:Union{MOI.GreaterThan{T},MOI.LessThan{T},MOI.EqualTo{T}}}, ) where {T,F<:MOI.AbstractScalarFunction} - return MOI.Utilities.is_coefficient_type(F, T) && !MOI.Utilities.is_complex(F) + return MOI.Utilities.is_coefficient_type(F, T) && + !MOI.Utilities.is_complex(F) end function MOI.Bridges.added_constrained_variable_types( From ac01457336e668aacc54607ff60ff1d093de7ce9 Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Mon, 28 Apr 2025 11:17:29 +1200 Subject: [PATCH 7/8] Update src/Bridges/Constraint/bridges/NormOneBridge.jl --- src/Bridges/Constraint/bridges/NormOneBridge.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Bridges/Constraint/bridges/NormOneBridge.jl b/src/Bridges/Constraint/bridges/NormOneBridge.jl index 30a5dc4187..b01a9688d9 100644 --- a/src/Bridges/Constraint/bridges/NormOneBridge.jl +++ b/src/Bridges/Constraint/bridges/NormOneBridge.jl @@ -56,7 +56,8 @@ function MOI.supports_constraint( ::Type{F}, ::Type{MOI.NormOneCone}, ) where {T,F<:MOI.AbstractVectorFunction} - return MOI.Utilities.is_coefficient_type(F, T) + return MOI.Utilities.is_coefficient_type(F, T) && + !MOI.Utilities.is_complex(F) end function MOI.Bridges.added_constrained_variable_types(::Type{<:NormOneBridge}) From fbb4128ad74fb7f6aa6c3cf08b0dd2e4b408befb Mon Sep 17 00:00:00 2001 From: Oscar Dowson Date: Mon, 28 Apr 2025 11:24:05 +1200 Subject: [PATCH 8/8] Update src/Bridges/Constraint/bridges/NormOneBridge.jl --- src/Bridges/Constraint/bridges/NormOneBridge.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bridges/Constraint/bridges/NormOneBridge.jl b/src/Bridges/Constraint/bridges/NormOneBridge.jl index b01a9688d9..e0221d5105 100644 --- a/src/Bridges/Constraint/bridges/NormOneBridge.jl +++ b/src/Bridges/Constraint/bridges/NormOneBridge.jl @@ -57,7 +57,7 @@ function MOI.supports_constraint( ::Type{MOI.NormOneCone}, ) where {T,F<:MOI.AbstractVectorFunction} return MOI.Utilities.is_coefficient_type(F, T) && - !MOI.Utilities.is_complex(F) + !MOI.Utilities.is_complex(F) end function MOI.Bridges.added_constrained_variable_types(::Type{<:NormOneBridge})