-
-
Notifications
You must be signed in to change notification settings - Fork 399
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
Constraining Symmetric matrix to be equal to a Hermitian matrix is not Hermitian #3804
Comments
This is expected behavior from #3778 Previously: julia> using JuMP, LinearAlgebra
julia> model = Model()
A JuMP Model
Feasibility problem with:
Variables: 0
Model mode: AUTOMATIC
CachingOptimizer state: NO_OPTIMIZER
Solver name: No optimizer attached.
julia> @variable(model, A[1:2, 1:2] in PSDCone())
2×2 Symmetric{VariableRef, Matrix{VariableRef}}:
A[1,1] A[1,2]
A[1,2] A[2,2]
julia> B = LinearAlgebra.Hermitian(rand(ComplexF64, 2, 2))
2×2 Hermitian{ComplexF64, Matrix{ComplexF64}}:
0.0952809+0.0im 0.0199259+0.447844im
0.0199259-0.447844im 0.0929153+0.0im
julia> @constraint(model, A == B)
ERROR: At REPL[7]:1: `@constraint(model, A == B)`: Unsupported matrix in vector-valued set. Did you mean to use the broadcasting syntax `.==` for element-wise equality? Alternatively, this syntax is supported in the special case that the matrices are `LinearAlgebra.Symmetric` or `LinearAlgebra.Hermitian`.
Stacktrace:
[1] error(::String, ::String) Now julia> using JuMP, LinearAlgebra
julia> model = Model()
A JuMP Model
Feasibility problem with:
Variables: 0
Model mode: AUTOMATIC
CachingOptimizer state: NO_OPTIMIZER
Solver name: No optimizer attached.
julia> @variable(model, A[1:2, 1:2] in PSDCone())
2×2 Symmetric{VariableRef, Matrix{VariableRef}}:
A[1,1] A[1,2]
A[1,2] A[2,2]
julia> B = LinearAlgebra.Hermitian(rand(ComplexF64, 2, 2))
2×2 Hermitian{ComplexF64, Matrix{ComplexF64}}:
0.317083+0.0im 0.432169+0.203233im
0.432169-0.203233im 0.198036+0.0im
julia> @constraint(model, A == B)
[A[1,1] - 0.31708259602015787 … A[1,2] + (-0.43216931547981996 - 0.2032326360515233im)
A[1,2] + (-0.43216931547981996 + 0.2032326360515233im) A[2,2] - 0.19803569737893978] ∈ Zeros()
julia> print(backend(model))
Feasibility
Subject to:
VectorOfVariables-in-PositiveSemidefiniteConeTriangle
┌ ┐
│A[1,1]│
│A[1,2]│
│A[2,2]│
└ ┘ ∈ PositiveSemidefiniteConeTriangle(2)
VectorAffineFunction{ComplexF64}-in-Zeros
┌ ┐
│(-0.31708259602015787 - 0.0im) + (1.0 + 0.0im) A[1,1] │
│(-0.43216931547981996 + 0.2032326360515233im) + (1.0 + 0.0im) A[1,2]│
│(-0.43216931547981996 - 0.2032326360515233im) + (1.0 + 0.0im) A[1,2]│
│(-0.19803569737893978 - 0.0im) + (1.0 + 0.0im) A[2,2] │
└ ┘ ∈ Zeros(4) The constraint |
In your example you are constraining In my example the problem was solved correctly, but a lot of redundant constraints were added, and the dual variable recovered is incorrect. |
It will tell you the problem is infeasible. That's not quite the same as an error.
It's not JuMP's job to decide what a nonsensical constraint is. In some cases, you might want to add
Can you clarify? Is the dual still wrong after we fixed #3797? |
Yes, the dual is still wrong. Just run the example I pasted, it returns the dual variable. To get the correct one you need to write |
What makes you think the dual is wrong? I get: julia> dot(ρ, W), objective_value(model)
(0.03661524167501384, 0.03661524512473435) Now, the You could fix it with We don't add symmetric constraints because we loose the type of the matrix: julia> σ
4×4 Symmetric{VariableRef, Matrix{VariableRef}}:
σ[1,1] σ[1,2] σ[1,3] σ[1,4]
σ[1,2] σ[2,2] σ[2,3] σ[2,4]
σ[1,3] σ[2,3] σ[3,3] σ[3,4]
σ[1,4] σ[2,4] σ[3,4] σ[4,4]
julia> noisy_state
4×4 Hermitian{AffExpr, Matrix{AffExpr}}:
λ + 0.0007142349938333907 -0.005378044977694615 … -0.02486244188463285
-0.005378044977694615 λ + 0.04049559043147808 0.18720915646155625
0.008164586821029125 -0.06147768665340706 -0.2842083727379334
-0.02486244188463285 0.18720915646155625 λ + 0.8654588781055151
julia> σ - noisy_state
4×4 Matrix{AffExpr}:
σ[1,1] - λ - 0.0007142349938333907 … σ[1,4] + 0.02486244188463285
σ[1,2] + 0.005378044977694615 σ[2,4] - 0.18720915646155625
σ[1,3] - 0.008164586821029125 σ[3,4] + 0.2842083727379334
σ[1,4] + 0.02486244188463285 σ[4,4] - λ - 0.8654588781055151 I guess we could perhaps expect that |
So perhaps your underlying issue is: julia> using JuMP, LinearAlgebra
julia> model = Model();
julia> @variable(model, A[1:2, 1:2] in PSDCone());
julia> @variable(model, B[1:2, 1:2] in HermitianPSDCone());
julia> A + B
2×2 Matrix{GenericAffExpr{ComplexF64, VariableRef}}:
A[1,1] + real(B[1,1]) A[1,2] + real(B[1,2]) + imag(B[1,2]) im
A[1,2] + real(B[1,2]) - imag(B[1,2]) im A[2,2] + real(B[2,2])
julia> C = LinearAlgebra.Symmetric(rand(Float64, 2, 2));
julia> D = LinearAlgebra.Hermitian(rand(ComplexF64, 2, 2));
julia> C + D
2×2 Hermitian{ComplexF64, Matrix{ComplexF64}}:
1.66933+0.0im 0.626978+0.438058im
0.626978-0.438058im 0.427326+0.0im |
We're missing overloads for these base methods: |
Fair enough. It's not the design I would have chosen, but there's no silent failure anymore, which is the part I found really objectionable. Now it gives either the correct answer or |
Because we assumed that I've added a new method to #3805 where we now add |
Cool, now it's real. Thanks a lot! |
Thanks for catching the bugs, issues in the dual are not easy to spot! |
Bug introduced in #3797: before if I tried to constrain A == B for Symmetric A and Hermitian B it would give me an error. Now it silently fails.
The text was updated successfully, but these errors were encountered: