Permutation of symmetric array in Python - python

I want to have the permutation for this symmetric matrix, if we move the the second column to the third the second row also should go to the third row.
array([[ 0. , 0.06377803, 0.1157737 , 0.19542195],
[ 0.06377803, 0. , 0.14754803, 0.23185761],
[ 0.1157737 , 0.14754803, 0. , 0.0843134 ],
[ 0.19542195, 0.23185761, 0.0843134 , 0. ]])
This is code for permutation on a list:
import numpy as np
x=[]
def perm(a, k=0):
if k == len(a):
x.extend(a)
# print (a )
else:
for i in range(k, len(a)):
a[k], a[i] = a[i] ,a[k]
perm(a, k+1)
a[k], a[i] = a[i], a[k]
perm([0,1,2,3])
a=np.asarray(x).reshape((24,4))
print(a)
Output:
[[0 1 2 3]
[0 1 3 2]
[0 2 1 3]
[0 2 3 1]
[0 3 2 1]
[0 3 1 2]
[1 0 2 3]
[1 0 3 2]
[1 2 0 3]
[1 2 3 0]
[1 3 2 0]
[1 3 0 2]
[2 1 0 3]
[2 1 3 0]
[2 0 1 3]
[2 0 3 1]
[2 3 0 1]
[2 3 1 0]
[3 1 2 0]
[3 1 0 2]
[3 2 1 0]
[3 2 0 1]
[3 0 2 1]
[3 0 1 2]]
But I want to have the permutation for the above array which is 4*4. For simplicity if we have a 3*3 array, we want something like below which is K!=6 but when k=4 then we have to get k! which is 24 permutations

import numpy as np
from itertools import permutations
n = 3
a = np.arange(n**2).reshape(n, n)
for perm in permutations(range(a.shape[0])):
b = np.zeros_like(a)
b[:, :] = a[perm, :]
b[:, :] = b[:, perm]
print(b)
gives the 6 following matrices:
[[0 1 2]
[3 4 5]
[6 7 8]]
[[0 2 1]
[6 8 7]
[3 5 4]]
[[4 3 5]
[1 0 2]
[7 6 8]]
[[4 5 3]
[7 8 6]
[1 2 0]]
[[8 6 7]
[2 0 1]
[5 3 4]]
[[8 7 6]
[5 4 3]
[2 1 0]]
Is this the question?

Related

Python Numpy make a pattern with a square matrix of any dimension

I am having difficulties trying to generate a specific pattern that would work for any square matrix with any square dimension using NumPy
For example:
User input: n = 3
Output:
[[1 2 0]
[2 3 2]
[0 2 1]]
User input: n = 5
Output:
[[1 2 3 0 0]
[2 3 4 0 0]
[3 4 5 4 3]
[0 0 4 3 2]
[0 0 3 2 1]]
User input: n = 8
Output:
[[1 2 3 4 5 0 0 0]
[2 3 4 5 6 0 0 0]
[3 4 5 6 7 0 0 0]
[4 5 6 9 8 7 6 5]
[5 6 7 8 9 6 5 4]
[0 0 0 7 6 5 4 3]
[0 0 0 6 5 4 3 2]
[0 0 0 5 4 3 2 1]]
Since a square matrix can be generated with any number in the form of (n x n), there would be instances where the user input is an odd number, how would I start figuring out the equations needed to make this work?
I got this going on but I was only able to do it on one corner of the matrix, any suggestion or idea is appreciated, thank you!
def input_number(n):
matrix = np.zeros(shape=(n, n), dtype=int)
for y in range(round(n // 2) + 1):
for x in range(round(n // 2) + 1):
matrix[y, x] = x + y + 1
y += 1
Input: n = 4
Output:
[[1 2 3 0 0]
[2 3 4 0 0]
[3 4 5 0 0]
[0 0 0 0 0]
[0 0 0 0 0]]
Try this:
def foo(n):
half = (n+1) // 2
res = np.zeros((n, n), int)
res[:half, :half] = np.arange(1, 1 + half) + np.arange(half).reshape(half, 1)
res[n//2:, n//2:] = res[half-1::-1, half-1::-1]
return res
This creates the top-left quarter then mirrors it to the bottom-right quarter.
Note it behaves a little differently to your example of n=8, the output is:
[[1, 2, 3, 4, 0, 0, 0, 0],
[2, 3, 4, 5, 0, 0, 0, 0],
[3, 4, 5, 6, 0, 0, 0, 0],
[4, 5, 6, 7, 0, 0, 0, 0],
[0, 0, 0, 0, 7, 6, 5, 4],
[0, 0, 0, 0, 6, 5, 4, 3],
[0, 0, 0, 0, 5, 4, 3, 2],
[0, 0, 0, 0, 4, 3, 2, 1]]
But I'll leave it this way because it seems more logical...you can edit the code if needed to make the center 4 values mix with each other as you showed.
I looked around a bit more and was eventually able to pull it off, here's my take on it.
import numpy as np
def input_number(n):
matrix = np.zeros(shape=(n, n), dtype=int)
for y in range(round(n // 2) + 1):
for x in range(round(n // 2) + 1):
matrix[y, x] = y + x + 1
matrix[(n - y) - 1][(n - x) - 1] = matrix[y, x]
print(matrix)
input_number(n)
Input: 3
Output:
[[1 2 0]
[2 3 2]
[0 2 1]]
Input: 5
Output:
[[1 2 3 0 0]
[2 3 4 0 0]
[3 4 5 4 3]
[0 0 4 3 2]
[0 0 3 2 1]]
Input: 8
Output:
[[1 2 3 4 5 0 0 0]
[2 3 4 5 6 0 0 0]
[3 4 5 6 7 0 0 0]
[4 5 6 9 8 7 6 5]
[5 6 7 8 9 6 5 4]
[0 0 0 7 6 5 4 3]
[0 0 0 6 5 4 3 2]
[0 0 0 5 4 3 2 1]]
I am not sure what is the pattern of zeros in these examples. In the cases of n=3 and n=5 the zero subarrays in the corners are of the size (n//2)x(n//2), but for n=8 they are of the size 3x3 and not 4x4. Assuming that the size of these subarrays should be (n//2)x(n//2) the following code should work:
n = 7
A = np.zeros((n, n), dtype=int)
for i in range(n):
A.ravel()[i:(n-i)*n:n+1] = n-i
m = n//2
A[:m, :m] = 0
A[-m:, -m:] = 0
A = A + A.T - np.diag(np.diag(A))
A = A[:, ::-1]
If the zero subarrays should be smaller, it suffices to change the value of m.

Numpy.array indexing

import numpy as np
arr = np.array([[0, 1, 0],
[1, 0, 0],
[1, 0, 0]])
mask = arr
print('boolean mask is:')
print(mask)
print('arr[mask] is:')
print(arr[mask])
Result:
boolean mask is:
[[0 1 0]
[1 0 0]
[1 0 0]]
arr[mask] is:
[[[0 1 0]
[1 0 0]
[0 1 0]]
[[1 0 0]
[0 1 0]
[0 1 0]]
[[1 0 0]
[0 1 0]
[0 1 0]]]
I know how indexing works when the mask is 2-D, but confused when the mask is 3-D.
Anyone can explain it?
import numpy as np
l = [[0,1,2],[3,5,4],[7,8,9]]
arr = np.array(l)
mask = arr[:,:] > 5
print(mask) # shows boolean results
print(mask.sum()) # shows how many items are > 5
print(arr[:,1]) # slicing
print(arr[:,2]) # slicing
print(arr[:, 0:3]) # slicing
output
[[False False False]
[False False False]
[ True True True]]
3
[1 5 8]
[2 4 9]
[[0 1 2]
[3 5 4]
[7 8 9]]

add field to memmaped numpy record array

With normal memmapped numpy arrays, you can "add" a new column by opening the memmap file with an additional column in the shape.
k = np.memmap('input', dtype='int32', shape=(10, 2), mode='r+', order='F')
k[:] = 1
l = np.memmap('input', dtype='int32', shape=(10, 3), mode='r+', order='F')
print(k)
print(l)
[[1 1]
[1 1]
[1 1]
[1 1]
[1 1]
[1 1]
[1 1]
[1 1]
[1 1]
[1 1]]
[[1 1 0]
[1 1 0]
[1 1 0]
[1 1 0]
[1 1 0]
[1 1 0]
[1 1 0]
[1 1 0]
[1 1 0]
[1 1 0]]
Is it possible to make a similar move with record arrays? Seems possible with rows, but can't find a way to do so with a new field, if the dtype has heterogeneous types.

Numpy swap the values of nested columns

Given the following data structure is there some way I can swap the first and last column such that each row is [3, 2, 1] (I don't wish to sort them) without looping through each row?
[[[1 2 3]
[1 2 3]
[1 2 3]
...
[1 2 3]
[1 2 3]
[1 2 3]]
[[1 2 3]
[1 2 3]
[1 2 3]
...
[1 2 3]
[1 2 3]
[1 2 3]]]

python: Find subsets coordinate is in

I have a set of coordinates and try to find those subsets the coordinate is in.
import numpy as np
a=np.array([[[0,1,1],[1,1,1]],[[0,1,1],[2,1,1]],[[3,3,3],[2,2,2]]])
If I try things like:
print(np.argwhere(a==[[0,1,1]]))
print(a[[0,1,1]])
print(np.isin([0,1,1],a))
I get:
[[0 0 0]
[0 0 1]
[0 0 2]
[0 1 1]
[0 1 2]
[1 0 0]
[1 0 1]
[1 0 2]
[1 1 1]
[1 1 2]]
[[[0 1 1]
[1 1 1]]
[[0 1 1]
[2 1 1]]
[[0 1 1]
[2 1 1]]]
[ True True True]
But I expect something like:
[true,true,false]
EDIT
The best case would be If I get an array where only all other coordinates which are members of the founded subsets are in like:
out = [[1,1,1],[2,1,1]]
Use all(-1) to assert the array equal at the last axis and then any(1) to check if such condition exists at the second axis:
(a == [0,1,1]).all(-1).any(1)
# array([ True, True, False], dtype=bool)
On the update:
mask = (a == [0,1,1]).all(-1)
a[mask.any(1)[:,None] & ~mask]
#array([[1, 1, 1],
# [2, 1, 1]])
I got the results you're looking for by doing this:
[[0,1,1] in b for b in a]
I'll try to figure out why isin didnt work.

Categories