From 601d8f32ae82eb696b5434b1b66566f6d7582a78 Mon Sep 17 00:00:00 2001 From: Eric Hanson <5846501+ericphanson@users.noreply.github.com> Date: Tue, 21 May 2024 00:02:36 +0200 Subject: [PATCH 1/3] handle complex case in QuadOverLinAtom --- src/atoms/QuadOverLinAtom.jl | 17 +++++++++++++++-- test/test_atoms.jl | 18 ++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/atoms/QuadOverLinAtom.jl b/src/atoms/QuadOverLinAtom.jl index 9c98139f7..8d55a3b77 100644 --- a/src/atoms/QuadOverLinAtom.jl +++ b/src/atoms/QuadOverLinAtom.jl @@ -13,6 +13,11 @@ mutable struct QuadOverLinAtom <: AbstractExpr "[QuadOverLinAtom] quadoverlin arguments must be a vector and a scalar", ) end + if iscomplex(y) + error( + "[QuadOverLinAtom] the second argument to quadoverlin must be real, not complex.", + ) + end return new((x, y), (1, 1)) end end @@ -29,13 +34,21 @@ curvature(::QuadOverLinAtom) = ConvexVexity() function evaluate(q::QuadOverLinAtom) x = evaluate(q.children[1]) - return x' * x / evaluate(q.children[2]) + # `real` is only necessary to fix the type; `x'*x` will always be real-valued. + return real(output(x' * x)) / evaluate(q.children[2]) end function new_conic_form!(context::Context{T}, q::QuadOverLinAtom) where {T} t = Variable() x, y = q.children - f = vcat(t, (1 / T(2)) * y, x) + if iscomplex(x) + # ||x||₂² = ∑ᵢ |xᵢ|^2 = ∑ᵢ [re(xᵢ)² + im(xᵢ)²] + # = ||re(x)||₂² + ||im(x)||₂² + # = || vcat(re(x), im(y)) ||₂² + f = vcat(t, (1 / T(2)) * y, vcat(real(x), imag(x))) + else + f = vcat(t, (1 / T(2)) * y, x) + end add_constraint!(context, Constraint{MOI.RotatedSecondOrderCone}(f)) return conic_form!(context, t) end diff --git a/test/test_atoms.jl b/test/test_atoms.jl index 0d59e483a..ae24b0d35 100644 --- a/test/test_atoms.jl +++ b/test/test_atoms.jl @@ -1958,16 +1958,34 @@ function test_QuadOverLinAtom() _test_atom(target) do context return quadoverlin(Variable(2), Variable()) end + target = """ + variables: t, y, x1, x2, x3, x4 + minobjective: 1.0 * t + [t, 0.5 * y, x1, x2, x3, x4] in RotatedSecondOrderCone(6) + """ + _test_atom(target) do context + return quadoverlin(ComplexVariable(2), Variable()) + end @test_throws( ErrorException( "[QuadOverLinAtom] quadoverlin arguments must be a vector and a scalar", ), quadoverlin(Variable(2), Variable(2)) ) + @test_throws( + ErrorException( + "[QuadOverLinAtom] the second argument to quadoverlin must be real, not complex.", + ), + quadoverlin(Variable(2), ComplexVariable()) + ) x = Variable(2) x.value = [2.0, 3.0] atom = quadoverlin(x, constant(2.0)) @test evaluate(atom) ≈ 13 / 2 + x = ComplexVariable(2) + x.value = [2.0+im, 3.0] + atom = quadoverlin(x, constant(2.0)) + @test evaluate(atom) ≈ 14 / 2 return end From fa70a1aac77ebc68dc55d2e3091fb353c083700c Mon Sep 17 00:00:00 2001 From: Eric Hanson <5846501+ericphanson@users.noreply.github.com> Date: Tue, 21 May 2024 00:05:00 +0200 Subject: [PATCH 2/3] format --- test/test_atoms.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_atoms.jl b/test/test_atoms.jl index ae24b0d35..9eaf68ccf 100644 --- a/test/test_atoms.jl +++ b/test/test_atoms.jl @@ -1983,7 +1983,7 @@ function test_QuadOverLinAtom() atom = quadoverlin(x, constant(2.0)) @test evaluate(atom) ≈ 13 / 2 x = ComplexVariable(2) - x.value = [2.0+im, 3.0] + x.value = [2.0 + im, 3.0] atom = quadoverlin(x, constant(2.0)) @test evaluate(atom) ≈ 14 / 2 return From c39587cd50de10995413ed90b82317bdf4b8d425 Mon Sep 17 00:00:00 2001 From: Eric Hanson <5846501+ericphanson@users.noreply.github.com> Date: Tue, 21 May 2024 00:16:25 +0200 Subject: [PATCH 3/3] update docs --- docs/src/manual/complex-domain_optimization.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/src/manual/complex-domain_optimization.md b/docs/src/manual/complex-domain_optimization.md index e8afac0da..bd3d00ce9 100644 --- a/docs/src/manual/complex-domain_optimization.md +++ b/docs/src/manual/complex-domain_optimization.md @@ -56,7 +56,6 @@ operate on complex variables as well. Notable exceptions include: > - `inverse` > - `square` -> - `quadoverlin` > - `sqrt` > - `geomean` > - `huber`