python numpy ndarray index permutations in all dimensions (variable dimension number)

Multi tool use
python numpy ndarray index permutations in all dimensions (variable dimension number)
'M' is a numpy ndarray, which dimension 'dim' number is variable (previously generated) but each dimension is of equal size 'size'. In my code it will be more like dim = 5, size = 7.
ex: (dim = 3,size = 4).
M = np.arange(size**dim).reshape((size,)*dim)
[[[ 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]
[36 37 38 39]
[40 41 42 43]
[44 45 46 47]]
[[48 49 50 51]
[52 53 54 55]
[56 57 58 59]
[60 61 62 63]]]
And I have a permutation generator of my own, 'per', that generates specific permutations (not random) of range(size).
print(next(per))
(1,0,3,2)
My need: transform M, by moving its elements according to as many permutations as I need. In the example: 21 (1 permutation for first dimension, 4 for second, 16 for third - generalised: size**d for d in range(dim) permutations). My permutations are not random, but they are independant, different from each other.
A result may be:
[[[36 39 37 38]
[33 34 32 35]
[46 44 45 47]]
[41 43 40 42]
[[9 10 11 8]
[2 1 3 0]
[6 7 5 4]
[13 12 14 15]]
[[56 59 57 58]
[63 61 62 60]
[53 54 52 55]
[51 50 49 48]]
[[28 30 29 31]
[27 25 24 26]
[17 18 16 19]
[23 21 20 22]]]
How can I do it directly from M as numpy array, whith my code remaining dynamic?
If you see my example, each line content has been permuted, but the lines in each 4*4 grid have been also, and the grid order also. All this needs to be done according to individual permutations (pertmuted index) from my generator.
– Cépagrave
Jul 2 at 23:49
1 Answer
1
This is an exercise in broadcasting:
>>> import numpy as np
>>> from itertools import islice
>>>
>>> A = np.arange(27).reshape(3,3,3)
>>> def per(n):
... while True:
... yield np.random.permutation(n)
...
>>> pg = per(3)
>>>
>>> p0 = next(pg)[..., None, None]
>>> p1 = np.array([p for p in islice(pg, 3)])[..., None]
>>> p2 = np.array([[p for p in islice(pg, 3)] for _ in range(3)])
>>>
>>> p0
array([[[2]],
[[1]],
[[0]]])
>>> p1
array([[[1],
[0],
[2]],
[[1],
[0],
[2]],
[[0],
[2],
[1]]])
>>> p2
array([[[1, 0, 2],
[0, 2, 1],
[0, 1, 2]],
[[2, 1, 0],
[1, 2, 0],
[2, 1, 0]],
[[1, 2, 0],
[2, 1, 0],
[2, 1, 0]]])
>>> A[p0, p1, p2]
array([[[22, 21, 23],
[18, 20, 19],
[24, 25, 26]],
[[14, 13, 12],
[10, 11, 9],
[17, 16, 15]],
[[ 1, 2, 0],
[ 8, 7, 6],
[ 5, 4, 3]]])
General soln:
import numpy as np
from itertools import islice
def per(n=None):
while True:
n = (yield n if n is None else np.random.permutation(n)) or n
def sweep(shp):
pg = per()
pg.send(None)
redshp = len(shp)*[1]
sz = 1
for j, k in enumerate(shp):
pg.send(k)
redshp[j] = k
yield np.reshape((*islice(pg, sz),), redshp)
sz *= k
# example
a = np.arange(24).reshape((2,3,4))
idx = *sweep(a.shape),
for i in idx:
print(i)
print(a[idx])
@Cépagrave see updated post.
– Paul Panzer
Jul 5 at 1:24
This is just Great ! Big job, thank you Paul !
– Cépagrave
Jul 5 at 12:33
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.
What do you mean by "by moving its elements according to as many permutations as I need"? What is the exact relationship supposed to be between the input array, the output array, and the permutation(s?) used?
– user2357112
Jul 2 at 23:36