As indicated by the topic, I intend to replace some small matrices with the StaticArrays but the global sparse matrix created by SparseArrays.jl cannot be indexed by a SVector. A simple example is given as follows.
using SparseArrays
using StaticArrays
A = spzeros(10, 10)
ind1 = SVector(1, 2, 3, 4)
a = @SArray rand(4, 4)
A[ind1, ind1] += a
@show A
The error is given in REPL as
julia> A[ind1,ind1] += a
ERROR: MethodError: no method matching length(::StaticArrays.StaticIndexing{SVector{4, Int64}})
Closest candidates are:
length(::Union{Base.KeySet, Base.ValueIterator})
@ Base abstractdict.jl:58
length(::Union{SparseArrays.FixedSparseVector{Tv, Ti}, SparseVector{Tv, Ti}} where {Tv, Ti})
@ SparseArrays C:\lijinze\julia\share\julia\stdlib\v1.9\SparseArrays\src\sparsevector.jl:95
length(::Union{ZMQ._Message, Base.RefValue{ZMQ._Message}})
@ ZMQ C:\lijinze\julia\packages\packages\ZMQ\lrABE\src\_message.jl:31
...
Stacktrace:
[1] setindex!(A::SparseMatrixCSC{Float64, Int64}, V::SMatrix{4, 4, Float64, 16}, Ix::SVector{4, Int64}, Jx::SVector{4, Int64})
@ SparseArrays C:\users\julia\share\julia\stdlib\v1.9\SparseArrays\src\sparsematrix.jl:3170
[2] top-level scope
@ REPL[24]:1
Thanks in advance for tackling this problem.
oheil
September 26, 2023, 2:43pm
2
The sparse matrix A doesnβt hold any values, except for the default value zero (of default type Float64) which isnβt explicitly stored. Accessing any range of indices gives some dots:
julia> A[ind1, ind1]
4Γ4 SparseMatrixCSC{Float64, Int64} with 0 stored entries:
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
Accessing via a single index returns the default value 0.0:
julia> A[1]
0.0
You operation can be written as (see the dot before the +):
julia> A[ind1,ind1] .+= a
4Γ4 view(::SparseMatrixCSC{Float64, Int64}, [1, 2, 3, 4], [1, 2, 3, 4]) with eltype Float64 with indices SOneTo(4)ΓSOneTo(4):
0.396905 0.518507 0.0333795 0.428079
0.105497 0.358759 0.0329777 0.748697
0.495962 0.948462 0.214173 0.55445
0.517173 0.866702 0.91867 0.352342
julia> A
10Γ10 SparseMatrixCSC{Float64, Int64} with 16 stored entries:
0.396905 0.518507 0.0333795 0.428079 β
β
β
β
β
β
0.105497 0.358759 0.0329777 0.748697 β
β
β
β
β
β
0.495962 0.948462 0.214173 0.55445 β
β
β
β
β
β
0.517173 0.866702 0.91867 0.352342 β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
β
This is a bit of a lack in the documentation of Sparse Arrays Β· The Julia Language I would say, where it says:
Arithmetic operations on sparse matrices also work as they do on dense matrices.
The error message points to a forgotten implementation of method length(::StaticArrays.StaticIndexing{SVector{4, Int64}}) somewhere, but I donβt have the nerves to look this up for now, and it wouldnβt help you much for your issue.
Thank you very much! It succeeds in addressing my problem.
Raf
September 26, 2023, 3:03pm
4
This is basically an incorrect return value from to_indices in StaticArrays.jl:
struct StaticIndexing{I}
ind::I
end
unwrap(i::StaticIndexing) = i.ind
function Base.to_indices(A, I::Tuple{Vararg{Union{Integer, CartesianIndex, StaticArray{<:Tuple,Int}}}})
inds = to_indices(A, axes(A), I)
return map(StaticIndexing, inds)
end
Itβs overriding internals Base._getindex but that doesnβt actually work.
function Base._getindex(::IndexStyle, A::AbstractArray, i1::StaticIndexing, I::StaticIndexing...)
inds = (unwrap(i1), map(unwrap, I)...)
return StaticArrays._getindex(A, index_sizes(inds...), inds)
end
StaticIndexing needs to be <: AbstractArray and it needs to define iterate and size (shockingly not getindex but thatβs another storyβ¦).
Please make an issue for this in StaticArrays.jl
Raf
September 26, 2023, 3:18pm
5
From the to_indices docs:
βThe returned tuple must only contain either Ints or AbstractArrays of scalar indices that are supported by array Aβ
StaticArrays.jl is just breaking the interface here.
Issue made here:
opened 03:21PM - 26 Sep 23 UTC
The `to_indices` docs state that:
> The returned tuple must only contain either⦠Ints or AbstractArrays of scalar indices that are supported by array A
But `StaticIndexing` is not either:
https://github.com/JuliaArrays/StaticArrays.jl/blob/217e6f10a01433b8a60b679622065bc8702da923/src/indexing.jl#L213-L221
See discourse:
https://discourse.julialang.org/t/a-sparse-matrix-cannot-be-indexed-by-a-svector/104265/5