Concatenate matrix of matrices in Julia
I have a matrix that I am building up block-wise, like so:
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
Now I'd like to concatenate all these parts into a larger matrix, with each block in its place. Is there a way to do this using the concatenation functions in Base
? I can't figure out how to use cat
to do it. For example, reduce((a, acc) -> cat(acc, a, dims=(1, 2), parts)
will create a block-diagonal matrix with r^2
blocks on the diagonal.
I think the official command for this is hvcat
, which is what's used to digest literal matrix syntax. Although whether it's the best solution may depend e.g. on how big theproblem is.
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"
I was able to do this by a nesting vcat
and hcat
like so:
reduce(vcat, [
reduce(hcat, [parts[i, k] for k in 1:r])
for i in 1:r
])
However, this doesn't nicely generalize to higher dimensions (although I guess you could nest further loops and use plain cat
). It will also allocate for each block row, rather than only allocating once for the entire result.