Operations with Eye do not preserve sparsity
amilsted opened this issue · 6 comments
Hi, I've noticed that SquareEye
, since it is a LinearAlgebra.Diagonal
preserves sparsity in many operations. For example:
julia> using FillArrays
julia> using SparseArrays
julia> E = Eye(2)
2×2 Eye{Float64}
julia> M = sprand(2,2, 0.5)
2×2 SparseMatrixCSC{Float64, Int64} with 3 stored entries:
0.906128 0.408236
0.0285949 ⋅
julia> E + M
2×2 SparseMatrixCSC{Float64, Int64} with 4 stored entries:
1.90613 0.408236
0.0285949 1.0
julia> kron(E, E) # although it would be nice is this were another SquareEye!
4×4 Diagonal{Float64, Vector{Float64}}:
1.0 ⋅ ⋅ ⋅
⋅ 1.0 ⋅ ⋅
⋅ ⋅ 1.0 ⋅
⋅ ⋅ ⋅ 1.0
However, general Eye
typically converts to a dense matrix:
julia> E = Eye(2,2)
2×2 Eye{Float64}
julia> E + M
2×2 Matrix{Float64}:
1.90613 0.408236
0.0285949 1.0
julia> kron(E,E)
4×4 Matrix{Float64}:
1.0 0.0 0.0 0.0
0.0 1.0 0.0 0.0
0.0 0.0 1.0 0.0
0.0 0.0 0.0 1.0
This was quite surprising to me. Could we add some operator overloads to keep things sparse in the Eye
case?
The broadcast is actually a bit involved, and defining everything here might not be the best idea. The interplay between the structured matrix broadcast style and the sparse matrix style is handled by SparseArrays
, so perhaps that is the package that should provide a hook to access that functionality for custom structured matrix types.
Regarding kron
, note that the result is not an Eye
in general for rectangular matrices, although perhaps we may express this as a sparse matrix
julia> E = Eye(2,3)
2×3 Eye{Float64}
julia> kron(E, E)
4×9 Matrix{Float64}:
1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0
0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0
The Diagonal
case should be fixed in #268
Right, I realize you can't make kron
of rectangular Eye
still be an Eye
, but that result is very sparse, so having kron(Eye(m,n), Eye(x,y))
return a sparse matrix seems reasonable. I don't think this case can be handles in SparseArrays
.
I guess another alternative is to return a SciMLOperators
lazy tensor product...
Now the rectangular kron is also addressed in #268, and it'll return a sparse array
getindex
also doesn't preserve sparsity
julia> Eye(5)[:,:]
5×5 Matrix{Float64}:
1.0 0.0 0.0 0.0 0.0
0.0 1.0 0.0 0.0 0.0
0.0 0.0 1.0 0.0 0.0
0.0 0.0 0.0 1.0 0.0
0.0 0.0 0.0 0.0 1.0
I'm not sure if it's worth adding BandedMatrices to the dependency.
Adding banded matrices as a dependency won’t work
we could add a new type called OffDiagonal
Note layout_getindex(D, :, :)
will produce a BandedMatrix