# Retaining the property of Symmetric?

**URL:** <https://discourse.julialang.org/t/retaining-the-property-of-symmetric/127437>\
**Category:** General Usage\
**Tags:** question, jump, linearalgebra, symmetric\
**Created:** [March 28, 2025, 4:47am UTC](https://discourse.julialang.org/t/retaining-the-property-of-symmetric/127437 "2025-03-28T04:47:50Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [March 28, 2025, 4:47am UTC](https://discourse.julialang.org/t/retaining-the-property-of-symmetric/127437/1 "2025-03-28T04:47:50Z")

</div>

It doesn’t keep the `Symmetric` property

```julia
import JuMP, Gurobi, LinearAlgebra
model = JuMP.Model(Gurobi.Optimizer)
JuMP.@variable(model, X[1:2, 1:2] >= 0, Symmetric)
JuMP.optimize!(model)
Xt = JuMP.value.(X) # ⚠️ Can this behavior be improved?

# julia> typeof(X)
# LinearAlgebra.Symmetric{JuMP.VariableRef, Matrix{JuMP.VariableRef}}

# julia> typeof(Xt)
# Matrix{Float64} (alias for Array{Float64, 2})

Xt = LinearAlgebra.Symmetric(Xt) # Since JuMP do not support, I have to do this myself

```

Here is another example

```julia
import JuMP, Gurobi, LinearAlgebra
model = JuMP.Model(Gurobi.Optimizer)
JuMP.@variable(model, x); JuMP.@variable(model, y)
trivial_value = 999
JuMP.@expression(model, X, LinearAlgebra.Symmetric([0 x; trivial_value y]))
JuMP.optimize!(model)
Xt = JuMP.value.(X) # ⚠️ Can this behavior be improved?

julia> typeof(X)
LinearAlgebra.Symmetric{JuMP.AffExpr, Matrix{JuMP.AffExpr}}

julia> typeof(Xt)
Matrix{Float64} (alias for Array{Float64, 2})

```

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [March 28, 2025, 6:40am UTC](https://discourse.julialang.org/t/retaining-the-property-of-symmetric/127437/2 "2025-03-28T06:40:00Z")

</div>

This is a property of Julia, not JuMP:

```julia
julia> using LinearAlgebra

julia> x = LinearAlgebra.Symmetric([1 2; 2 3])
2×2 Symmetric{Int64, Matrix{Int64}}:
 1 2
 2 3

julia> x.^2
2×2 Matrix{Int64}:
 1 4
 4 9

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [March 28, 2025, 6:59am UTC](https://discourse.julialang.org/t/retaining-the-property-of-symmetric/127437/3 "2025-03-28T06:59:53Z")

</div>

Related issue on redundant operations in elementwise operations: [map and broadcast on symmetric matrices is inefficient · Issue #643 · JuliaLang/LinearAlgebra.jl](https://github.com/JuliaLang/LinearAlgebra.jl/issues/643). However, would it be breaking to go farther and change the return type to `Symmetric`, even if most people would welcome it?

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [March 28, 2025, 7:13am UTC](https://discourse.julialang.org/t/retaining-the-property-of-symmetric/127437/4 "2025-03-28T07:13:03Z")

</div>

The current behavior is

```julia
julia> S
3×3 Symmetric{Int64, Matrix{Int64}}:
  0 -8 -2
 -8 -2 3
 -2 3 8

julia> S^2
3×3 Symmetric{Int64, Matrix{Int64}}:
  68 10 -40
  10 77 34
 -40 34 77

julia> S * S
3×3 Matrix{Int64}:
  68 10 -40
  10 77 34
 -40 34 77

julia> transpose(S) * S
3×3 Matrix{Int64}:
  68 10 -40
  10 77 34
 -40 34 77

julia> S .^ 2
3×3 Matrix{Int64}:
  0 64 4
 64 4 9
  4 9 64

```

---

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [May 1, 2025, 5:45am UTC](https://discourse.julialang.org/t/retaining-the-property-of-symmetric/127437/5 "2025-05-01T05:45:18Z")

</div>

> [@WalterMadelim](#):
>
> ```julia
> julia> S * S
> 3×3 Matrix{Int64}:
> 68 10 -40
> 10 77 34
> -40 34 77
> 
> julia> transpose(S) * S
> 3×3 Matrix{Int64}:
> 68 10 -40
> 10 77 34
> -40 34 77
> 
> ```

These two probably need to stay the way they are. The product of two symmetric matrices is not necessarily symmetric. In your specific examples, the result is symmetric because the factors are identical, but that’s a property of the values, not their types. It’s generally desirable for the return type to only depend on the argument types, not the argument values.

For `S.^2` it would be reasonable to return `Symmetric`, but changing that now might be considered too breaking, that is, not backward compatible.

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [May 1, 2025, 8:51am UTC](https://discourse.julialang.org/t/retaining-the-property-of-symmetric/127437/6 "2025-05-01T08:51:05Z")

</div>

> [@danielwe](#):
>
> changing that now might be considered too breaking, that is, not backward compatible.

I think it’s fine to change return types across versions, given that types are tightly coupled with performance. This is somewhat breaking if people are explicitly dispatching on a `Matrix`, but the return type is not documented to be stable across versions.

---

<div class="post-metadata">

**Author:** ![WalterMadelim](https://avatars.discourse-cdn.com/v4/letter/w/3e96dc/32.png) [@WalterMadelim](https://discourse.julialang.org/u/WalterMadelim)\
**Post date:** [May 9, 2025, 6:22am UTC](https://discourse.julialang.org/t/retaining-the-property-of-symmetric/127437/7 "2025-05-09T06:22:57Z")

</div>

I have a novel idea: Why should we write `S .^ 2`?  
A more thoughtful method could have been

```julia
julia> S
3×3 Symmetric{Int64, Matrix{Int64}}:
 -5 -1 3
 -1 -5 1
  3 1 -5

julia> U = UpperTriangular(S.data)
3×3 UpperTriangular{Int64, Matrix{Int64}}:
 -5 -1 3
  ⋅ -5 1
  ⋅ ⋅ -5

julia> U = U .^ 2
3×3 UpperTriangular{Int64, Matrix{Int64}}:
 25 1 9
  ⋅ 25 1
  ⋅ ⋅ 25

julia> ret = Symmetric(U.data)
3×3 Symmetric{Int64, Matrix{Int64}}:
 25 1 9
  1 25 1
  9 1 25

julia> ret == S .^ 2
true

```

I don’t know whether this is appropriate.

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [May 9, 2025, 7:20am UTC](https://discourse.julialang.org/t/retaining-the-property-of-symmetric/127437/8 "2025-05-09T07:20:29Z")

</div>

This is precisely how many algebraic operations are carried out for `Symmetric`, and seems appropriate once we specialize broadcasting for the type.
