我有两个
Matrix{Vector{}}
,比如 A
和 B
,大小相同。我想得到一个Matrix{Matrix{}}
,M
,这样每个元素都是A
和B
的每个元素的外加和,即
M[i, j][k, l] = A[i, j][k] + B[i, j][l]
.
如何向量化上述操作?
案例:
A=[[[1, 2]] [[3, 4]] ; [[5, 6]] [[7, 8]]]
2×2 Matrix{Vector{Int64}}:
[1, 2] [3, 4]
[5, 6] [7, 8]
B=[[[11, 21]] [[13, 44]] ; [[25, 61]] [[27, 28]]]
2×2 Matrix{Vector{Int64}}:
[11, 21] [13, 44]
[25, 61] [27, 28]
size(A)==size(B)
true
M=[A[i, j] .+ B[i, j]' for i in 1:size(A)[1], j in 1:size(A)[2]]
2×2 Matrix{Matrix{Int64}}:
[12 22; 13 23] [16 47; 17 48]
[30 66; 31 67] [34 35; 35 36]
我很想找到一种方法来避免
for
循环,因为在我的用例中,A
和 B
是巨大的矩阵!我也试过 A .+ adjoint.(B)
但这会引发错误消息:
ERROR: DimensionMismatch: dimensions must match: a has dims (Base.OneTo(1), Base.OneTo(2)), b has dims (Base.OneTo(2),), mismatch at 1
.
我找到了一个使用 TensorCast 包的解决方法,它看起来像
@cast MCast[i, j][k, l] := A[i, j][k] + B[i, j][l];
julia> MCast = collect(MCast);
julia> MCast
2×2 Matrix{SubArray{Int64, 2, Array{Int64, 4}, Tuple{Base.Slice{Base.OneTo{Int64}}, Base.Slice{Base.OneTo{Int64}}, Int64, Int64}, true}}:
[12 22; 13 23] [16 47; 17 48]
[30 66; 31 67] [34 35; 35 36]
这确实有效,但我想知道是否存在更优雅的方法,最好是在本地 Julia 中。
julia> map(.+, A, adjoint.(B))
2×2 Matrix{Matrix{Int64}}:
[12 22; 13 23] [16 47; 17 48]
[30 66; 31 67] [34 35; 35 36]
是我到目前为止得到的。
轻微改善:
using MappedArrays
map(.+, A, mappedarray(adjoint,B))
(没有实现
adjoint.(B)
)
使用数组理解比使用
map
和 .+
更有效,因为它避免了不必要的分配。但是你可以把你的理解写得更简洁优雅,也更安全。对 1:size(A)[1]
等进行索引并不被认为是安全的,因为并非所有数组都具有这样的索引。
这里有三种选择:
[A[i, j] .+ B[i, j]' for i in axes(A, 1), j in axes(A, 2)]
[A[i] .+ B[i]' for i in CartesianIndices(A)]
[a .+ b' for (a, b) in zip(A, B)]
记住,Julia 中的循环很快。