在 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
个块。
我可以通过嵌套 vcat
和 hcat
来做到这一点:
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"
我有一个按块构建的矩阵,如下所示:
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
个块。
我可以通过嵌套 vcat
和 hcat
来做到这一点:
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"