Sparse Arrays

Julia 对稀疏向量和 sparse matricesSparseArrays 标准库模块中提供支持。稀疏数组是指包含足够多零的数组,将它们存储在特殊数据结构中可以节省空间和执行时间,相较于密集数组。

可以在 Noteworthy External Sparse Packages 中找到实现不同稀疏存储类型、多维稀疏数组等的外部包。

Compressed Sparse Column (CSC) Sparse Matrix Storage

在 Julia 中,稀疏矩阵存储在 Compressed Sparse Column (CSC) format 中。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  ⋅
 ⋅  ⋅  ⋅

Sparse Vector Storage

稀疏向量以与稀疏矩阵的压缩稀疏列格式相似的方式存储。在 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

关于 SparseMatrixCSCSparseVector 类型也可以包含显式存储的零。(参见 Sparse Matrix Storage。)

Sparse Vector and Matrix Constructors

创建稀疏数组的最简单方法是使用一个等同于 zeros 的函数,该函数是 Julia 提供的用于处理密集数组的函数。要生成稀疏数组,您可以使用相同的名称并加上 sp 前缀:

julia> spzeros(3)
3-element SparseVector{Float64, Int64} with 0 stored entries

sparse 函数通常是构造稀疏数组的便捷方法。例如,要构造一个稀疏矩阵,我们可以输入一个行索引向量 I、一个列索引向量 J 和一个存储值的向量 V(这也被称为 COO (coordinate) format)。然后,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

Sparse matrix operations

稀疏矩阵上的算术运算与密集矩阵上的运算相同。稀疏矩阵的索引、赋值和连接的方式与密集矩阵相同。索引操作,特别是赋值,在逐个元素执行时是昂贵的。在许多情况下,将稀疏矩阵转换为 (I,J,V) 格式可能更好,使用 findnz,在密集向量 (I,J,V) 中操作值或结构,然后重建稀疏矩阵。

Correspondence of dense and sparse methods

下表给出了稀疏矩阵上的内置方法与其对应的密集矩阵类型的方法之间的对应关系。一般来说,生成稀疏矩阵的方法与其密集对应物的不同之处在于,生成的矩阵遵循给定稀疏矩阵 S 的相同稀疏模式,或者生成的稀疏矩阵具有密度 d,即每个矩阵元素有概率 d 为非零。

详细信息可以在标准库参考的 Sparse Vectors and Matrices 部分找到。

SparseDenseDescription
spzeros(m,n)zeros(m,n)Creates a m-by-n matrix of zeros. (spzeros(m,n) is empty.)
sparse(I,n,n)Matrix(I,n,n)Creates a n-by-n identity matrix.
sparse(A)Array(S)Interconverts between dense and sparse formats.
sprand(m,n,d)rand(m,n)Creates a m-by-n random matrix (of density d) with iid non-zero elements distributed uniformly on the half-open interval $[0, 1)$.
sprandn(m,n,d)randn(m,n)Creates a m-by-n random matrix (of density d) with iid non-zero elements distributed according to the standard normal (Gaussian) distribution.
sprandn(rng,m,n,d)randn(rng,m,n)Creates a m-by-n random matrix (of density d) with iid non-zero elements generated with the rng random number generator

Sparse Linear Algebra

稀疏矩阵求解器调用来自 SuiteSparse 的函数。以下分解可用:

TypeDescription
CHOLMOD.FactorCholesky and LDLt factorizations
UMFPACK.UmfpackLULU factorization
SPQR.QRSparseQR factorization

这些因式分解在 Sparse Linear Algebra API section 中有更详细的描述:

  1. cholesky
  2. ldlt
  3. lu
  4. qr

SparseArrays API

SparseArrays.AbstractSparseVectorType
AbstractSparseVector{Tv,Ti}

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

source
SparseArrays.AbstractSparseMatrixType
AbstractSparseMatrix{Tv,Ti}

二维稀疏数组(或类似数组类型)的超类型,元素类型为 Tv,索引类型为 Ti。是 AbstractSparseArray{Tv,Ti,2} 的别名。

source
SparseArrays.SparseVectorType
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])

也会产生相同的稀疏向量。

source
SparseArrays.sparseFunction
sparse(A)

将抽象矩阵 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
source
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] <= 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
source
SparseArrays.sparse!Function
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}())即可,或者调用 sparse! 方法时忽略 cscrowvalcscnzval

返回时,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 在其论文 "Two fast algorithms for sparse matrices: multiplication and permuted transposition," ACM TOMS 4(3), 250-269 (1978) 中描述的 HALFPERM 算法启发了此方法使用一对计数排序。

source
SparseArrays.sparse!(I, J, V, [m, n, combine]) -> SparseMatrixCSC

sparse! 的变体,重新使用输入向量(IJV)作为最终矩阵存储。在构造后,输入向量将别名矩阵缓冲区;S.colptr === IS.rowval === J,和 S.nzval === V 成立,并且它们会根据需要进行 resize!

请注意,仍然会分配一些工作缓冲区。具体来说,此方法是 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 或更高版本。

source
SparseArrays.sparsevecFunction
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
source
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
source
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
source
Base.similarMethod
similar(A::AbstractSparseMatrixCSC{Tv,Ti}, [::Type{TvNew}, ::Type{TiNew}, m::Integer, n::Integer]) where {Tv,Ti}

创建一个未初始化的可变数组,具有给定的元素类型、索引类型和大小,基于给定的源 SparseMatrixCSC。新的稀疏矩阵保持原始稀疏矩阵的结构,除非输出矩阵的维度与输出不同。

输出矩阵在与输入相同的位置上有零,但在非零位置上有未初始化的值。

source
SparseArrays.issparseFunction
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
source
SparseArrays.nnzFunction
nnz(A)

返回稀疏数组中存储(填充)元素的数量。

示例

julia> A = sparse(2I, 3, 3)
3×3 SparseMatrixCSC{Int64, Int64} with 3 stored entries:
 2  ⋅  ⋅
 ⋅  2  ⋅
 ⋅  ⋅  2

julia> nnz(A)
3
source
SparseArrays.findnzFunction
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])
source
SparseArrays.spzerosFunction
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
source
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 或更高版本。

source
SparseArrays.spzeros!Function
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 或更高版本。

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

spzeros! 的变体,重新使用输入向量 IJ 作为最终矩阵存储。在构造后,输入向量将别名矩阵缓冲区;S.colptr === IS.rowval === J 成立,并且它们会根据需要进行 resize!

请注意,仍然会分配一些工作缓冲区。具体来说,此方法是 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 或更高版本。

source
SparseArrays.spdiagmFunction
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  ⋅
source
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
source
SparseArrays.sparse_hcatFunction
sparse_hcat(A...)

沿着维度 2 进行连接。返回一个 SparseMatrixCSC 对象。

Julia 1.8

此方法是在 Julia 1.8 中添加的。它模仿了之前的连接行为,其中与来自 LinearAlgebra.jl 的专用 "稀疏" 矩阵类型的连接在没有任何 SparseArray 参数的情况下自动产生稀疏输出。

source
SparseArrays.sparse_vcatFunction
sparse_vcat(A...)

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

Julia 1.8

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

source
SparseArrays.sparse_hvcatFunction
sparse_hvcat(rows::Tuple{Vararg{Int}}, values...)

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

Julia 1.8

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

source
SparseArrays.blockdiagFunction
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
source
SparseArrays.sprandFunction
sprand([rng],[T::Type],m,[n],p::AbstractFloat)
sprand([rng],m,[n],p::AbstractFloat,[rfn=rand])

创建一个随机长度为 m 的稀疏向量或 m x n 的稀疏矩阵,其中任何元素为非零的概率独立地由 p 给出(因此非零的平均密度也恰好为 p)。可选的 rng 参数指定一个随机数生成器,参见 Random Numbers。可选的 T 参数指定元素类型,默认为 Float64

默认情况下,非零值是从均匀分布中采样的,使用 rand 函数,即通过 rand(T),或者如果提供了 rng,则为 rand(rng, T);对于默认的 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
source
SparseArrays.sprandnFunction
sprandn([rng][,Type],m[,n],p::AbstractFloat)

创建一个长度为 m 的随机稀疏向量或大小为 m x n 的稀疏矩阵,具有指定的(独立的)概率 p,表示任何条目为非零的概率,其中非零值是从正态分布中抽样的。可选的 rng 参数指定一个随机数生成器,参见 Random Numbers

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
source
SparseArrays.nonzerosFunction
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
source
SparseArrays.rowvalsFunction
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
source
SparseArrays.nzrangeFunction
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]
      # 执行稀疏魔法...
   end
end
Warning

向矩阵添加或移除非零元素可能会使 nzrange 无效,在迭代时不应修改矩阵。

source
nzrange(x::SparseVectorUnion, col)

给出稀疏向量的结构非零值的索引范围。列索引 col 被忽略(假定为 1)。

source
SparseArrays.droptol!Function
droptol!(A::AbstractSparseMatrixCSC, tol)

A 中移除绝对值小于或等于 tol 的存储值。

source
droptol!(x::AbstractCompressedVector, tol)

x 中移除绝对值小于或等于 tol 的存储值。

source
SparseArrays.dropzeros!Function
dropzeros!(x::AbstractCompressedVector)

x 中移除存储的数值零。

有关不改变原始数据的版本,请参见 dropzeros。有关算法信息,请参见 fkeep!

source
SparseArrays.dropzerosFunction
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} 具有 3 个存储条目:
 1.0   ⋅    ⋅
  ⋅   0.0   ⋅
  ⋅    ⋅   1.0

julia> dropzeros(A)
3×3 SparseMatrixCSC{Float64, Int64} 具有 2 个存储条目:
 1.0   ⋅    ⋅
  ⋅    ⋅    ⋅
  ⋅    ⋅   1.0
source
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
source
SparseArrays.permuteFunction
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  ⋅  ⋅  ⋅
source
Base.permute!Method
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 中。如果存在,则将中间结果 (AQ)^T (transpose(A[:,q])) 存储在可选参数 C 中。要求 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.

source
SparseArrays.halfperm!Function
halfperm!(X::AbstractSparseMatrixCSC{Tv,Ti}, A::AbstractSparseMatrixCSC{TvA,Ti},
          q::AbstractVector{<:Integer}, f::Function = identity) where {Tv,TvA,Ti}

列置换并转置 A,同时对 A 的每个条目应用 f,将结果 (f(A)Q)^T (map(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 描述的 HALFPERM 算法,"Two fast algorithms for sparse matrices: multiplication and permuted transposition," ACM TOMS 4(3), 250-269 (1978)。该算法的运行时间为 O(size(A, 1), size(A, 2), nnz(A)),并且不需要超出传入的空间。

source
SparseArrays.ftranspose!Function
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!

source

Sparse Linear Algebra API

LinearAlgebra.choleskyFunction
cholesky(A, NoPivot(); check = true) -> Cholesky

计算稠密对称正定矩阵 A 的 Cholesky 分解,并返回一个 Cholesky 分解。矩阵 A 可以是一个 SymmetricHermitian AbstractMatrix,或者是一个 完全 对称或 Hermitian 的 AbstractMatrix

可以通过 F.LF.U 从分解 F 中获得三角形 Cholesky 因子,其中 A ≈ F.U' * F.U ≈ F.L * F.L'

对于 Cholesky 对象,提供以下函数:size\invdetlogdetisposdef

如果你有一个由于构造中的舍入误差而稍微非 Hermitian 的矩阵 A,请在将其传递给 cholesky 之前用 Hermitian(A) 将其包装,以便将其视为完全 Hermitian。

check = true 时,如果分解失败,将抛出错误。当 check = false 时,检查分解有效性的责任(通过 issuccess)在于用户。

示例

julia> A = [4. 12. -16.; 12. 37. -43.; -16. -43. 98.]
3×3 Matrix{Float64}:
   4.0   12.0  -16.0
  12.0   37.0  -43.0
 -16.0  -43.0   98.0

julia> C = cholesky(A)
Cholesky{Float64, Matrix{Float64}}
U factor:
3×3 UpperTriangular{Float64, Matrix{Float64}}:
 2.0  6.0  -8.0
  ⋅   1.0   5.0
  ⋅    ⋅    3.0

julia> C.U
3×3 UpperTriangular{Float64, Matrix{Float64}}:
 2.0  6.0  -8.0
  ⋅   1.0   5.0
  ⋅    ⋅    3.0

julia> C.L
3×3 LowerTriangular{Float64, Matrix{Float64}}:
  2.0   ⋅    ⋅
  6.0  1.0   ⋅
 -8.0  5.0  3.0

julia> C.L * C.U == A
true
source
cholesky(A, RowMaximum(); tol = 0.0, check = true) -> CholeskyPivoted

计算稠密对称半正定矩阵 A 的带主元的 Cholesky 分解,并返回一个 CholeskyPivoted 分解。矩阵 A 可以是 SymmetricHermitian AbstractMatrix,或者是 完全 对称或 Hermitian 的 AbstractMatrix

可以通过 F.LF.U 从分解 F 中获得三角 Cholesky 因子,以及通过 F.p 获得置换,其中 A[F.p, F.p] ≈ Ur' * Ur ≈ Lr * Lr',其中 Ur = F.U[1:F.rank, :]Lr = F.L[:, 1:F.rank],或者替代地 A ≈ Up' * Up ≈ Lp * Lp',其中 Up = F.U[1:F.rank, invperm(F.p)]Lp = F.L[invperm(F.p), 1:F.rank]

以下函数可用于 CholeskyPivoted 对象:size\invdetrank

参数 tol 决定了确定秩的容差。对于负值,容差为机器精度。

如果您有一个由于构造中的舍入误差而略微非 Hermitian 的矩阵 A,请在将其传递给 cholesky 之前用 Hermitian(A) 将其包装,以便将其视为完全 Hermitian。

check = true 时,如果分解失败,将抛出错误。当 check = false 时,检查分解有效性的责任(通过 issuccess)在于用户。

示例

julia> X = [1.0, 2.0, 3.0, 4.0];

julia> A = X * X';

julia> C = cholesky(A, RowMaximum(), check = false)
CholeskyPivoted{Float64, Matrix{Float64}, Vector{Int64}}
U factor with rank 1:
4×4 UpperTriangular{Float64, Matrix{Float64}}:
 4.0  2.0  3.0  1.0
  ⋅   0.0  6.0  2.0
  ⋅    ⋅   9.0  3.0
  ⋅    ⋅    ⋅   1.0
permutation:
4-element Vector{Int64}:
 4
 2
 3
 1

julia> C.U[1:C.rank, :]' * C.U[1:C.rank, :] ≈ A[C.p, C.p]
true

julia> l, u = C; # destructuring via iteration

julia> l == C.L && u == C.U
true
source
cholesky(A::SparseMatrixCSC; shift = 0.0, check = true, perm = nothing) -> CHOLMOD.Factor

计算稀疏正定矩阵 A 的 Cholesky 分解。A 必须是 SparseMatrixCSCSparseMatrixCSCSymmetric/Hermitian 视图。请注意,即使 A 没有类型标签,它仍然必须是对称的或厄米的。如果未给出 perm,则使用填充减少的置换。F = cholesky(A) 最常用于通过 F\b 求解方程组,但方法 diagdetlogdet 也为 F 定义。您还可以使用 F.L 提取单个因子。然而,由于默认情况下启用了主元,因子分解在内部表示为 A == P'*L*L'*P,其中 P 是置换矩阵;仅使用 L 而不考虑 P 将给出不正确的答案。为了包括置换的影响,通常更可取的是提取“组合”因子,如 PtL = F.PtL(相当于 P'*L)和 LtP = F.UP(相当于 L'*P)。

check = true 时,如果分解失败,将抛出错误。当 check = false 时,检查分解有效性的责任(通过 issuccess)由用户承担。

设置可选的 shift 关键字参数将计算 A+shift*I 的分解,而不是 A。如果提供了 perm 参数,它应该是 1:size(A,1) 的一个置换,给出要使用的顺序(而不是 CHOLMOD 的默认 AMD 顺序)。

示例

在以下示例中,使用的填充减少置换是 [3, 2, 1]。如果将 perm 设置为 1:3 以强制不进行置换,则因子中的非零元素数量为 6。

julia> A = [2 1 1; 1 2 0; 1 0 2]
3×3 Matrix{Int64}:
 2  1  1
 1  2  0
 1  0  2

julia> C = cholesky(sparse(A))
SparseArrays.CHOLMOD.Factor{Float64, Int64}
type:    LLt
method:  simplicial
maxnnz:  5
nnz:     5
success: true

julia> C.p
3-element Vector{Int64}:
 3
 2
 1

julia> L = sparse(C.L);

julia> Matrix(L)
3×3 Matrix{Float64}:
 1.41421   0.0       0.0
 0.0       1.41421   0.0
 0.707107  0.707107  1.0

julia> L * L' ≈ A[C.p, C.p]
true

julia> P = sparse(1:3, C.p, ones(3))
3×3 SparseMatrixCSC{Float64, Int64} with 3 stored entries:
  ⋅    ⋅   1.0
  ⋅   1.0   ⋅
 1.0   ⋅    ⋅

julia> P' * L * L' * P ≈ A
true

julia> C = cholesky(sparse(A), perm=1:3)
SparseArrays.CHOLMOD.Factor{Float64, Int64}
type:    LLt
method:  simplicial
maxnnz:  6
nnz:     6
success: true

julia> L = sparse(C.L);

julia> Matrix(L)
3×3 Matrix{Float64}:
 1.41421    0.0       0.0
 0.707107   1.22474   0.0
 0.707107  -0.408248  1.1547

julia> L * L' ≈ A
true
Note

此方法使用来自 SuiteSparse 的 CHOLMOD[ACM887][DavisHager2009] 库。CHOLMOD 仅支持单精度或双精度的实数或复数类型。输入矩阵如果不是这些元素类型,将适当地转换为这些类型。

CHOLMOD 的许多其他函数被封装但未从 Base.SparseArrays.CHOLMOD 模块导出。

source
LinearAlgebra.cholesky!Function
cholesky!(A::AbstractMatrix, NoPivot(); check = true) -> Cholesky

cholesky 相同,但通过覆盖输入 A 来节省空间,而不是创建副本。如果因分解产生的数字无法用 A 的元素类型表示,例如对于整数类型,将抛出 InexactError 异常。

示例

julia> A = [1 2; 2 50]
2×2 Matrix{Int64}:
 1   2
 2  50

julia> cholesky!(A)
ERROR: InexactError: Int64(6.782329983125268)
Stacktrace:
[...]
source
cholesky!(A::AbstractMatrix, RowMaximum(); tol = 0.0, check = true) -> CholeskyPivoted

cholesky 相同,但通过覆盖输入 A 来节省空间,而不是创建副本。如果因子分解产生的数字无法由 A 的元素类型表示,例如对于整数类型,将抛出 InexactError 异常。

source
cholesky!(F::CHOLMOD.Factor, A::SparseMatrixCSC; shift = 0.0, check = true) -> CHOLMOD.Factor

计算 A 的 Cholesky ($LL'$) 分解,重用符号分解 FA 必须是 SparseMatrixCSCSparseMatrixCSCSymmetric/ Hermitian 视图。请注意,即使 A 没有类型标签,它仍然必须是对称的或厄米的。

另请参见 cholesky

Note

此方法使用来自 SuiteSparse 的 CHOLMOD 库,仅支持单精度或双精度的实数或复数类型。输入矩阵如果不是这些元素类型,将会适当地转换为这些类型。

source
LinearAlgebra.lowrankupdateFunction
lowrankupdate(C::Cholesky, v::AbstractVector) -> CC::Cholesky

使用向量 v 更新 Cholesky 分解 C。如果 A = C.U'C.U,则 CC = cholesky(C.U'C.U + v*v'),但 CC 的计算仅使用 O(n^2) 操作。

source
lowrankupdate(F::CHOLMOD.Factor, C::AbstractArray) -> FF::CHOLMOD.Factor

获取给定 ALDLtLLt 分解 FA + C*C'LDLt 分解。

返回的因子始终是 LDLt 分解。

另见 lowrankupdate!, lowrankdowndate, lowrankdowndate!.

source
LinearAlgebra.lowrankupdate!Function
lowrankupdate!(C::Cholesky, v::AbstractVector) -> CC::Cholesky

使用向量 v 更新 Cholesky 分解 C。如果 A = C.U'C.U,则 CC = cholesky(C.U'C.U + v*v'),但 CC 的计算仅使用 O(n^2) 操作。输入的分解 C 会就地更新,以便在退出时 C == CC。在计算过程中,向量 v 会被销毁。

source
lowrankupdate!(F::CHOLMOD.Factor, C::AbstractArray)

ALDLtLLt 分解 F 更新为 A + C*C' 的分解。

LLt 分解会转换为 LDLt

另见 lowrankupdate, lowrankdowndate, lowrankdowndate!.

source
LinearAlgebra.lowrankdowndateFunction
lowrankdowndate(C::Cholesky, v::AbstractVector) -> CC::Cholesky

使用向量 v 对 Cholesky 分解 C 进行降维。如果 A = C.U'C.U,则 CC = cholesky(C.U'C.U - v*v'),但 CC 的计算仅使用 O(n^2) 的操作。

source
lowrankdowndate(F::CHOLMOD.Factor, C::AbstractArray) -> FF::CHOLMOD.Factor

给定 ALDLtLLt 分解 F,获取 A + C*C'LDLt 分解。

返回的因子始终是 LDLt 分解。

另见 lowrankdowndate!, lowrankupdate, lowrankupdate!.

source
LinearAlgebra.lowrankdowndate!Function
lowrankdowndate!(C::Cholesky, v::AbstractVector) -> CC::Cholesky

使用向量 v 对 Cholesky 分解 C 进行降维。如果 A = C.U'C.U,则 CC = cholesky(C.U'C.U - v*v'),但 CC 的计算仅使用 O(n^2) 操作。输入的分解 C 会就地更新,以便在退出时 C == CC。在计算过程中,向量 v 会被销毁。

source
lowrankdowndate!(F::CHOLMOD.Factor, C::AbstractArray)

ALDLtLLt 分解 F 更新为 A - C*C' 的分解。

LLt 分解会转换为 LDLt

另见 lowrankdowndate, lowrankupdate, lowrankupdate!.

source
SparseArrays.CHOLMOD.lowrankupdowndate!Function
lowrankupdowndate!(F::CHOLMOD.Factor, C::Sparse, update::Cint)

ALDLtLLt 分解 F 更新为 A ± C*C' 的分解。

如果使用保持稀疏性的分解,即 L*L' == P*A*P',则新因子将是 L*L' == P*A*P' + C'*C

updateCint(1) 表示 A + CC'Cint(0) 表示 A - CC'

source
LinearAlgebra.ldltFunction
ldlt(S::SymTridiagonal) -> LDLt

计算实对称三对角矩阵 SLDLt(即 $LDL^T$)分解,使得 S = L*Diagonal(d)*L',其中 L 是单位下三角矩阵,d 是一个向量。LDLt 分解 F = ldlt(S) 的主要用途是求解线性方程组 Sx = b,使用 F\b

另请参见 bunchkaufman,它是任意对称或厄米矩阵的类似但带有主元的分解。

示例

julia> S = SymTridiagonal([3., 4., 5.], [1., 2.])
3×3 SymTridiagonal{Float64, Vector{Float64}}:
 3.0  1.0   ⋅
 1.0  4.0  2.0
  ⋅   2.0  5.0

julia> ldltS = ldlt(S);

julia> b = [6., 7., 8.];

julia> ldltS \ b
3-element Vector{Float64}:
 1.7906976744186047
 0.627906976744186
 1.3488372093023255

julia> S \ b
3-element Vector{Float64}:
 1.7906976744186047
 0.627906976744186
 1.3488372093023255
source
ldlt(A::SparseMatrixCSC; shift = 0.0, check = true, perm=nothing) -> CHOLMOD.Factor

计算稀疏矩阵 A$LDL'$ 分解。A 必须是 SparseMatrixCSCSparseMatrixCSCSymmetric/Hermitian 视图。请注意,即使 A 没有类型标签,它仍然必须是对称或厄米的。使用填充减少的置换。F = ldlt(A) 最常用于求解方程组 A*x = b,使用 F\b。返回的分解对象 F 还支持方法 diagdetlogdetinv。您可以使用 F.LF 中提取单个因子。然而,由于默认情况下启用了主元,分解在内部表示为 A == P'*L*D*L'*P,其中 P 是置换矩阵;仅使用 L 而不考虑 P 将给出不正确的答案。为了包括置换的影响,通常更好地提取“组合”因子,如 PtL = F.PtL(相当于 P'*L)和 LtP = F.UP(相当于 L'*P)。支持的因子完整列表为 :L, :PtL, :D, :UP, :U, :LD, :DU, :PtLD, :DUP

check = true 时,如果分解失败,将抛出错误。当 check = false 时,检查分解有效性的责任(通过 issuccess)由用户承担。

设置可选的 shift 关键字参数计算 A+shift*I 的分解,而不是 A。如果提供了 perm 参数,它应该是 1:size(A,1) 的一个置换,给出要使用的顺序(而不是 CHOLMOD 的默认 AMD 顺序)。

Note

此方法使用来自 SuiteSparse 的 CHOLMOD[ACM887][DavisHager2009] 库。CHOLMOD 仅支持单精度或双精度的实数或复数类型。输入矩阵如果不是这些元素类型,将根据需要转换为这些类型。

CHOLMOD 的许多其他函数被封装但未从 Base.SparseArrays.CHOLMOD 模块导出。

source
LinearAlgebra.luFunction
lu(A::AbstractSparseMatrixCSC; check = true, q = nothing, control = get_umfpack_control()) -> F::UmfpackLU

计算稀疏矩阵 A 的 LU 分解。

对于元素类型为实数或复数的稀疏 A,返回类型 FUmfpackLU{Tv, Ti},其中 Tv = Float64ComplexF64,而 Ti 是整数类型(Int32Int64)。

check = true 时,如果分解失败,将抛出错误。当 check = false 时,检查分解有效性的责任(通过 issuccess)由用户承担。

置换 q 可以是一个置换向量或 nothing。如果未提供置换向量或 qnothing,则使用 UMFPACK 的默认值。如果置换不是零基的,则会制作一个零基的副本。

control 向量默认为 Julia SparseArrays 包的 UMFPACK 默认配置(注意:这已从 UMFPACK 默认值修改,以禁用迭代精炼),但可以通过传递长度为 UMFPACK_CONTROL 的向量进行更改,具体配置请参见 UMFPACK 手册。例如,要重新启用迭代精炼:

umfpack_control = SparseArrays.UMFPACK.get_umfpack_control(Float64, Int64) # 读取 Float64 稀疏矩阵的 Julia 默认配置
SparseArrays.UMFPACK.show_umf_ctrl(umfpack_control) # 可选 - 显示值
umfpack_control[SparseArrays.UMFPACK.JL_UMFPACK_IRSTEP] = 2.0 # 重新启用迭代精炼(2 是 UMFPACK 默认的最大迭代精炼步骤)

Alu = lu(A; control = umfpack_control)
x = Alu \ b   # 解 Ax = b,包括 UMFPACK 迭代精炼

可以通过索引访问分解 F 的各个组件:

组件描述
LLUL(下三角)部分
ULUU(上三角)部分
p右置换 Vector
q左置换 Vector
Rs缩放因子的 Vector
:(L,U,p,q,Rs) 组件

FA 之间的关系为

F.L*F.U == (F.Rs .* A)[F.p, F.q]

F 进一步支持以下函数:

另见 lu!

Note

lu(A::AbstractSparseMatrixCSC) 使用的是 UMFPACK[ACM832] 库,该库是 SuiteSparse 的一部分。由于该库仅支持元素为 Float64ComplexF64 的稀疏矩阵,lu 会将 A 转换为类型为 SparseMatrixCSC{Float64}SparseMatrixCSC{ComplexF64} 的副本。

source
lu(A, pivot = RowMaximum(); check = true, allowsingular = false) -> F::LU

计算 A 的 LU 分解。

check = true 时,如果分解失败,将抛出错误。当 check = false 时,检查分解有效性的责任(通过 issuccess)由用户承担。

默认情况下,当 check = true 时,如果分解产生有效因子,但上三角因子 U 的秩不足,也会抛出错误。可以通过传递 allowsingular = true 来更改此行为。

在大多数情况下,如果 AAbstractMatrix{T} 的子类型 S,且元素类型 T 支持 +-*/,则返回类型为 LU{T,S{T}}

一般来说,LU 分解涉及对矩阵行的排列(对应于下面描述的 F.p 输出),称为“主元选择”(因为它对应于选择哪个行包含“主元”,即 F.U 的对角元素)。可以通过可选的 pivot 参数选择以下主元选择策略:

  • RowMaximum()(默认):标准主元选择策略;主元对应于剩余待分解行中绝对值最大的元素。此主元选择策略要求元素类型也支持 abs<。 (这通常是浮点矩阵的唯一数值稳定选项。)
  • RowNonZero():主元对应于剩余待分解行中第一个非零元素。 (这对应于手动计算中的典型选择,对于支持 iszero 但不支持 abs< 的更一般的代数数类型也很有用。)
  • NoPivot():关闭主元选择(如果在主元位置遇到零条目,将失败,即使 allowsingular = true)。

可以通过 getproperty 访问分解 F 的各个组成部分:

组件描述
F.LL(下三角)部分的 LU
F.UU(上三角)部分的 LU
F.p(右)排列 Vector
F.P(右)排列 Matrix

迭代分解会产生组件 F.LF.UF.p

FA 之间的关系是

F.L*F.U == A[F.p, :]

F 进一步支持以下函数:

支持的函数LULU{T,Tridiagonal{T}}
/
\
inv
det
logdet
logabsdet
size
Julia 1.11

allowsingular 关键字参数是在 Julia 1.11 中添加的。

示例

julia> A = [4 3; 6 3]
2×2 Matrix{Int64}:
 4  3
 6  3

julia> F = lu(A)
LU{Float64, Matrix{Float64}, Vector{Int64}}
L factor:
2×2 Matrix{Float64}:
 1.0       0.0
 0.666667  1.0
U factor:
2×2 Matrix{Float64}:
 6.0  3.0
 0.0  1.0

julia> F.L * F.U == A[F.p, :]
true

julia> l, u, p = lu(A); # 通过迭代解构

julia> l == F.L && u == F.U && p == F.p
true

julia> lu([1 2; 1 2], allowsingular = true)
LU{Float64, Matrix{Float64}, Vector{Int64}}
L factor:
2×2 Matrix{Float64}:
 1.0  0.0
 1.0  1.0
U factor (rank-deficient):
2×2 Matrix{Float64}:
 1.0  2.0
 0.0  0.0
source
LinearAlgebra.qrFunction
qr(A::SparseMatrixCSC; tol=_default_tol(A), ordering=ORDERING_DEFAULT) -> QRSparse

计算稀疏矩阵 AQR 分解。使用填充减少的行和列置换,使得 F.R = F.Q'*A[F.prow,F.pcol]。这种类型的主要应用是解决最小二乘或欠定问题,使用 \。该函数调用 C 库 SPQR[ACM933]

Note

qr(A::SparseMatrixCSC) 使用的是 SuiteSparse 中的 SPQR 库。由于该库仅支持具有 Float64ComplexF64 元素的稀疏矩阵,因此从 Julia v1.4 开始,qrA 转换为适当类型的 SparseMatrixCSC{Float64}SparseMatrixCSC{ComplexF64} 的副本。

示例

julia> A = sparse([1,2,3,4], [1,1,2,2], [1.0,1.0,1.0,1.0])
4×2 SparseMatrixCSC{Float64, Int64} with 4 stored entries:
 1.0   ⋅
 1.0   ⋅
  ⋅   1.0
  ⋅   1.0

julia> qr(A)
SparseArrays.SPQR.QRSparse{Float64, Int64}
Q factor:
4×4 SparseArrays.SPQR.QRSparseQ{Float64, Int64}
R factor:
2×2 SparseMatrixCSC{Float64, Int64} with 2 stored entries:
 -1.41421    ⋅
   ⋅       -1.41421
Row permutation:
4-element Vector{Int64}:
 1
 3
 4
 2
Column permutation:
2-element Vector{Int64}:
 1
 2
source
qr(A, pivot = NoPivot(); blocksize) -> F

计算矩阵 A 的 QR 分解:一个正交(或如果 A 是复值则为单位)矩阵 Q,以及一个上三角矩阵 R,使得

\[A = Q R\]

返回的对象 F 以打包格式存储分解:

  • 如果 pivot == ColumnNorm(),则 F 是一个 QRPivoted 对象,
  • 否则如果 A 的元素类型是 BLAS 类型(Float32Float64ComplexF32ComplexF64),则 F 是一个 QRCompactWY 对象,
  • 否则 F 是一个 QR 对象。

可以通过属性访问器检索分解 F 的各个组成部分:

  • F.Q:正交/单位矩阵 Q
  • F.R:上三角矩阵 R
  • F.p:置换向量(仅 QRPivoted
  • F.P:置换矩阵(仅 QRPivoted
Note

每次通过 F.R 引用上三角因子都会分配一个新数组。因此,建议缓存该数组,例如,通过 R = F.R 并继续使用 R

迭代分解会产生组件 QR,以及如果存在则为 p

以下函数可用于 QR 对象:invsize\。当 A 是矩形时,\ 将返回一个最小二乘解,如果解不是唯一的,则返回范数最小的解。当 A 不是满秩时,需要进行(列)置换的分解以获得最小范数解。

允许与全/方形或非全/方形 Q 进行乘法,即支持 F.Q*F.RF.Q*A。可以使用 MatrixQ 矩阵转换为常规矩阵。此操作返回“薄” Q 因子,即,如果 Am×nm>=n,则 Matrix(F.Q) 产生一个具有正交列的 m×n 矩阵。要检索“完整” Q 因子,即一个 m×m 的正交矩阵,请使用 F.Q*Icollect(F.Q)。如果 m<=n,则 Matrix(F.Q) 产生一个 m×m 的正交矩阵。

QR 分解的块大小可以通过关键字参数 blocksize :: Integer 指定,当 pivot == NoPivot()A isa StridedMatrix{<:BlasFloat} 时。如果 blocksize > minimum(size(A)),则会被忽略。请参见 QRCompactWY

Julia 1.4

blocksize 关键字参数需要 Julia 1.4 或更高版本。

示例

julia> A = [3.0 -6.0; 4.0 -8.0; 0.0 1.0]
3×2 Matrix{Float64}:
 3.0  -6.0
 4.0  -8.0
 0.0   1.0

julia> F = qr(A)
LinearAlgebra.QRCompactWY{Float64, Matrix{Float64}, Matrix{Float64}}
Q 因子:3×3 LinearAlgebra.QRCompactWYQ{Float64, Matrix{Float64}, Matrix{Float64}}
R 因子:
2×2 Matrix{Float64}:
 -5.0  10.0
  0.0  -1.0

julia> F.Q * F.R == A
true
Note

qr 返回多种类型,因为 LAPACK 使用几种表示法来最小化 Householder 基本反射器的乘积的内存存储需求,以便 QR 矩阵可以紧凑地存储,而不是作为两个单独的密集矩阵。

source

Noteworthy External Sparse Packages

几个其他的 Julia 包提供了稀疏矩阵的实现,值得一提:

  1. SuiteSparseGraphBLAS.jl 是一个快速的多线程 SuiteSparse:GraphBLAS C 库的封装。在 CPU 上,这通常是最快的选项,通常显著优于 MKLSparse。

  2. CUDA.jl 暴露了 CUSPARSE 库,用于 GPU 稀疏矩阵操作。

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

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

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

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

  7. ExtendableSparse.jl 通过对新存储索引的懒惰方法实现了对稀疏矩阵的快速插入。

  8. Finch.jl 支持通过迷你张量语言和编译器进行广泛的多维稀疏数组格式和操作,全部使用原生 Julia。支持 COO、CSF、CSR、CSC 等格式,以及广播、归约等操作和自定义操作。

外部包提供稀疏直接求解器:

  1. KLU.jl
  2. Pardiso.jl

外部包提供用于特征系统和奇异值分解的迭代解法的求解器:

  1. ArnoldiMethods.jl
  2. KrylovKit
  3. Arpack.jl

用于处理图形的外部包:

  1. Graphs.jl
  • ACM887Chen, Y., Davis, T. A., Hager, W. W., & Rajamanickam, S. (2008). Algorithm 887: CHOLMOD, Supernodal Sparse Cholesky Factorization and Update/Downdate. ACM Trans. Math. Softw., 35(3). doi:10.1145/1391989.1391995
  • DavisHager2009Davis, Timothy A., & Hager, W. W. (2009). Dynamic Supernodes in Sparse Cholesky Update/Downdate and Triangular Solves. ACM Trans. Math. Softw., 35(4). doi:10.1145/1462173.1462176
  • ACM832Davis, Timothy A. (2004b). Algorithm 832: UMFPACK V4.3–-an Unsymmetric-Pattern Multifrontal Method. ACM Trans. Math. Softw., 30(2), 196–199. doi:10.1145/992200.992206
  • ACM933Foster, L. V., & Davis, T. A. (2013). Algorithm 933: Reliable Calculation of Numerical Rank, Null Space Bases, Pseudoinverse Solutions, and Basic Solutions Using SuitesparseQR. ACM Trans. Math. Softw., 40(1). doi:10.1145/2513109.2513116