如何广播两个vector of vector的元素外和?

问题描述 投票:0回答:2

我有两个

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 中。

arrays julia vectorization tensor array-broadcasting
2个回答
1
投票
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)


0
投票

使用数组理解比使用

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 中的循环很快。

© www.soinside.com 2019 - 2024. All rights reserved.