在 Julia 中连接矩阵矩阵

Concatenate matrix of matrices in Julia

我有一个按块构建的矩阵,如下所示:

parts = Matrix{SparseMatrixCSC{Float64}}(undef, r, r)
for i in 1:r
    for k in 1:r
        parts[i, k] = make_part(i, k)
    end
end

现在我想将所有这些部分连接成一个更大的矩阵,每个块各就各位。有没有办法使用 Base 中的连接函数来做到这一点?我不知道如何使用 cat 来做到这一点。例如,reduce((a, acc) -> cat(acc, a, dims=(1, 2), parts) 将创建一个块对角矩阵,对角线上有 r^2 个块。

我可以通过嵌套 vcathcat 来做到这一点:

reduce(vcat, [
    reduce(hcat, [parts[i, k] for k in 1:r])
    for i in 1:r
])

然而,这并不能很好地推广到更高的维度(尽管我猜你可以嵌套更多的循环并使用普通的 cat)。它还将为每个块行分配,而不是只为整个结果分配一次。

假设你有类似的东西:

parts = [sprand(2,2,0.7) for i in 1:2, j in 1:3]
2×3 Matrix{SparseMatrixCSC{Float64, Int64}}:
…  

using BlockArrays你能做的:

julia> mortar(parts)
2×3-blocked 4×6 BlockMatrix{Float64, Matrix{SparseMatrixCSC{Float64, Int64}}, Tuple{BlockedUnitRange{Vector{Int64}}, BlockedUnitRange{Vector{Int64}}}}:
  ⋅        0.543703  │   ⋅       0.773536  │  0.390049  0.0287028
 0.113945  0.422259  │   ⋅       0.764168  │  0.140334   ⋅
 ────────────────────┼─────────────────────┼─────────────────────
 0.295535  0.286277  │  0.81173   ⋅        │  0.646139  0.0616408
 0.641121  0.033793  │   ⋅       0.754504  │  0.995975   ⋅

我认为官方命令是 hvcat,这是用来消化文字矩阵语法的。尽管它是否是最佳解决方案可能取决于例如关于问题有多大。

julia> parts = [fill(i + 10j, 2,2) for i in 1:2, j in 1:3]
2×3 Matrix{Matrix{Int64}}:
 [11 11; 11 11]  [21 21; 21 21]  [31 31; 31 31]
 [12 12; 12 12]  [22 22; 22 22]  [32 32; 32 32]

julia> parts[end] = [91 92; 93 94]  # secretly calls hvcat
2×2 Matrix{Int64}:
 91  92
 93  94

julia> hvcat(3, permutedims(parts)...)  # note that it works along the rows!
4×6 Matrix{Int64}:
 11  11  21  21  31  31
 11  11  21  21  31  31
 12  12  22  22  91  92
 12  12  22  22  93  94

julia> parts = [sprand(2,2,0.7) for i in 1:2, j in 1:3];

julia> hvcat(3, permutedims(parts)...) |> summary  # preserves sparseness
"4×6 SparseMatrixCSC{Float64, Int64} with 17 stored entries"