我正在尝试直接以 csc 格式创建稀疏矩阵。这是因为我可以重复使用我编写的数组,预先分配它们并在其中创建@view。
但是,如果我使用@view,它会给出错误,而如果我离开简单的切片,它会起作用。
N::Int32 = 4
m::Int32 = 2
nzval_Sz = Array{Int8}(undef, N)
nzval_Sz[1] = 1
nzval_Sz[2] = -1
rowval_Sz = Array{Int32}(undef, N)
rowval_Sz[1] = 1
rowval_Sz[2] = 2
colptr_Sz = Array{Int32}(undef, N+1)
colptr_Sz[1] = 1
colptr_Sz[2] = 2
colptr_Sz[3] = 3 #last one is tot_nnz+1
sparsematrix = SparseMatrixCSC(m, m, colptr_Sz[1:m+1], rowval_Sz[1:m], nzval_Sz[1:m])
我确定它没有复制数据吗? (这非常重要,因为进行预分配是因为我需要迭代很多克罗内克乘积,它将成为一个非常大的切片,直到它覆盖一个非常大的矩阵)
如果您查看 Julia 中稀疏数组的实现方式,您会注意到仅接受
Vector
(这是来自 https://github.com/JuliaSparse/SparseArrays.jl/blob/main/src/sparsematrix 的代码。 jl):
struct SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrixCSC{Tv,Ti}
m::Int # Number of rows
n::Int # Number of columns
colptr::Vector{Ti} # Column i is in colptr[i]:(colptr[i+1]-1)
rowval::Vector{Ti} # Row indices of stored values
nzval::Vector{Tv} # Stored values, typically nonzeros
...
这意味着在某些时候需要转换为
Vector
。
唯一的非分配选项是 resize!
你的向量,这可能意味着可重用性问题:
resize!(colptr_Sz, m) # non allocating
但是,您可以轻松地实现自己的 SparseMatrixCSC 实现。或多或少类似于:
struct FlexiSparseMatrixCSC{Tv, Ti<:Integer, Vi<:AbstractVector{Ti}, Vv<:AbstractVector{Tv}} <: SparseArrays.AbstractSparseMatrixCSC{Tv,Ti}
m::Int
n::Int
colptr::Vi
rowval::Vi
nzval::Vv
...
现在基本上您需要做的是从 SparseArrays 复制大部分代码,这应该可以很好地与视图配合使用。
甚至更快的是拥有一个
FlexiSparseMatrixCSC
,它宁愿有一个额外的参数,只是裁剪大小(不使用视图 - 只是传递太大的向量),但这很可能需要对代码进行更大的重写。