稀疏数组

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

sparsesparsevec 函数的逆函数是 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)创建一个 mn 列的零矩阵。(spzeros(m,n) 为空。)
sparse(I,n,n)Matrix(I,n,n)创建一个 nn 列的单位矩阵。
sparse(A)Array(S)在稠密和稀疏格式之间进行互换。
sprand(m,n,d)rand(m,n)创建一个 mn 列的随机矩阵(密度为 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.AbstractSparseVector类型
AbstractSparseVector{Tv,Ti}

一维稀疏数组(或类似数组的类型)的超类型,其元素类型为 Tv,索引类型为 TiAbstractSparseArray{Tv,Ti,1} 的别名。

来源
SparseArrays.AbstractSparseMatrix类型
AbstractSparseMatrix{Tv,Ti}

二维稀疏数组(或类似数组的类型)的超类型,其元素类型为 Tv,索引类型为 TiAbstractSparseArray{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.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 函数用于组合重复项。如果未指定 mn,则分别设置为 maximum(I)maximum(J)。如果未提供 combine 函数,则 combine 默认设置为 +,除非 V 的元素是布尔值,在这种情况下,combine 默认设置为 |I 的所有元素必须满足 1 <= I[k] <= mJ 的所有元素必须满足 1 <= J[k] <= n。(IJV)中的数值零将保留为结构性非零值;要删除数值零,请使用 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 形式。

输入数组 csrrowptrcsrcolvalcsrnzval 构成中间 CSR 形式的存储空间,需要 length(csrrowptr) >= m + 1length(csrcolval) >= length(I)length(csrnzval >= length(I))。输入数组 klasttouch(第二阶段的工作区)需要 length(klasttouch) >= n。可选输入数组 csccolptrcscrowvalcscnzval 构成返回的 CSC 形式 S 的存储空间。如果需要,这些数组将自动调整大小以满足 length(csccolptr) = n + 1length(cscrowval) = nnz(S)length(cscnzval) = nnz(S);因此,如果 nnz(S) 在一开始未知,则传入适当类型的空向量(分别为 Vector{Ti}()Vector{Tv}())就足够了,或者调用忽略 cscrowvalcscnzvalsparse! 方法。

返回时,csrrowptrcsrcolvalcsrnzval 包含结果转置的未排序列表示。

您可以将输入数组的存储空间(IJV)重新用于输出数组(csccolptrcscrowvalcscnzval)。例如,您可以调用 sparse!(I, J, V, csrrowptr, csrcolval, csrnzval, I, J, V)。请注意,它们将调整大小以满足上述条件。

为了效率起见,此方法除了 1 <= I[k] <= m1 <= 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! 的变体,它将输入向量(IJV)重新用于最终的矩阵存储。构建后,输入向量将与矩阵缓冲区别名;S.colptr === IS.rowval === JS.nzval === V 成立,并且它们将根据需要调整大小。

请注意,某些工作缓冲区仍然会分配。具体来说,此方法是 sparse!(I, J, V, m, n, combine, klasttouch, csrrowptr, csrcolval, csrnzval, csccolptr, cscrowval, cscnzval) 的便利包装器,其中此方法分配适当大小的 klasttouchcsrrowptrcsrcolvalcsrnzval,但将 IJV 重新用于 csccolptrcscrowvalcscnzval

参数 mncombine 分别默认为 maximum(I)maximum(J)+

Julia 1.10

此方法需要 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),其中 IJ 是稀疏矩阵 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

此方法需要 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

此方法需要 Julia 版本 1.10 或更高版本。

来源
SparseArrays.spzeros!(::Type{Tv}, I, J, [m, n]) -> SparseMatrixCSC{Tv}

spzeros! 的变体,它将输入向量 IJ 重新用于最终的矩阵存储。构建后,输入向量将与矩阵缓冲区别名;S.colptr === IS.rowval === J 成立,并且它们将根据需要调整大小。

请注意,某些工作缓冲区仍然会分配。具体来说,此方法是 spzeros!(Tv, I, J, m, n, klasttouch, csrrowptr, csrcolval, csccolptr, cscrowval) 的便利包装器,其中此方法分配适当大小的 klasttouchcsrrowptrcsrcolval,但将 IJ 重新用于 csccolptrcscrowval

参数 mn 分别默认为 maximum(I)maximum(J)

Julia 1.10

此方法需要 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)

使用向量元素作为对角元素构建稀疏矩阵。默认情况下(没有给定的mn),矩阵为方阵,其大小由length(v)给出,但可以通过将mn作为第一个参数传递来指定非方形大小m×n

Julia 1.6

这些函数需要至少 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

此方法在 Julia 1.8 中添加。它模拟了以前的连接行为,其中使用来自 LinearAlgebra.jl 的专门“稀疏”矩阵类型的连接即使在没有任何 SparseArray 参数的情况下也会自动产生稀疏输出。

来源
SparseArrays.sparse_vcat函数
sparse_vcat(A...)

沿维度 1 连接。返回一个 SparseMatrixCSC 对象。

Julia 1.8

此方法在 Julia 1.8 中添加。它模拟了以前的连接行为,其中使用来自 LinearAlgebra.jl 的专门“稀疏”矩阵类型的连接即使在没有任何 SparseArray 参数的情况下也会自动产生稀疏输出。

来源
SparseArrays.sparse_hvcat函数
sparse_hvcat(rows::Tuple{Vararg{Int}}, values...)

一次调用稀疏水平和垂直连接。此函数用于块矩阵语法。第一个参数指定每个块行中要连接的参数数量。

Julia 1.8

此方法在 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的稀疏向量或mn的稀疏矩阵,其中任何元素为非零的概率独立地由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的随机稀疏向量或大小为mn的稀疏矩阵,其中任何条目为非零的指定(独立)概率为p,其中非零值从正态分布中采样。可选的rng参数指定一个随机数生成器,请参见随机数

Julia 1.1

指定输出元素类型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。请参见rowvalsnzrange

示例

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。提供对行索引如何在内部存储的访问在与迭代结构性非零值结合使用时可能很有用。另请参见nonzerosnzrange

示例

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)

返回稀疏矩阵列的结构性非零值的索引范围。结合nonzerosrowvals,这允许方便地迭代稀疏矩阵

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!函数
dropzeros!(x::AbstractCompressedVector)

x中删除存储的数值零。

有关非就地版本,请参见dropzeros。有关算法信息,请参见fkeep!

来源
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,返回PAQA[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,将结果PAQA[p,q])存储在X中。如果存在,则在可选参数C中存储中间结果(AQ)^Ttranspose(A[:,q]))。要求XA以及(如果存在)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)^Tmap(f, transpose(A[:,q])))存储在X中。

X的元素类型Tv必须与f(::TvA)匹配,其中TvAA的元素类型。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))。除了调整Xrowvalnzval的大小(如果需要)之外,不会分配任何额外的内存。

请参见halfperm!

来源

值得注意的外部包

还有几个其他 Julia 包提供了应该提到的稀疏矩阵实现

  1. SuiteSparseGraphBLAS.jl 是快速、多线程 SuiteSparse:GraphBLAS C 库的包装器。在 CPU 上,这通常是最快的选择,通常比 MKLSparse 性能高得多。

  2. CUDA.jl 公开了CUSPARSE 库用于 GPU 稀疏矩阵操作。

  3. SparseMatricesCSR.jl 提供了压缩稀疏行 (CSR) 格式的 Julia 原生实现。

  4. MKLSparse.jl 使用英特尔的 MKL 库加速 SparseArrays 稀疏-密集矩阵操作。

  5. SparseArrayKit.jl 可用于多维稀疏数组。

  6. LuxurySparse.jl 提供静态稀疏数组格式,以及坐标格式。

  7. ExtendableSparse.jl 使用延迟方法来处理新的存储索引,从而可以快速插入稀疏矩阵。