稀疏数组
Julia 在 SparseArrays
标准库模块中支持稀疏向量和 稀疏矩阵。稀疏数组是包含足够多的零的数组,以至于将它们存储在特殊数据结构中,与稠密数组相比,可以在空间和执行时间上节省。
可以在 值得注意的外部包 中找到实现不同稀疏存储类型、多维稀疏数组等的外部包。
压缩稀疏列 (CSC) 稀疏矩阵存储
在 Julia 中,稀疏矩阵以 压缩稀疏列 (CSC) 格式 存储。Julia 稀疏矩阵具有类型 SparseMatrixCSC{Tv,Ti}
,其中 Tv
是存储值的类型,Ti
是用于存储列指针和行索引的整数类型。SparseMatrixCSC
的内部表示如下
struct SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrixCSC{Tv,Ti}
m::Int # Number of rows
n::Int # Number of columns
colptr::Vector{Ti} # Column j is in colptr[j]:(colptr[j+1]-1)
rowval::Vector{Ti} # Row indices of stored values
nzval::Vector{Tv} # Stored values, typically nonzeros
end
压缩稀疏列存储使得访问稀疏矩阵列中的元素变得容易快捷,而按行访问稀疏矩阵则要慢得多。在 CSC 结构中,一次在一个位置插入以前未存储的条目等操作往往很慢。这是因为稀疏矩阵中所有超出插入点的元素都必须向后移动一位。
对稀疏矩阵的所有操作都经过精心实现,以利用 CSC 数据结构以获得性能,并避免昂贵的操作。
如果您有来自不同应用程序或库的 CSC 格式数据,并希望将其导入 Julia,请确保您使用的是 1 索引。每列中的行索引需要排序,如果它们没有排序,矩阵将显示不正确。如果您的 SparseMatrixCSC
对象包含未排序的行索引,一种快速排序它们的方法是进行双重转置。由于转置操作是懒惰的,请创建一个副本以具体化每个转置。
在某些应用中,在 SparseMatrixCSC
中存储显式零值很方便。这些值会被 Base
中的函数接受(但不能保证在修改操作中会被保留)。这些显式存储的零值被许多例程视为结构性非零值。nnz
函数返回稀疏数据结构中显式存储的元素数量,包括非结构性零值。为了统计数值非零值的准确数量,请使用 count(!iszero, x)
,它检查稀疏矩阵的每个存储元素。可以使用 dropzeros
和就地 dropzeros!
从稀疏矩阵中删除存储的零值。
julia> A = sparse([1, 1, 2, 3], [1, 3, 2, 3], [0, 1, 2, 0])
3×3 SparseMatrixCSC{Int64, Int64} with 4 stored entries:
0 ⋅ 1
⋅ 2 ⋅
⋅ ⋅ 0
julia> dropzeros(A)
3×3 SparseMatrixCSC{Int64, Int64} with 2 stored entries:
⋅ ⋅ 1
⋅ 2 ⋅
⋅ ⋅ ⋅
稀疏向量存储
稀疏向量存储方式与稀疏矩阵的压缩稀疏列格式非常类似。在 Julia 中,稀疏向量具有类型 SparseVector{Tv,Ti}
,其中 Tv
是存储值的类型,Ti
是索引的整数类型。内部表示如下
struct SparseVector{Tv,Ti<:Integer} <: AbstractSparseVector{Tv,Ti}
n::Int # Length of the sparse vector
nzind::Vector{Ti} # Indices of stored values
nzval::Vector{Tv} # Stored values, typically nonzeros
end
与 SparseMatrixCSC
一样,SparseVector
类型也可以包含显式存储的零值。(参见 稀疏矩阵存储。)
稀疏向量和矩阵构造函数
创建稀疏数组最简单的方法是使用与 Julia 用于处理稠密数组的 zeros
函数等效的函数。要生成稀疏数组,您可以使用带有 sp
前缀的相同名称
julia> spzeros(3)
3-element SparseVector{Float64, Int64} with 0 stored entries
sparse
函数通常是构造稀疏数组的便捷方法。例如,要构造一个稀疏矩阵,我们可以输入行索引向量 I
、列索引向量 J
和存储值向量 V
(这也被称为 COO(坐标)格式)。sparse(I,J,V)
然后构造一个稀疏矩阵,使得 S[I[k], J[k]] = V[k]
。等效的稀疏向量构造函数是 sparsevec
,它接受(行)索引向量 I
和包含存储值的向量 V
,并构造一个稀疏向量 R
,使得 R[I[k]] = V[k]
。
julia> I = [1, 4, 3, 5]; J = [4, 7, 18, 9]; V = [1, 2, -5, 3];
julia> S = sparse(I,J,V)
5×18 SparseMatrixCSC{Int64, Int64} with 4 stored entries:
⎡⠀⠈⠀⠀⠀⠀⠀⠀⢀⎤
⎣⠀⠀⠀⠂⡀⠀⠀⠀⠀⎦
julia> R = sparsevec(I,V)
5-element SparseVector{Int64, Int64} with 4 stored entries:
[1] = 1
[3] = -5
[4] = 2
[5] = 3
sparse
和 sparsevec
函数的逆函数是 findnz
,它检索用于创建稀疏数组的输入。 findall(!iszero, x)
返回 x
中非零条目的笛卡尔索引(包括存储的等于零的条目)。
julia> findnz(S)
([1, 4, 5, 3], [4, 7, 9, 18], [1, 2, 3, -5])
julia> findall(!iszero, S)
4-element Vector{CartesianIndex{2}}:
CartesianIndex(1, 4)
CartesianIndex(4, 7)
CartesianIndex(5, 9)
CartesianIndex(3, 18)
julia> findnz(R)
([1, 3, 4, 5], [1, -5, 2, 3])
julia> findall(!iszero, R)
4-element Vector{Int64}:
1
3
4
5
创建稀疏数组的另一种方法是使用 sparse
函数将稠密数组转换为稀疏数组
julia> sparse(Matrix(1.0I, 5, 5))
5×5 SparseMatrixCSC{Float64, Int64} with 5 stored entries:
1.0 ⋅ ⋅ ⋅ ⋅
⋅ 1.0 ⋅ ⋅ ⋅
⋅ ⋅ 1.0 ⋅ ⋅
⋅ ⋅ ⋅ 1.0 ⋅
⋅ ⋅ ⋅ ⋅ 1.0
julia> sparse([1.0, 0.0, 1.0])
3-element SparseVector{Float64, Int64} with 2 stored entries:
[1] = 1.0
[3] = 1.0
您可以使用 Array
构造函数反向操作。可以使用 issparse
函数查询矩阵是否为稀疏的。
julia> issparse(spzeros(5))
true
稀疏矩阵运算
稀疏矩阵的算术运算与稠密矩阵的算术运算相同。稀疏矩阵的索引、赋值和连接与稠密矩阵的操作方式相同。索引操作,尤其是赋值,在每次执行一个元素时会很昂贵。在许多情况下,最好将稀疏矩阵转换为 (I,J,V)
格式,使用 findnz
进行操作,在稠密向量 (I,J,V)
中操作值或结构,然后重建稀疏矩阵。
稠密和稀疏方法的对应关系
下表给出了稀疏矩阵的内置方法与其在稠密矩阵类型上的对应方法之间的对应关系。通常,生成稀疏矩阵的方法与稠密矩阵方法的不同之处在于,结果矩阵遵循给定稀疏矩阵 S
的相同稀疏性模式,或者结果稀疏矩阵的密度为 d
,即每个矩阵元素具有概率 d
为非零值。
详细信息可以在标准库参考的 稀疏向量和矩阵 部分找到。
稀疏 | 稠密 | 描述 |
---|---|---|
spzeros(m,n) | zeros(m,n) | 创建一个 m 行 n 列的零矩阵。(spzeros(m,n) 为空。) |
sparse(I,n,n) | Matrix(I,n,n) | 创建一个 n 行 n 列的单位矩阵。 |
sparse(A) | Array(S) | 在稠密和稀疏格式之间进行互换。 |
sprand(m,n,d) | rand(m,n) | 创建一个 m 行 n 列的随机矩阵(密度为 d),其中 iid 非零元素在半开区间 $[0, 1)$ 上均匀分布。 |
sprandn(m,n,d) | randn(m,n) | 创建一个具有 iid 非零元素的 *m*-by-*n* 随机矩阵(密度为 *d*),这些元素服从标准正态(高斯)分布。 |
sprandn(rng,m,n,d) | randn(rng,m,n) | 创建一个具有 iid 非零元素的 *m*-by-*n* 随机矩阵(密度为 *d*),这些元素使用 rng 随机数生成器生成。 |
SparseArrays API
SparseArrays.AbstractSparseArray
— 类型AbstractSparseArray{Tv,Ti,N}
N
维稀疏数组(或类似数组的类型)的超类型,其元素类型为 Tv
,索引类型为 Ti
。 SparseMatrixCSC
、SparseVector
和 SuiteSparse.CHOLMOD.Sparse
是此类型的子类型。
SparseArrays.AbstractSparseVector
— 类型AbstractSparseVector{Tv,Ti}
一维稀疏数组(或类似数组的类型)的超类型,其元素类型为 Tv
,索引类型为 Ti
。AbstractSparseArray{Tv,Ti,1}
的别名。
SparseArrays.AbstractSparseMatrix
— 类型AbstractSparseMatrix{Tv,Ti}
二维稀疏数组(或类似数组的类型)的超类型,其元素类型为 Tv
,索引类型为 Ti
。AbstractSparseArray{Tv,Ti,2}
的别名。
SparseArrays.SparseVector
— 类型SparseVector{Tv,Ti<:Integer} <: AbstractSparseVector{Tv,Ti}
用于存储稀疏向量的向量类型。可以通过传递向量的长度、非零索引的 *排序* 向量和非零值的向量来创建。
例如,向量 [5, 6, 0, 7]
可以表示为
SparseVector(4, [1, 2, 4], [5, 6, 7])
这表示索引 1 处的元素为 5,索引 2 处的元素为 6,索引 3 处的元素为 zero(Int)
,索引 4 处的元素为 7。
使用 sparse
从密集向量直接创建稀疏向量可能更方便,例如
sparse([5, 6, 0, 7])
生成相同的稀疏向量。
SparseArrays.SparseMatrixCSC
— 类型SparseMatrixCSC{Tv,Ti<:Integer} <: AbstractSparseMatrixCSC{Tv,Ti}
用于以 压缩稀疏列 格式存储稀疏矩阵的矩阵类型。构造 SparseMatrixCSC 的标准方法是通过 sparse
函数。另请参阅 spzeros
、spdiagm
和 sprand
.
SparseArrays.sparse
— 函数sparse(A)
将 AbstractMatrix A
转换为稀疏矩阵。
示例
julia> A = Matrix(1.0I, 3, 3)
3×3 Matrix{Float64}:
1.0 0.0 0.0
0.0 1.0 0.0
0.0 0.0 1.0
julia> sparse(A)
3×3 SparseMatrixCSC{Float64, Int64} with 3 stored entries:
1.0 ⋅ ⋅
⋅ 1.0 ⋅
⋅ ⋅ 1.0
sparse(I, J, V,[ m, n, combine])
创建一个 m x n
维的稀疏矩阵 S
,使得 S[I[k], J[k]] = V[k]
。combine
函数用于组合重复项。如果未指定 m
和 n
,则分别设置为 maximum(I)
和 maximum(J)
。如果未提供 combine
函数,则 combine
默认设置为 +
,除非 V
的元素是布尔值,在这种情况下,combine
默认设置为 |
。I
的所有元素必须满足 1 <= I[k] <= m
,J
的所有元素必须满足 1 <= J[k] <= n
。(I
、J
、V
)中的数值零将保留为结构性非零值;要删除数值零,请使用 dropzeros!
.
有关其他文档和专家驱动程序,请参阅 SparseArrays.sparse!
。
示例
julia> Is = [1; 2; 3];
julia> Js = [1; 2; 3];
julia> Vs = [1; 2; 3];
julia> sparse(Is, Js, Vs)
3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:
1 ⋅ ⋅
⋅ 2 ⋅
⋅ ⋅ 3
SparseArrays.sparse!
— 函数sparse!(I::AbstractVector{Ti}, J::AbstractVector{Ti}, V::AbstractVector{Tv},
m::Integer, n::Integer, combine, klasttouch::Vector{Ti},
csrrowptr::Vector{Ti}, csrcolval::Vector{Ti}, csrnzval::Vector{Tv},
[csccolptr::Vector{Ti}], [cscrowval::Vector{Ti}, cscnzval::Vector{Tv}] ) where {Tv,Ti<:Integer}
sparse
的父级和专家驱动程序;有关基本用法,请参阅 sparse
。此方法允许用户为 sparse
的中间对象和结果提供预分配的存储空间,如下所述。此功能使从坐标表示中更有效地连续构建 SparseMatrixCSC
成为可能,并且还使无需额外成本即可提取结果转置的未排序列表示成为可能。
此方法包括三个主要步骤:(1)将提供的坐标表示计数排序到包含重复项的未排序行 CSR 形式。 (2) 扫描 CSR 形式,同时计算所需的 CSC 形式的列指针数组,检测重复项,并重新打包具有组合重复项的 CSR 形式;此阶段产生没有重复项的未排序行 CSR 形式。(3) 将前面的 CSR 形式计数排序到没有重复项的完全排序的 CSC 形式。
输入数组 csrrowptr
、csrcolval
和 csrnzval
构成中间 CSR 形式的存储空间,需要 length(csrrowptr) >= m + 1
、length(csrcolval) >= length(I)
和 length(csrnzval >= length(I))
。输入数组 klasttouch
(第二阶段的工作区)需要 length(klasttouch) >= n
。可选输入数组 csccolptr
、cscrowval
和 cscnzval
构成返回的 CSC 形式 S
的存储空间。如果需要,这些数组将自动调整大小以满足 length(csccolptr) = n + 1
、length(cscrowval) = nnz(S)
和 length(cscnzval) = nnz(S)
;因此,如果 nnz(S)
在一开始未知,则传入适当类型的空向量(分别为 Vector{Ti}()
和 Vector{Tv}()
)就足够了,或者调用忽略 cscrowval
和 cscnzval
的 sparse!
方法。
返回时,csrrowptr
、csrcolval
和 csrnzval
包含结果转置的未排序列表示。
您可以将输入数组的存储空间(I
、J
、V
)重新用于输出数组(csccolptr
、cscrowval
、cscnzval
)。例如,您可以调用 sparse!(I, J, V, csrrowptr, csrcolval, csrnzval, I, J, V)
。请注意,它们将调整大小以满足上述条件。
为了效率起见,此方法除了 1 <= I[k] <= m
和 1 <= J[k] <= n
之外不执行任何参数检查。谨慎使用。在 --check-bounds=yes
的情况下进行测试是明智的。
此方法在 O(m, n, length(I))
时间内运行。F. Gustavson 的 HALFPERM 算法“稀疏矩阵的两种快速算法:乘法和置换转置”,ACM TOMS 4(3), 250-269 (1978) 启发了此方法对一对计数排序的使用。
SparseArrays.sparse!(I, J, V, [m, n, combine]) -> SparseMatrixCSC
sparse!
的变体,它将输入向量(I
、J
、V
)重新用于最终的矩阵存储。构建后,输入向量将与矩阵缓冲区别名;S.colptr === I
、S.rowval === J
和 S.nzval === V
成立,并且它们将根据需要调整大小。
请注意,某些工作缓冲区仍然会分配。具体来说,此方法是 sparse!(I, J, V, m, n, combine, klasttouch, csrrowptr, csrcolval, csrnzval, csccolptr, cscrowval, cscnzval)
的便利包装器,其中此方法分配适当大小的 klasttouch
、csrrowptr
、csrcolval
和 csrnzval
,但将 I
、J
和 V
重新用于 csccolptr
、cscrowval
和 cscnzval
。
参数 m
、n
和 combine
分别默认为 maximum(I)
、maximum(J)
和 +
。
此方法需要 Julia 版本 1.10 或更高版本。
SparseArrays.sparsevec
— 函数sparsevec(I, V, [m, combine])
创建一个长度为 m
的稀疏向量 S
,使得 S[I[k]] = V[k]
。重复项使用 combine
函数组合,如果未提供 combine
参数,则该函数默认为 +
,除非 V
的元素是布尔值,在这种情况下,combine
默认设置为 |
。
示例
julia> II = [1, 3, 3, 5]; V = [0.1, 0.2, 0.3, 0.2];
julia> sparsevec(II, V)
5-element SparseVector{Float64, Int64} with 3 stored entries:
[1] = 0.1
[3] = 0.5
[5] = 0.2
julia> sparsevec(II, V, 8, -)
8-element SparseVector{Float64, Int64} with 3 stored entries:
[1] = 0.1
[3] = -0.1
[5] = 0.2
julia> sparsevec([1, 3, 1, 2, 2], [true, true, false, false, false])
3-element SparseVector{Bool, Int64} with 3 stored entries:
[1] = 1
[2] = 0
[3] = 1
sparsevec(d::Dict, [m])
创建一个长度为 m
的稀疏向量,其中非零索引是字典中的键,非零值是字典中的值。
示例
julia> sparsevec(Dict(1 => 3, 2 => 2))
2-element SparseVector{Int64, Int64} with 2 stored entries:
[1] = 3
[2] = 2
sparsevec(A)
将向量 A
转换为长度为 m
的稀疏向量。
示例
julia> sparsevec([1.0, 2.0, 0.0, 0.0, 3.0, 0.0])
6-element SparseVector{Float64, Int64} with 3 stored entries:
[1] = 1.0
[2] = 2.0
[5] = 3.0
Base.similar
— 方法similar(A::AbstractSparseMatrixCSC{Tv,Ti}, [::Type{TvNew}, ::Type{TiNew}, m::Integer, n::Integer]) where {Tv,Ti}
基于给定的源 SparseMatrixCSC
,创建一个具有给定元素类型、索引类型和大小的未初始化可变数组。新的稀疏矩阵保持原始稀疏矩阵的结构,除非输出矩阵的维数与输出矩阵不同。
输出矩阵在与输入矩阵相同的位置具有零,但在非零位置具有未初始化的值。
SparseArrays.issparse
— 函数issparse(S)
如果 S
是稀疏的,则返回 true
,否则返回 false
。
示例
julia> sv = sparsevec([1, 4], [2.3, 2.2], 10)
10-element SparseVector{Float64, Int64} with 2 stored entries:
[1] = 2.3
[4] = 2.2
julia> issparse(sv)
true
julia> issparse(Array(sv))
false
SparseArrays.nnz
— 函数nnz(A)
返回稀疏数组中存储的(填充的)元素数量。
示例
julia> A = sparse(2I, 3, 3)
3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:
2 ⋅ ⋅
⋅ 2 ⋅
⋅ ⋅ 2
julia> nnz(A)
3
SparseArrays.findnz
— 函数findnz(A::SparseMatrixCSC)
返回一个元组 (I, J, V)
,其中 I
和 J
是稀疏矩阵 A
中存储的(“结构性非零”)值的行列索引,V
是值的向量。
示例
julia> A = sparse([1 2 0; 0 0 3; 0 4 0])
3×3 SparseMatrixCSC{Int64, Int64} with 4 stored entries:
1 2 ⋅
⋅ ⋅ 3
⋅ 4 ⋅
julia> findnz(A)
([1, 1, 3, 2], [1, 2, 2, 3], [1, 2, 4, 3])
SparseArrays.spzeros
— 函数spzeros([type,]m[,n])
创建一个长度为 m
的稀疏向量或大小为 m x n
的稀疏矩阵。此稀疏数组将不包含任何非零值。在构造期间不会为非零值分配存储空间。如果未指定类型,则类型默认为 Float64
.
示例
julia> spzeros(3, 3)
3×3 SparseMatrixCSC{Float64, Int64} with 0 stored entries:
⋅ ⋅ ⋅
⋅ ⋅ ⋅
⋅ ⋅ ⋅
julia> spzeros(Float32, 4)
4-element SparseVector{Float32, Int64} with 0 stored entries
spzeros([type], I::AbstractVector, J::AbstractVector, [m, n])
创建一个 m x n
维的稀疏矩阵 S
,在 S[I[k], J[k]]
处具有结构性零。
此方法可用于构建矩阵的稀疏性模式,并且比使用例如 sparse(I, J, zeros(length(I)))
更有效。
有关其他文档和专家驱动程序,请参阅 SparseArrays.spzeros!
。
此方法需要 Julia 版本 1.10 或更高版本。
SparseArrays.spzeros!
— 函数spzeros!(::Type{Tv}, I::AbstractVector{Ti}, J::AbstractVector{Ti}, m::Integer, n::Integer,
klasttouch::Vector{Ti}, csrrowptr::Vector{Ti}, csrcolval::Vector{Ti},
[csccolptr::Vector{Ti}], [cscrowval::Vector{Ti}, cscnzval::Vector{Tv}]) where {Tv,Ti<:Integer}
spzeros(I, J)
的父级和专家驱动程序,允许用户为中间对象提供预分配的存储空间。此方法与 spzeros
的关系如同 SparseArrays.sparse!
与 sparse
的关系。有关详细信息和所需缓冲区长度,请参阅 SparseArrays.sparse!
的文档。
此方法需要 Julia 版本 1.10 或更高版本。
SparseArrays.spzeros!(::Type{Tv}, I, J, [m, n]) -> SparseMatrixCSC{Tv}
spzeros!
的变体,它将输入向量 I
和 J
重新用于最终的矩阵存储。构建后,输入向量将与矩阵缓冲区别名;S.colptr === I
和 S.rowval === J
成立,并且它们将根据需要调整大小。
请注意,某些工作缓冲区仍然会分配。具体来说,此方法是 spzeros!(Tv, I, J, m, n, klasttouch, csrrowptr, csrcolval, csccolptr, cscrowval)
的便利包装器,其中此方法分配适当大小的 klasttouch
、csrrowptr
和 csrcolval
,但将 I
和 J
重新用于 csccolptr
和 cscrowval
。
参数 m
和 n
分别默认为 maximum(I)
和 maximum(J)
。
此方法需要 Julia 版本 1.10 或更高版本。
SparseArrays.spdiagm
— 函数spdiagm(kv::Pair{<:Integer,<:AbstractVector}...)
spdiagm(m::Integer, n::Integer, kv::Pair{<:Integer,<:AbstractVector}...)
从向量和对角线的 Pair
构造一个稀疏对角矩阵。每个向量 kv.second
将放置在 kv.first
对角线上。默认情况下,矩阵是正方形的,其大小是从 kv
推断出来的,但可以通过将 m,n
作为第一个参数传递来指定非正方形大小 m
×n
(根据需要用零填充)。
示例
julia> spdiagm(-1 => [1,2,3,4], 1 => [4,3,2,1])
5×5 SparseMatrixCSC{Int64, Int64} with 8 stored entries:
⋅ 4 ⋅ ⋅ ⋅
1 ⋅ 3 ⋅ ⋅
⋅ 2 ⋅ 2 ⋅
⋅ ⋅ 3 ⋅ 1
⋅ ⋅ ⋅ 4 ⋅
spdiagm(v::AbstractVector)
spdiagm(m::Integer, n::Integer, v::AbstractVector)
使用向量元素作为对角元素构建稀疏矩阵。默认情况下(没有给定的m
和n
),矩阵为方阵,其大小由length(v)
给出,但可以通过将m
和n
作为第一个参数传递来指定非方形大小m
×n
。
这些函数需要至少 Julia 1.6。
示例
julia> spdiagm([1,2,3])
3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:
1 ⋅ ⋅
⋅ 2 ⋅
⋅ ⋅ 3
julia> spdiagm(sparse([1,0,3]))
3×3 SparseMatrixCSC{Int64, Int64} with 2 stored entries:
1 ⋅ ⋅
⋅ ⋅ ⋅
⋅ ⋅ 3
SparseArrays.sparse_hcat
— 函数sparse_hcat(A...)
沿维度 2 连接。返回一个 SparseMatrixCSC 对象。
此方法在 Julia 1.8 中添加。它模拟了以前的连接行为,其中使用来自 LinearAlgebra.jl 的专门“稀疏”矩阵类型的连接即使在没有任何 SparseArray 参数的情况下也会自动产生稀疏输出。
SparseArrays.sparse_vcat
— 函数sparse_vcat(A...)
沿维度 1 连接。返回一个 SparseMatrixCSC 对象。
此方法在 Julia 1.8 中添加。它模拟了以前的连接行为,其中使用来自 LinearAlgebra.jl 的专门“稀疏”矩阵类型的连接即使在没有任何 SparseArray 参数的情况下也会自动产生稀疏输出。
SparseArrays.sparse_hvcat
— 函数sparse_hvcat(rows::Tuple{Vararg{Int}}, values...)
一次调用稀疏水平和垂直连接。此函数用于块矩阵语法。第一个参数指定每个块行中要连接的参数数量。
此方法在 Julia 1.8 中添加。它模拟了以前的连接行为,其中使用来自 LinearAlgebra.jl 的专门“稀疏”矩阵类型的连接即使在没有任何 SparseArray 参数的情况下也会自动产生稀疏输出。
SparseArrays.blockdiag
— 函数blockdiag(A...)
沿块对角线连接矩阵。目前只对稀疏矩阵实现。
示例
julia> blockdiag(sparse(2I, 3, 3), sparse(4I, 2, 2))
5×5 SparseMatrixCSC{Int64, Int64} with 5 stored entries:
2 ⋅ ⋅ ⋅ ⋅
⋅ 2 ⋅ ⋅ ⋅
⋅ ⋅ 2 ⋅ ⋅
⋅ ⋅ ⋅ 4 ⋅
⋅ ⋅ ⋅ ⋅ 4
SparseArrays.sprand
— 函数sprand([rng],[T::Type],m,[n],p::AbstractFloat)
sprand([rng],m,[n],p::AbstractFloat,[rfn=rand])
创建一个随机长度为m
的稀疏向量或m
乘n
的稀疏矩阵,其中任何元素为非零的概率独立地由p
给出(因此非零的平均密度也正好为p
)。可选的rng
参数指定一个随机数生成器,请参见随机数。可选的T
参数指定元素类型,默认为Float64
。
默认情况下,非零值使用rand
函数从均匀分布中采样,即由rand(T)
或rand(rng, T)
给出(如果提供了rng
);对于默认的T=Float64
,这对应于在[0,1)
中均匀采样的非零值。
您可以通过传递自定义rfn
函数而不是rand
来从不同的分布中采样非零值。这应该是一个函数rfn(k)
,它返回从所需分布中采样的k
个随机数的数组;或者,如果提供了rng
,它应该是一个函数rfn(rng, k)
。
示例
julia> sprand(Bool, 2, 2, 0.5)
2×2 SparseMatrixCSC{Bool, Int64} with 2 stored entries:
1 1
⋅ ⋅
julia> sprand(Float64, 3, 0.75)
3-element SparseVector{Float64, Int64} with 2 stored entries:
[1] = 0.795547
[2] = 0.49425
SparseArrays.sprandn
— 函数sprandn([rng][,Type],m[,n],p::AbstractFloat)
创建一个长度为m
的随机稀疏向量或大小为m
乘n
的稀疏矩阵,其中任何条目为非零的指定(独立)概率为p
,其中非零值从正态分布中采样。可选的rng
参数指定一个随机数生成器,请参见随机数。
指定输出元素类型Type
需要至少 Julia 1.1。
示例
julia> sprandn(2, 2, 0.75)
2×2 SparseMatrixCSC{Float64, Int64} with 3 stored entries:
-1.20577 ⋅
0.311817 -0.234641
SparseArrays.nonzeros
— 函数nonzeros(A)
返回稀疏数组A
中结构性非零值的向量。这包括显式存储在稀疏数组中的零。返回的向量直接指向A
的内部非零存储,并且对返回的向量的任何修改也将修改A
。请参见rowvals
和nzrange
。
示例
julia> A = sparse(2I, 3, 3)
3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:
2 ⋅ ⋅
⋅ 2 ⋅
⋅ ⋅ 2
julia> nonzeros(A)
3-element Vector{Int64}:
2
2
2
SparseArrays.rowvals
— 函数rowvals(A::AbstractSparseMatrixCSC)
返回A
的行索引向量。对返回的向量的任何修改也将修改A
。提供对行索引如何在内部存储的访问在与迭代结构性非零值结合使用时可能很有用。另请参见nonzeros
和nzrange
。
示例
julia> A = sparse(2I, 3, 3)
3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:
2 ⋅ ⋅
⋅ 2 ⋅
⋅ ⋅ 2
julia> rowvals(A)
3-element Vector{Int64}:
1
2
3
SparseArrays.nzrange
— 函数nzrange(A::AbstractSparseMatrixCSC, col::Integer)
返回稀疏矩阵列的结构性非零值的索引范围。结合nonzeros
和rowvals
,这允许方便地迭代稀疏矩阵
A = sparse(I,J,V)
rows = rowvals(A)
vals = nonzeros(A)
m, n = size(A)
for j = 1:n
for i in nzrange(A, j)
row = rows[i]
val = vals[i]
# perform sparse wizardry...
end
end
向矩阵添加或删除非零元素可能会使nzrange
失效,在迭代时不应该修改矩阵。
nzrange(x::SparseVectorUnion, col)
给出稀疏向量的结构性非零值的索引范围。列索引col
被忽略(假定为1
)。
SparseArrays.droptol!
— 函数droptol!(A::AbstractSparseMatrixCSC, tol)
从A
中删除绝对值小于或等于tol
的存储值。
droptol!(x::AbstractCompressedVector, tol)
从x
中删除绝对值小于或等于tol
的存储值。
SparseArrays.dropzeros!
— 函数SparseArrays.dropzeros
— 函数dropzeros(A::AbstractSparseMatrixCSC;)
生成A
的副本,并从该副本中删除存储的数值零。
有关就地版本和算法信息,请参见dropzeros!
。
示例
julia> A = sparse([1, 2, 3], [1, 2, 3], [1.0, 0.0, 1.0])
3×3 SparseMatrixCSC{Float64, Int64} with 3 stored entries:
1.0 ⋅ ⋅
⋅ 0.0 ⋅
⋅ ⋅ 1.0
julia> dropzeros(A)
3×3 SparseMatrixCSC{Float64, Int64} with 2 stored entries:
1.0 ⋅ ⋅
⋅ ⋅ ⋅
⋅ ⋅ 1.0
dropzeros(x::AbstractCompressedVector)
生成x
的副本,并从该副本中删除数值零。
有关就地版本和算法信息,请参见dropzeros!
。
示例
julia> A = sparsevec([1, 2, 3], [1.0, 0.0, 1.0])
3-element SparseVector{Float64, Int64} with 3 stored entries:
[1] = 1.0
[2] = 0.0
[3] = 1.0
julia> dropzeros(A)
3-element SparseVector{Float64, Int64} with 2 stored entries:
[1] = 1.0
[3] = 1.0
SparseArrays.permute
— 函数permute(A::AbstractSparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer},
q::AbstractVector{<:Integer}) where {Tv,Ti}
双边置换A
,返回PAQ
(A[p,q]
)。列置换q
的长度必须与A
的列数匹配(length(q) == size(A, 2)
)。行置换p
的长度必须与A
的行数匹配(length(p) == size(A, 1)
)。
对于专家驾驶员和更多信息,请参见permute!
。
示例
julia> A = spdiagm(0 => [1, 2, 3, 4], 1 => [5, 6, 7])
4×4 SparseMatrixCSC{Int64, Int64} with 7 stored entries:
1 5 ⋅ ⋅
⋅ 2 6 ⋅
⋅ ⋅ 3 7
⋅ ⋅ ⋅ 4
julia> permute(A, [4, 3, 2, 1], [1, 2, 3, 4])
4×4 SparseMatrixCSC{Int64, Int64} with 7 stored entries:
⋅ ⋅ ⋅ 4
⋅ ⋅ 3 7
⋅ 2 6 ⋅
1 5 ⋅ ⋅
julia> permute(A, [1, 2, 3, 4], [4, 3, 2, 1])
4×4 SparseMatrixCSC{Int64, Int64} with 7 stored entries:
⋅ ⋅ 5 1
⋅ 6 2 ⋅
7 3 ⋅ ⋅
4 ⋅ ⋅ ⋅
Base.permute!
— 方法permute!(X::AbstractSparseMatrixCSC{Tv,Ti}, A::AbstractSparseMatrixCSC{Tv,Ti},
p::AbstractVector{<:Integer}, q::AbstractVector{<:Integer},
[C::AbstractSparseMatrixCSC{Tv,Ti}]) where {Tv,Ti}
双边置换A
,将结果PAQ
(A[p,q]
)存储在X
中。如果存在,则在可选参数C
中存储中间结果(AQ)^T
(transpose(A[:,q])
)。要求X
、A
以及(如果存在)C
彼此不别名;要将结果PAQ
存储回A
,请使用以下缺少X
的方法
permute!(A::AbstractSparseMatrixCSC{Tv,Ti}, p::AbstractVector{<:Integer},
q::AbstractVector{<:Integer}[, C::AbstractSparseMatrixCSC{Tv,Ti},
[workcolptr::Vector{Ti}]]) where {Tv,Ti}
X
的维度必须与A
的维度匹配(size(X, 1) == size(A, 1)
和size(X, 2) == size(A, 2)
),并且X
必须有足够的存储空间来容纳A
中的所有分配条目(length(rowvals(X)) >= nnz(A)
和length(nonzeros(X)) >= nnz(A)
)。列置换q
的长度必须与A
的列数匹配(length(q) == size(A, 2)
)。行置换p
的长度必须与A
的行数匹配(length(p) == size(A, 1)
)。
C
的维度必须与transpose(A)
的维度匹配(size(C, 1) == size(A, 2)
和size(C, 2) == size(A, 1)
),并且C
必须有足够的存储空间来容纳A
中的所有分配条目(length(rowvals(C)) >= nnz(A)
和length(nonzeros(C)) >= nnz(A)
)。
有关更多(算法)信息,以及针对这些方法的版本,这些版本放弃了参数检查,请参见(未导出)的父方法unchecked_noalias_permute!
和unchecked_aliasing_permute!
。
另请参见permute
。
SparseArrays.halfperm!
— 函数halfperm!(X::AbstractSparseMatrixCSC{Tv,Ti}, A::AbstractSparseMatrixCSC{TvA,Ti},
q::AbstractVector{<:Integer}, f::Function = identity) where {Tv,TvA,Ti}
列置换并转置A
,同时将f
应用于A
的每个条目,将结果(f(A)Q)^T
(map(f, transpose(A[:,q]))
)存储在X
中。
X
的元素类型Tv
必须与f(::TvA)
匹配,其中TvA
是A
的元素类型。X
的维度必须与transpose(A)
的维度匹配(size(X, 1) == size(A, 2)
和size(X, 2) == size(A, 1)
),并且X
必须有足够的存储空间来容纳A
中的所有分配条目(length(rowvals(X)) >= nnz(A)
和length(nonzeros(X)) >= nnz(A)
)。列置换q
的长度必须与A
的列数匹配(length(q) == size(A, 2)
)。
此方法是执行SparseMatrixCSC
的转置和置换操作的几种方法的父方法。由于此方法不执行任何参数检查,因此建议优先使用更安全的子方法([c]transpose[!]
、permute[!]
)而不是直接使用。
此方法实现了 F. Gustavson 在“两种用于稀疏矩阵的快速算法:乘法和置换转置”ACM TOMS 4(3), 250-269 (1978) 中描述的HALFPERM
算法。该算法在O(size(A, 1), size(A, 2), nnz(A))
时间内运行,并且除了传递的空间之外不需要任何空间。
SparseArrays.ftranspose!
— 函数ftranspose!(X::AbstractSparseMatrixCSC{Tv,Ti}, A::AbstractSparseMatrixCSC{Tv,Ti}, f::Function) where {Tv,Ti}
转置A
并将其存储在X
中,同时将函数f
应用于非零元素。不会删除由f
创建的零。size(X)
必须等于size(transpose(A))
。除了调整X
的rowval
和nzval
的大小(如果需要)之外,不会分配任何额外的内存。
请参见halfperm!
值得注意的外部包
还有几个其他 Julia 包提供了应该提到的稀疏矩阵实现
SuiteSparseGraphBLAS.jl 是快速、多线程 SuiteSparse:GraphBLAS C 库的包装器。在 CPU 上,这通常是最快的选择,通常比 MKLSparse 性能高得多。
SparseMatricesCSR.jl 提供了压缩稀疏行 (CSR) 格式的 Julia 原生实现。
MKLSparse.jl 使用英特尔的 MKL 库加速 SparseArrays 稀疏-密集矩阵操作。
SparseArrayKit.jl 可用于多维稀疏数组。
LuxurySparse.jl 提供静态稀疏数组格式,以及坐标格式。
ExtendableSparse.jl 使用延迟方法来处理新的存储索引,从而可以快速插入稀疏矩阵。