jump-dev / JuMP.jl

Modeling language for Mathematical Optimization (linear, mixed-integer, conic, semidefinite, nonlinear)
http://jump.dev/JuMP.jl/
Other
2.17k stars 390 forks source link

*(::Real, ::Hermitian) is not hermitian #3694

Closed odow closed 4 months ago

odow commented 4 months ago
julia> using JuMP, LinearAlgebra

julia> A = LinearAlgebra.Hermitian([1 1+1im; 1-1im 2])
2×2 Hermitian{Complex{Int64}, Matrix{Complex{Int64}}}:
 1+0im  1+1im
 1-1im  2+0im

julia> model = Model();

julia> @variable(model, x)
x

julia> x * A
2×2 Matrix{GenericAffExpr{ComplexF64, VariableRef}}:
 x           (1 + im) x
 (1 - im) x  2 x

x-ref https://github.com/jump-dev/MutableArithmetics.jl/issues/264#issuecomment-1971966048

odow commented 4 months ago

I guess the problem with *(a::AbstractMutable, A::LinearAlgebra.Hermitian) is that there is no way to know if a is real or complex.

araujoms commented 4 months ago

Why not? As far as I understand there's only three possibilities that need to be tested: GenericVariableRef{T}, GenericAffExpr{T, GenericVariableRef{T}}, and GenericAffExpr{Complex{T}, GenericVariableRef{T}}. A bit cumbersome but doable, no?

odow commented 4 months ago

We could do this in JuMP, but there is no easy fix in MutableArithmetics for arbitrary types.

araujoms commented 4 months ago

I see. Maybe it is worth it to introduce RealMutableScalar and ComplexMutableScalar supertypes? I had a similar problem in jump-dev/Hypatia.jl#831: I needed to dispatch a function on whether the argument was a real or complex Mutable, and I couldn't figure out how. So in the end I just did a ugly hack hoping that a better programmer could fix it.

odow commented 4 months ago

I'd rather not do that unless absolutely necessary. MA is already too complicated. In this case, the answer is still correct, it's just not the most performant.

We can fix this in JuMP though, so I'll move the issue.