Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix various bugs with Real-valued Hermitian matrices #3805

Merged
merged 7 commits into from
Aug 12, 2024
Merged

Conversation

odow
Copy link
Member

@odow odow commented Aug 11, 2024

Closes #3804

Now the dual of #3804 is Hermitian

julia> using JuMP

julia> using LinearAlgebra

julia> import Hypatia

julia> import Ket

julia> import Random

julia> function dual_test(d)
           Random.seed!(1)
           ρ = Ket.random_state(Float64, d^2, 1)
           model = Model()
           @variable(model, σ[1:d^2, 1:d^2] in PSDCone())
           @variable(model, λ)
           noisy_state = Hermitian+ λ * I(d^2))
           @constraint(model, witness_constraint, σ == noisy_state)
           @objective(model, Min, λ)
           @constraint(model, Ket.partial_transpose(σ, 2, [d, d]) in PSDCone())
           set_optimizer(model, Hypatia.Optimizer)
           set_silent(model)
           optimize!(model)
           W = dual(witness_constraint)
           return W
       end
dual_test (generic function with 1 method)

julia> dual_test(2)
4×4 Hermitian{ComplexF64, Matrix{ComplexF64}}:
 -0.119631+0.0im   0.213316+0.0im  -0.213316+0.0im   0.380369+0.0im
  0.213316-0.0im  -0.380369+0.0im  -0.119631+0.0im   0.213316+0.0im
 -0.213316-0.0im  -0.119631-0.0im  -0.380369+0.0im  -0.213316+0.0im
  0.380369-0.0im   0.213316-0.0im  -0.213316-0.0im  -0.119631+0.0im

Copy link

codecov bot commented Aug 11, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 97.90%. Comparing base (52bb94f) to head (cb854d7).

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #3805   +/-   ##
=======================================
  Coverage   97.90%   97.90%           
=======================================
  Files          44       44           
  Lines        6010     6020   +10     
=======================================
+ Hits         5884     5894   +10     
  Misses        126      126           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@odow odow changed the title Fix return type of +/-(::Symmetric, ::Hermitian) for JuMP types Fix various bugs with Real-valued Hermitian matrices Aug 11, 2024
@odow
Copy link
Member Author

odow commented Aug 11, 2024

We now get:

julia> using JuMP

julia> using LinearAlgebra

julia> import Hypatia

julia> import Ket

julia> import Random

julia> function dual_test(d)
           Random.seed!(1)
           ρ = Ket.random_state(Float64, d^2, 1)
           model = Model()
           @variable(model, σ[1:d^2, 1:d^2] in PSDCone())
           @variable(model, λ)
           noisy_state = Hermitian+ λ * I(d^2))
           @constraint(model, witness_constraint, σ == noisy_state)
           @objective(model, Min, λ)
           @constraint(model, Ket.partial_transpose(σ, 2, [d, d]) in PSDCone())
           set_optimizer(model, Hypatia.Optimizer)
           set_silent(model)
           optimize!(model)
           W = dual(witness_constraint)
           return W
       end
dual_test (generic function with 1 method)

julia> dual_test(2)
4×4 Symmetric{Float64, Matrix{Float64}}:
 -0.119631   0.213316  -0.213316   0.380369
  0.213316  -0.380369  -0.119631   0.213316
 -0.213316  -0.119631  -0.380369  -0.213316
  0.380369   0.213316  -0.213316  -0.119631

@odow
Copy link
Member Author

odow commented Aug 11, 2024

I'm not fully convinced about this one. You could argue that we should be able to return Hermitian{Float64,Matrix{Float64}}, which would mean being able to distinguish real- and complex-valued HermitianMatrixSpace.

@blegat should weigh in before we merge.

@odow
Copy link
Member Author

odow commented Aug 11, 2024

My underlying problem is that Julia has both Symmetric and Hermitian{<:Real}, which are slightly different things.

@@ -571,3 +569,55 @@ function Base.complex(
)
return r + im * i
end

function Base.:+(
Copy link
Member

@blegat blegat Aug 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comment that the fault returns a Matrix and we overload to return a Hermitian. This is already done in LinearAlgebra for subtypes of Real

@blegat
Copy link
Member

blegat commented Aug 12, 2024

I'm not fully convinced about this one. You could argue that we should be able to return Hermitian{Float64,Matrix{Float64}}, which would mean being able to distinguish real- and complex-valued HermitianMatrixSpace.

It might make more sense to return Hermitian{Float64} and we could add a RealHermitianMatrixSpace. However, it could also be confusing so I think Symmetric has advantages. We've made an effort that the shape only depends on the type of the input but here the type is Hermitian{<:Real} so we see that it's synonymous to Symmetric so Symmetric seems to be the best option.

@odow
Copy link
Member Author

odow commented Aug 12, 2024

so Symmetric seems to be the best option.

Sounds good.

@odow odow merged commit 34ec0a0 into master Aug 12, 2024
11 checks passed
@odow odow deleted the od/sym-herm branch August 12, 2024 21:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Constraining Symmetric matrix to be equal to a Hermitian matrix is not Hermitian
2 participants