# Specific methods for symmetric matrices

**URL:** <https://discourse.julialang.org/t/specific-methods-for-symmetric-matrices/12445>\
**Category:** General Usage\
**Tags:** type\
**Created:** [July 17, 2018, 10:26pm UTC](https://discourse.julialang.org/t/specific-methods-for-symmetric-matrices/12445 "2018-07-17T22:26:23Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [July 17, 2018, 10:26pm UTC](https://discourse.julialang.org/t/specific-methods-for-symmetric-matrices/12445/1 "2018-07-17T22:26:23Z")

</div>

I’m defining a function `f(m)` that operates on a big matrix `m` that may be or not be symmetric. If it is symmetric, the algorithm can by optimized by only working on the upper triangle.

I know that the symmetry of `m` can be checked with `issymmetric(m)`, but for big matrices this also has some cost, and in some cases _I already know_ that `m` is symmetric, because it has been created by another function `g` that always produces symmetric matrices.

I guess that there must be something that I could do with types, in order to apply the efficient algorithm for symmetric matrices when suitable (without using `issymmetric`), but I’m failing to find the correct solution.

I have tried with a special function `f(x::Symmetric)` that implements the efficient algorithm, and calling `m=Symmetric(m)` in the last line of the function `g` that produces the symmetric matrix. But the conversion to `Symmetric` also takes time, and performance can be even worse.

Now I was trying to create a subtype of `AbstractMatrix`, _ad hoc_ for the output of `g`, which I cold use in the signature of `f` instead of `Symmetric`. But I don’t know how to declare such type.

[https://docs.julialang.org/en/stable/manual/types/](https://docs.julialang.org/en/stable/manual/types/) tells how to define subtypes of scalars, composite types, etc., but not how to define a subtype of vectors, matrices, etc. Doing it as for scalars, with `abstract type`, I get an error of invalid subtyping.

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [July 18, 2018, 12:57am UTC](https://discourse.julialang.org/t/specific-methods-for-symmetric-matrices/12445/2 "2018-07-18T00:57:16Z")

</div>

It sounds like you actually have almost the right implementation already. As I understand it, what you’re doing is:

```julia
f(x::Symmetric) = <do the fast symmetric version>

f(x::AbstractMatrix) = <do the slow non-symmetric version>

```

and then when you know you have a symmetric input, you do:

```julia
f(Symmetric(m))

```

That sounds totally fine to me. You could certainly implement your own type which is a subtype of AbstractMatrix, but you might not need to.

However, you mentioned that the conversion to `Symmetric(m)` takes time and hurts your performance. That shouldn’t be the case, as the `Symmetric` type is already just an extremely cheap wrapper around an existing matrix. For example:

```julia
julia> using BenchmarkTools

julia> A = rand(1000, 1000);

julia> @btime Symmetric($A);
  13.772 ns (1 allocation: 32 bytes)

```

constructing the `Symmetric` wrapper takes less than 14 nanoseconds, which is pretty fast.

I suspect the performance problem with `Symmetric` is coming from some other aspect of your code. For example, the following code will be slower:

```julia
m = rand(10, 10) # in this line, m is a Matrix{Float64}
m = Symmetric(m) # now m has changed type to a `Symmetric{Float64, Matrix{Float64}}`

```

because the variable `m` changes type, which is the definition of type-unstable code. See: [https://docs.julialang.org/en/stable/manual/performance-tips/#Avoid-changing-the-type-of-a-variable-1](https://docs.julialang.org/en/stable/manual/performance-tips/#Avoid-changing-the-type-of-a-variable-1)

If you share more about your actual code we can probably help you figure out why the Symmetric wrapper is slow for you.

---

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [July 18, 2018, 8:26am UTC](https://discourse.julialang.org/t/specific-methods-for-symmetric-matrices/12445/3 "2018-07-18T08:26:28Z")

</div>

You are right. The problem was in another place, not with `Symmetric`.

Just to explain what happened: I neglected to mention that I am actually working with symmetric _sparse bool_ matrices (`SparseMatrixCSC{Bool,Int64}`), and my original code was like this:

```julia
function f(x)
    # do some stuff, and call another function h
    h(x)
end

# Different methods of h:
function h(x::SparseMatrixCSC{Bool})
    # Efficient method that goes through nonzero cells
end
function h(x::AbstractMatrix)
    # Slower method that traverses the full matrix
end

```

I had created a new function `hsym` with equivalent methods, but only going through the upper triangle, and then added:

```julia
function f(x::Symmetric)
    # call the symmetric version of h
    hsym(x)
end

```

Now, `Symmetric <: AbstractMatrix`, but not `SparseMatrixCSC`, so I was calling the wrong, slower method of `hsym`. Fixed it with:

```julia
function f(x::Symmetric)
    # call the symmetric version of h
    hsym(x.data)
end

```

---

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [July 18, 2018, 9:29am UTC](https://discourse.julialang.org/t/specific-methods-for-symmetric-matrices/12445/4 "2018-07-18T09:29:14Z")

</div>

I have changed the title of the conversation, since I think the new one reflects better what we are talking about.

By the way, I found only by chance that I can access the underlying data of `x::Symmetric` through `x.data`, since it is not documented. So I wonder if this is the right way of solving my problem, or just a hack that might break without notice.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [July 18, 2018, 10:07am UTC](https://discourse.julialang.org/t/specific-methods-for-symmetric-matrices/12445/5 "2018-07-18T10:07:10Z")

</div>

> [@rdeits](#):
>
> ```julia
> m = rand(10, 10) # in this line, m is a Matrix{Float64}
> m = Symmetric(m) # now m has changed type to a `Symmetric{Float64, Matrix{Float64}}`
> 
> ```
> 
> because the variable `m` changes type, which is the definition of type-unstable code. See: [https://docs.julialang.org/en/stable/manual/performance-tips/#Avoid-changing-the-type-of-a-variable-1](https://docs.julialang.org/en/stable/manual/performance-tips/#Avoid-changing-the-type-of-a-variable-1)

That’s not really what ‘type-unstable’ means, in my understanding. The docs call it “An analogous “type-stability” problem”. Type-instability generally means that the output type of an operation is not predictable from the input types, but also depends on run-time values, or some other run-time information.

The code above is entirely type-predictable _in principle_, but the compiler is for some reason not currently clever enough to track type changes in a variable.
