I'm implementing Strassen's Matrix Multiplication using python. In divide step, we divide a larger matrix into smaller sub-matrices. Is there a built-in numpy function to split a matrix?
Asked
Active
Viewed 4.7k times
4 Answers
21
According to this answer, you might use the swapaxes
:
You can create a helper method as:
def split(array, nrows, ncols):
"""Split a matrix into sub-matrices."""
r, h = array.shape
return (array.reshape(h//nrows, nrows, -1, ncols)
.swapaxes(1, 2)
.reshape(-1, nrows, ncols))
Here is an example of using it
import numpy as np
array = np.array([
[1, 1, 2, 2],
[3, 3, 4, 4],
[5, 5, 6, 6],
[7, 7, 8, 8]])
A, B, C, D = split(array, 2, 2)
# A =
# [[1 1]
# [3 3]]
# B =
# [[2 2]
# [4 4]]
# C =
# [[5 5]
# [7 7]]
# D =
# [[6 6]
# [8 8]]
print('A = \n{}\n\n'
'B = \n{}\n\n'
'C = \n{}\n\n'
'D =\n{}'.format(A, B, C, D))

Dat
- 5,405
- 2
- 31
- 32
18
Not exactly, but using array slicing notation you should be able to do it yourself pretty easily.
>>> A = np.linspace(0,24,25).reshape([5,5,])
>>> A
array([[ 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.]])
Make B the top-left 2x2 in A:
>>> B = A[0:2,0:2]
Note that B is a view, it shares data with A
>>> B[1,1] = 60
>>> print A
[[ 0. 1. 2. 3. 4.]
[ 5. 60. 7. 8. 9.]
[ 10. 11. 12. 13. 14.]
[ 15. 16. 17. 18. 19.]
[ 20. 21. 22. 23. 24.]]
If you need to copy the data from A, use the copy method:
>>> B = A[0:2,0:2].copy()
>>> B
array([[ 0., 1.],
[ 5., 60.]])
>>> B[1,1] = 600
>>> B
array([[ 0., 1.],
[ 5., 600.]])
>>> A
array([[ 0., 1., 2., 3., 4.],
[ 5., 60., 7., 8., 9.],
[ 10., 11., 12., 13., 14.],
[ 15., 16., 17., 18., 19.],
[ 20., 21., 22., 23., 24.]])

Rob Falck
- 2,324
- 16
- 14
12
I ran into the same problem and found some built-in numpy functions to split my matrix into 4 submatrices (my matrices are of size 2^N*2^N)
Here is the code i wrote:
upper_half = np.hsplit(np.vsplit(my_matrix, 2)[0], 2)
lower_half = np.hsplit(np.vsplit(my_matrix, 2)[1], 2)
upper_left = upper_half[0]
upper_right = upper_half[1]
lower_left = lower_half[0]
lower_right = lower_half[1]
Bonus to recombine them using numpy:
C=np.vstack([np.hstack([c11, c12]), np.hstack([c21, c22])])
vsplit hsplit hstack and vstack seem to be made for that purpose

Roulbacha
- 457
- 7
- 20
0
Not fundamentally different from the above answers but maybe a little more concise:
A = np.random.randn(4, 4)
print(A)
B = [np.hsplit(half, 2) for half in np.vsplit(A, 2)]
print(B)
C = np.block(B)
print(C)
[[ 0.14577043 -1.01422737 -0.21212882 -1.56080335]
[-0.26758559 0.48542432 -0.8508443 1.84165807]
[ 0.18615368 -0.55853988 -1.08452365 -0.65183916]
[-0.69947061 -1.23371315 1.88217085 -0.65417009]]
[[array([[ 0.14577043, -1.01422737],
[-0.26758559, 0.48542432]]), array([[-0.21212882, -1.56080335],
[-0.8508443 , 1.84165807]])], [array([[ 0.18615368, -0.55853988],
[-0.69947061, -1.23371315]]), array([[-1.08452365, -0.65183916],
[ 1.88217085, -0.65417009]])]]
[[ 0.14577043 -1.01422737 -0.21212882 -1.56080335]
[-0.26758559 0.48542432 -0.8508443 1.84165807]
[ 0.18615368 -0.55853988 -1.08452365 -0.65183916]
[-0.69947061 -1.23371315 1.88217085 -0.65417009]]

cgogolin
- 960
- 1
- 10
- 22