英文:
Adding block-constant matrices in numpy
问题
让我们假设我们有一个:
n*n
矩阵A
m*m
矩阵B
- 一个包含块大小的向量
b=[b_1,...,b_m]
,满足b_1 + ... + b_m = n
和b_i >= 1
。
然后,我定义了一个 n*n
块矩阵 B_block
,其 (i,j)
块是一个具有常值 B_{ij}
的 b_i*b_j
矩阵。如何在 numpy 中高效计算 A+B_block
?
到目前为止,我正在执行以下操作:
A = np.arange(36).reshape(6,6)
B = np.arange(9).reshape(3,3)
blocks_sizes = np.array([3,2,1])
B_block = np.block([[np.ones((a,b))*B[i,j] for j,b in enumerate(block_sizes)] for i,a in enumerate(block_sizes)])
C = A + B_block
print(A)
print(B_block)
print(C)
得到的结果如下:
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]
[24 25 26 27 28 29]
[30 31 32 33 34 35]]
[[0. 0. 0. 1. 1. 2.]
[0. 0. 0. 1. 1. 2.]
[0. 0. 0. 1. 1. 2.]
[3. 3. 3. 4. 4. 5.]
[3. 3. 3. 4. 4. 5.]
[6. 6. 6. 7. 7. 8.]]
[[ 0. 1. 2. 4. 5. 7.]
[ 6. 7. 8. 10. 11. 13.]
[12. 13. 14. 16. 17. 19.]
[21. 22. 23. 25. 26. 28.]
[27. 28. 29. 31. 32. 34.]
[36. 37. 38. 40. 41. 43.]]
这个方法是有效的,但似乎效率不高。是否有一种不需要手动构建块矩阵或使用 Python 循环的 numpy 解决方案?
如果所有的块大小都相同,那么可以使用 np.kron
...
英文:
Let's say we have a
n*n
matrixA
m*m
matrixB
- a vector
b=[b_1,...,b_m]
of block sizes withb_1 + ... + b_m = n
andb_i >= 1
.
Then I define a n*n
block matrix B_block
whose (i,j)
-th block is a b_i*b_j
matrix of constant value B_{ij}
. How can I efficiently compute A+B_block
in numpy?
So far I am doing
A = np.arange(36).reshape(6,6)
B = np.arange(9).reshape(3,3)
blocks_sizes = np.array([3,2,1])
B_block = np.block([[np.ones((a,b))*B[i,j] for j,b in enumerate(block_sizes)] for i,a in enumerate(block_sizes)])
C = A + B_block
print(A)
print(B_block)
print(C)
resulting in
[[ 0 1 2 3 4 5]
[ 6 7 8 9 10 11]
[12 13 14 15 16 17]
[18 19 20 21 22 23]
[24 25 26 27 28 29]
[30 31 32 33 34 35]]
[[0. 0. 0. 1. 1. 2.]
[0. 0. 0. 1. 1. 2.]
[0. 0. 0. 1. 1. 2.]
[3. 3. 3. 4. 4. 5.]
[3. 3. 3. 4. 4. 5.]
[6. 6. 6. 7. 7. 8.]]
[[ 0. 1. 2. 4. 5. 7.]
[ 6. 7. 8. 10. 11. 13.]
[12. 13. 14. 16. 17. 19.]
[21. 22. 23. 25. 26. 28.]
[27. 28. 29. 31. 32. 34.]
[36. 37. 38. 40. 41. 43.]]
which works fine but seems inefficient. Is there a numpy-solution which does not require constructing the block matrix by hand, or python-loops?
If all the blocks were of the same size, then I could use np.kron
...
答案1
得分: 1
B_block = B[np.arange(len(blocks_sizes)).repeat(blocks_sizes)][:, np.arange(len(blocks_sizes)).repeat(blocks_sizes)]
C = A + B_block
我的性能:
4.36 微秒 ± 93.9 纳秒每次循环(7 次运行的平均值 ± 标准差,每次循环100,000次)
您的性能:
83.1 微秒 ± 34.7 微秒每次循环(7 次运行的平均值 ± 标准差,每次循环10,000次)
如果您愿意,也可以定义 `slice_ids = np.arange(len(blocks_sizes)).repeat(blocks_sizes)` 来使其更轻便:
B_block = B[slice_ids][:, slice_ids]
C = A + B_block
英文:
B_block = B[np.arange(len(blocks_sizes)).repeat(blocks_sizes)][:, np.arange(len(blocks_sizes)).repeat(blocks_sizes)]
C = A + B_block
my performance:
4.36 µs ± 93.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
your performance:
83.1 µs ± 34.7 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
If you prefer you can also define slice_ids = np.arange(len(blocks_sizes)).repeat(blocks_sizes)
in order to make the lighter and so:
B_block = B[slice_ids][:, slice_ids]
C = A + B_block
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论