From 115778d3006852de0f4a861f7a0fe07c911e8dbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Tue, 15 Apr 2025 16:14:00 +0200 Subject: [PATCH 01/10] Add bridge from Hermitian PSD to complex function in Symmetric PSD --- .../HermitianToComplexSymmetricBridge.jl | 161 ++++++++++++++++++ 1 file changed, 161 insertions(+) create mode 100644 src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl diff --git a/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl b/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl new file mode 100644 index 0000000000..6a1c1ba501 --- /dev/null +++ b/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl @@ -0,0 +1,161 @@ +# Copyright (c) 2017: Miles Lubin and contributors +# Copyright (c) 2017: Google Inc. +# +# Use of this source code is governed by an MIT-style license that can be found +# in the LICENSE.md file or at https://opensource.org/licenses/MIT. + +""" + HermitianToComplexSymmetricBridge{T,F,G} <: Bridges.Constraint.AbstractBridge + +`HermitianToSymmetricBridge` implements the following reformulation: + + * Hermitian positive semidefinite `n x n` represented as a vector of real + entries with real and imaginary parts on different entries to a vector + of complex entries. + +See also [`MOI.Bridges.Constraint.HermitianToSymmetricPSDBridge`](@ref). + +## Source node + +`HermitianToComplexSymmetricBridge` supports: + + * `G` in [`MOI.HermitianPositiveSemidefiniteConeTriangle`](@ref) + +## Target node + +`HermitianToComplexSymmetricBridge` creates: + + * `F` in [`MOI.PositiveSemidefiniteConeTriangle`](@ref) + +## Reformulation + +The reformulation is best described by example. + +The Hermitian matrix: +```math +\\begin{bmatrix} + x_{11} & x_{12} + y_{12}im & x_{13} + y_{13}im\\\\ + x_{12} - y_{12}im & x_{22} & x_{23} + y_{23}im\\\\ + x_{13} - y_{13}im & x_{23} - y_{23}im & x_{33} +\\end{bmatrix} +``` +is positive semidefinite if and only if the symmetric matrix: +```math +\\begin{bmatrix} + x_{11} & x_{12} & x_{13} & 0 & y_{12} & y_{13} \\\\ + & x_{22} & x_{23} & -y_{12} & 0 & y_{23} \\\\ + & & x_{33} & -y_{13} & -y_{23} & 0 \\\\ + & & & x_{11} & x_{12} & x_{13} \\\\ + & & & & x_{22} & x_{23} \\\\ + & & & & & x_{33} +\\end{bmatrix} +``` +is positive semidefinite. + +The bridge achieves this reformulation by constraining the above matrix to +belong to the `MOI.PositiveSemidefiniteConeTriangle(6)`. +""" +struct HermitianToComplexSymmetricBridge{T,F,G} <: SetMapBridge{ + T, + MOI.PositiveSemidefiniteConeTriangle, + MOI.HermitianPositiveSemidefiniteConeTriangle, + F, + G, +} + constraint::MOI.ConstraintIndex{F,MOI.PositiveSemidefiniteConeTriangle} +end + +# Should be favored over `HermitianToSymmetricPSDBridge` +MOI.Bridges.bridging_cost(::Type{<:SOCtoPSDBridge}) = 0.5 + +function _promote_complex_vcat(::Type{T}, ::Type{G}) where {T,G} + S = MOI.Utilities.scalar_type(G) + M = MOI.Utilities.promote_operation(*, Complex{T}, S) + return MOI.Utilities.promote_operation(vcat, T, M) +end + +function concrete_bridge_type( + ::Type{<:HermitianToComplexSymmetricBridge{T}}, + G::Type{<:MOI.AbstractVectorFunction}, + ::Type{MOI.HermitianPositiveSemidefiniteConeTriangle}, +) where {T} + F = _promote_complex_vcat(T, G) + return HermitianToComplexSymmetricBridge{T,F,G} +end + +function MOI.Bridges.map_set( + ::Type{<:HermitianToComplexSymmetricBridge}, + set::MOI.HermitianPositiveSemidefiniteConeTriangle, +) + return MOI.PositiveSemidefiniteConeTriangle(set.side_dimension) +end + +function MOI.Bridges.inverse_map_set( + ::Type{<:HermitianToComplexSymmetricBridge}, + set::MOI.PositiveSemidefiniteConeTriangle, +) + return MOI.HermitianPositiveSemidefiniteConeTriangle(set.side_dimension) +end + +function MOI.Bridges.map_function( + ::Type{<:HermitianToComplexSymmetricBridge{T}}, + func, +) where {T} + complex_scalars = MOI.Utilities.eachscalar(func) + S = MOI.Utilities.scalar_type(_promote_complex_vcat(T, typeof(func))) + complex_dim = length(complex_scalars) + complex_set = MOI.Utilities.set_with_dimension( + MOI.HermitianPositiveSemidefiniteConeTriangle, + complex_dim, + ) + n = complex_set.side_dimension + real_set = MOI.PositiveSemidefiniteConeTriangle(n) + real_dim = MOI.dimension(real_set) + real_scalars = Vector{S}(undef, real_dim) + real_index = 0 + imag_index = real_dim + for j in 1:n + for i in 1:j + real_index += 1 + if i == j + real_scalars[real_index] = complex_scalars[real_index] + else + imag_index += 1 + real_scalars[real_index] = complex_scalars[real_index] + (one(T) * im) * complex_scalars[imag_index] + end + end + end + @assert length(real_scalars) == real_index + @assert length(complex_scalars) == imag_index + return MOI.Utilities.vectorize(real_scalars) +end + +function MOI.Bridges.inverse_map_function( + ::Type{<:HermitianToComplexSymmetricBridge}, + func, +) + real_scalars = MOI.Utilities.eachscalar(func) + real_set = MOI.Utilities.set_with_dimension( + MOI.PositiveSemidefiniteConeTriangle, + length(real_scalars), + ) + n = real_set.side_dimension + complex_set = MOI.HermitianPositiveSemidefiniteConeTriangle(n) + complex_scalars = + Vector{MA.promote_operation(real, MOI.Utilities.scalar_type(typeof(func)))}(undef, MOI.dimension(complex_set)) + real_index = 0 + imag_index = MOI.dimension(real_set) + for j in 1:n + for i in 1:j + real_index += 1 + complex_scalars[real_index] = real(real_scalars[real_index]) + if i != j + imag_index += 1 + complex_scalars[imag_index] = imag(real_scalars[real_index]) + end + end + end + @assert length(real_scalars) == real_index + @assert length(complex_scalars) == imag_index + return MOI.Utilities.vectorize(complex_scalars) +end From f9769fa2b5fa094daf123b84bd4d9f31b574e2c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Tue, 15 Apr 2025 16:16:00 +0200 Subject: [PATCH 02/10] Fix docstring --- .../HermitianToComplexSymmetricBridge.jl | 29 ++----------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl b/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl index 6a1c1ba501..418ff88e35 100644 --- a/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl +++ b/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl @@ -27,33 +27,8 @@ See also [`MOI.Bridges.Constraint.HermitianToSymmetricPSDBridge`](@ref). * `F` in [`MOI.PositiveSemidefiniteConeTriangle`](@ref) -## Reformulation - -The reformulation is best described by example. - -The Hermitian matrix: -```math -\\begin{bmatrix} - x_{11} & x_{12} + y_{12}im & x_{13} + y_{13}im\\\\ - x_{12} - y_{12}im & x_{22} & x_{23} + y_{23}im\\\\ - x_{13} - y_{13}im & x_{23} - y_{23}im & x_{33} -\\end{bmatrix} -``` -is positive semidefinite if and only if the symmetric matrix: -```math -\\begin{bmatrix} - x_{11} & x_{12} & x_{13} & 0 & y_{12} & y_{13} \\\\ - & x_{22} & x_{23} & -y_{12} & 0 & y_{23} \\\\ - & & x_{33} & -y_{13} & -y_{23} & 0 \\\\ - & & & x_{11} & x_{12} & x_{13} \\\\ - & & & & x_{22} & x_{23} \\\\ - & & & & & x_{33} -\\end{bmatrix} -``` -is positive semidefinite. - -The bridge achieves this reformulation by constraining the above matrix to -belong to the `MOI.PositiveSemidefiniteConeTriangle(6)`. +Note that if `G` is `MOI.VectorAffineFunction{T}` then `F` will be +`MOI.VectorAffineFunction{Complex{T}}` """ struct HermitianToComplexSymmetricBridge{T,F,G} <: SetMapBridge{ T, From fa03e54b34f8a9660172645f39d28896812df322 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Tue, 15 Apr 2025 16:18:34 +0200 Subject: [PATCH 03/10] Add to add_all_bridges --- src/Bridges/Constraint/Constraint.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Bridges/Constraint/Constraint.jl b/src/Bridges/Constraint/Constraint.jl index 859e0ef766..197e1e5bfe 100644 --- a/src/Bridges/Constraint/Constraint.jl +++ b/src/Bridges/Constraint/Constraint.jl @@ -56,6 +56,7 @@ function add_all_bridges(model, ::Type{T}) where {T} end MOI.Bridges.add_bridge(model, GreaterToLessBridge{T}) MOI.Bridges.add_bridge(model, HermitianToSymmetricPSDBridge{T}) + MOI.Bridges.add_bridge(model, HermitianToComplexSymmetricBridge{T}) MOI.Bridges.add_bridge(model, IndicatorActiveOnFalseBridge{T}) MOI.Bridges.add_bridge(model, IndicatorGreaterToLessThanBridge{T}) MOI.Bridges.add_bridge(model, IndicatorLessToGreaterThanBridge{T}) From c9a8d47af369a1a68ce60371ec9f97ea7e9a8026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Tue, 15 Apr 2025 16:19:03 +0200 Subject: [PATCH 04/10] Fix format --- .../bridges/HermitianToComplexSymmetricBridge.jl | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl b/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl index 418ff88e35..ad72bb8ec9 100644 --- a/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl +++ b/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl @@ -96,7 +96,9 @@ function MOI.Bridges.map_function( real_scalars[real_index] = complex_scalars[real_index] else imag_index += 1 - real_scalars[real_index] = complex_scalars[real_index] + (one(T) * im) * complex_scalars[imag_index] + real_scalars[real_index] = + complex_scalars[real_index] + + (one(T) * im) * complex_scalars[imag_index] end end end @@ -116,8 +118,12 @@ function MOI.Bridges.inverse_map_function( ) n = real_set.side_dimension complex_set = MOI.HermitianPositiveSemidefiniteConeTriangle(n) - complex_scalars = - Vector{MA.promote_operation(real, MOI.Utilities.scalar_type(typeof(func)))}(undef, MOI.dimension(complex_set)) + complex_scalars = Vector{ + MA.promote_operation(real, MOI.Utilities.scalar_type(typeof(func))), + }( + undef, + MOI.dimension(complex_set), + ) real_index = 0 imag_index = MOI.dimension(real_set) for j in 1:n From 92c5707a86f5f72d36d65da4c3b83c87ca21f704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Tue, 15 Apr 2025 16:21:50 +0200 Subject: [PATCH 05/10] Fix --- .../Constraint/bridges/HermitianToComplexSymmetricBridge.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl b/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl index ad72bb8ec9..5eab4172de 100644 --- a/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl +++ b/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl @@ -41,7 +41,7 @@ struct HermitianToComplexSymmetricBridge{T,F,G} <: SetMapBridge{ end # Should be favored over `HermitianToSymmetricPSDBridge` -MOI.Bridges.bridging_cost(::Type{<:SOCtoPSDBridge}) = 0.5 +MOI.Bridges.bridging_cost(::Type{<:HermitianToComplexSymmetricBridge}) = 0.5 function _promote_complex_vcat(::Type{T}, ::Type{G}) where {T,G} S = MOI.Utilities.scalar_type(G) From f2e2b7c67e1e1a03e3cdea1f9b5bec296d9a348e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Tue, 15 Apr 2025 17:15:05 +0200 Subject: [PATCH 06/10] Add tests --- .../HermitianToComplexSymmetricBridge.jl | 14 ++++-- .../HermitianToComplexSymmetricBridge.jl | 49 +++++++++++++++++++ 2 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 test/Bridges/Constraint/HermitianToComplexSymmetricBridge.jl diff --git a/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl b/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl index 5eab4172de..7154202ac7 100644 --- a/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl +++ b/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl @@ -43,10 +43,16 @@ end # Should be favored over `HermitianToSymmetricPSDBridge` MOI.Bridges.bridging_cost(::Type{<:HermitianToComplexSymmetricBridge}) = 0.5 -function _promote_complex_vcat(::Type{T}, ::Type{G}) where {T,G} +function _promote_complex_vcat(::Type{T}, ::Type{G}) where {T<:Real,G} S = MOI.Utilities.scalar_type(G) - M = MOI.Utilities.promote_operation(*, Complex{T}, S) - return MOI.Utilities.promote_operation(vcat, T, M) + if S === T + M = Complex{T} + elseif S <: MOI.Utilities.TypedLike{T} + M = MOI.Utilities.similar_type(S, Complex{T}) + else + M = MOI.Utilities.promote_operation(*, Complex{T}, Complex{T}, S) + end + return MOI.Utilities.promote_operation(vcat, Complex{T}, M) end function concrete_bridge_type( @@ -97,7 +103,7 @@ function MOI.Bridges.map_function( else imag_index += 1 real_scalars[real_index] = - complex_scalars[real_index] + + one(Complex{T}) * complex_scalars[real_index] + (one(T) * im) * complex_scalars[imag_index] end end diff --git a/test/Bridges/Constraint/HermitianToComplexSymmetricBridge.jl b/test/Bridges/Constraint/HermitianToComplexSymmetricBridge.jl new file mode 100644 index 0000000000..249fbe8ca6 --- /dev/null +++ b/test/Bridges/Constraint/HermitianToComplexSymmetricBridge.jl @@ -0,0 +1,49 @@ +# Copyright (c) 2017: Miles Lubin and contributors +# Copyright (c) 2017: Google Inc. +# +# Use of this source code is governed by an MIT-style license that can be found +# in the LICENSE.md file or at https://opensource.org/licenses/MIT. + +module TestConstraintHermitianToComplexSymmetric + +using Test + +import MathOptInterface as MOI + +function runtests() + for name in names(@__MODULE__; all = true) + if startswith("$(name)", "test_") + @testset "$(name)" begin + getfield(@__MODULE__, name)() + end + end + end + return +end + +function test_dimension_2() + MOI.Bridges.runtests( + MOI.Bridges.Constraint.HermitianToComplexSymmetricBridge, + model -> begin + a, b, c = MOI.add_variables(model, 3) + MOI.add_constraint( + model, + MOI.Utilities.vectorize([1.0 * a + 2.0 * b, 3.0 * c, 4.0 * b, 5.0 * a]), + MOI.HermitianPositiveSemidefiniteConeTriangle(2), + ) + end, + model -> begin + a, b, c = MOI.add_variables(model, 3) + MOI.add_constraint( + model, + MOI.Utilities.vectorize([Complex(1.0) * a + Complex(2.0) * b, Complex(3.0) * c + 5.0 * im * a, Complex(4.0) * b]), + MOI.PositiveSemidefiniteConeTriangle(2), + ) + end, + ) + return +end + +end # module + +TestConstraintHermitianToComplexSymmetric.runtests() From 9400ab5401818f4c1eab7e4e69f49ea8f41dd511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Tue, 15 Apr 2025 17:27:56 +0200 Subject: [PATCH 07/10] Add adjoint --- .../bridges/HermitianToComplexSymmetricBridge.jl | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl b/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl index 7154202ac7..b63fe0c4d8 100644 --- a/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl +++ b/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl @@ -113,6 +113,13 @@ function MOI.Bridges.map_function( return MOI.Utilities.vectorize(real_scalars) end +function MOI.Bridges.inverse_adjoint_map_function( + BT::Type{<:HermitianToComplexSymmetricBridge}, + func, +) + return MOI.Bridges.map_function(BT, func) +end + function MOI.Bridges.inverse_map_function( ::Type{<:HermitianToComplexSymmetricBridge}, func, @@ -146,3 +153,10 @@ function MOI.Bridges.inverse_map_function( @assert length(complex_scalars) == imag_index return MOI.Utilities.vectorize(complex_scalars) end + +function MOI.Bridges.adjoint_map_function( + BT::Type{<:HermitianToComplexSymmetricBridge}, + func, +) + return MOI.Bridges.inverse_map_function(BT, func) +end From 19917ef5901dc1ef6100ffbb05bf96b863540b56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Tue, 15 Apr 2025 17:34:31 +0200 Subject: [PATCH 08/10] Add test --- .../bridges/HermitianToSymmetricPSDBridge.jl | 2 +- .../HermitianToComplexSymmetricBridge.jl | 43 ++++++++++++++++++- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/src/Bridges/Constraint/bridges/HermitianToSymmetricPSDBridge.jl b/src/Bridges/Constraint/bridges/HermitianToSymmetricPSDBridge.jl index 0283e29845..81ad558682 100644 --- a/src/Bridges/Constraint/bridges/HermitianToSymmetricPSDBridge.jl +++ b/src/Bridges/Constraint/bridges/HermitianToSymmetricPSDBridge.jl @@ -153,7 +153,7 @@ function MOI.Bridges.map_function( end function MOI.Bridges.inverse_map_function( - BT::Type{<:HermitianToSymmetricPSDBridge}, + ::Type{<:HermitianToSymmetricPSDBridge}, func, ) real_scalars = MOI.Utilities.eachscalar(func) diff --git a/test/Bridges/Constraint/HermitianToComplexSymmetricBridge.jl b/test/Bridges/Constraint/HermitianToComplexSymmetricBridge.jl index 249fbe8ca6..0a02e1574a 100644 --- a/test/Bridges/Constraint/HermitianToComplexSymmetricBridge.jl +++ b/test/Bridges/Constraint/HermitianToComplexSymmetricBridge.jl @@ -28,7 +28,12 @@ function test_dimension_2() a, b, c = MOI.add_variables(model, 3) MOI.add_constraint( model, - MOI.Utilities.vectorize([1.0 * a + 2.0 * b, 3.0 * c, 4.0 * b, 5.0 * a]), + MOI.Utilities.vectorize([ + 1.0 * a + 2.0 * b, + 3.0 * c, + 4.0 * b, + 5.0 * a, + ]), MOI.HermitianPositiveSemidefiniteConeTriangle(2), ) end, @@ -36,7 +41,11 @@ function test_dimension_2() a, b, c = MOI.add_variables(model, 3) MOI.add_constraint( model, - MOI.Utilities.vectorize([Complex(1.0) * a + Complex(2.0) * b, Complex(3.0) * c + 5.0 * im * a, Complex(4.0) * b]), + MOI.Utilities.vectorize([ + Complex(1.0) * a + Complex(2.0) * b, + Complex(3.0) * c + 5.0 * im * a, + Complex(4.0) * b, + ]), MOI.PositiveSemidefiniteConeTriangle(2), ) end, @@ -44,6 +53,36 @@ function test_dimension_2() return end +function test_dimension_3() + MOI.Bridges.runtests( + MOI.Bridges.Constraint.HermitianToComplexSymmetricBridge, + model -> begin + x = MOI.add_variables(model, 9) + MOI.add_constraint( + model, + MOI.VectorOfVariables(x), + MOI.HermitianPositiveSemidefiniteConeTriangle(3), + ) + end, + model -> begin + x = MOI.add_variables(model, 9) + MOI.add_constraint( + model, + MOI.Utilities.vectorize([ + Complex(1.0) * x[1], + Complex(1.0) * x[2] + 1.0 * im * x[7], + Complex(1.0) * x[3], + Complex(1.0) * x[4] + 1.0 * im * x[8], + Complex(1.0) * x[5] + 1.0 * im * x[9], + Complex(1.0) * x[6], + ]), + MOI.PositiveSemidefiniteConeTriangle(3), + ) + end, + ) + return +end + end # module TestConstraintHermitianToComplexSymmetric.runtests() From c7a95579a7c985b4ca2569438e6fbe0ed9fe8578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Tue, 15 Apr 2025 18:56:00 +0200 Subject: [PATCH 09/10] Fix SetDotScaling --- src/Bridges/Constraint/bridges/SetDotScalingBridge.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bridges/Constraint/bridges/SetDotScalingBridge.jl b/src/Bridges/Constraint/bridges/SetDotScalingBridge.jl index 9fff52e8ba..e778d4019b 100644 --- a/src/Bridges/Constraint/bridges/SetDotScalingBridge.jl +++ b/src/Bridges/Constraint/bridges/SetDotScalingBridge.jl @@ -194,10 +194,10 @@ end # for `SetMapBridge` does not work function MOI.supports_constraint( ::Type{<:SetDotScalingBridge}, - ::Type{<:MOI.AbstractVectorFunction}, + F::Type{<:MOI.AbstractVectorFunction}, S::Type{<:MOI.AbstractVectorSet}, ) - return MOI.is_set_dot_scaled(S) + return !MOI.Utilities.is_complex(F) && MOI.is_set_dot_scaled(S) end function MOI.supports_constraint( From 19a28dc896ccc9dc23db15a95f40db2d79077fb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Wed, 16 Apr 2025 09:38:47 +0200 Subject: [PATCH 10/10] Add SingleBridgeOptimizer --- .../Constraint/bridges/HermitianToComplexSymmetricBridge.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl b/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl index b63fe0c4d8..ff5a02f94e 100644 --- a/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl +++ b/src/Bridges/Constraint/bridges/HermitianToComplexSymmetricBridge.jl @@ -40,6 +40,9 @@ struct HermitianToComplexSymmetricBridge{T,F,G} <: SetMapBridge{ constraint::MOI.ConstraintIndex{F,MOI.PositiveSemidefiniteConeTriangle} end +const HermitianToComplexSymmetric{T,OT<:MOI.ModelLike} = + SingleBridgeOptimizer{HermitianToComplexSymmetricBridge{T},OT} + # Should be favored over `HermitianToSymmetricPSDBridge` MOI.Bridges.bridging_cost(::Type{<:HermitianToComplexSymmetricBridge}) = 0.5