Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding Permutation Matrix with NumPy

I am looking for the correct permutation matrix that would take matrix a and turn it into matrix b given

a = np.array([[1,4,7,-2],[3,0,-2,-1],[-4,2,1,0],[-8,-3,-1,2]])
b = np.array([[-4,2,1,0],[3,0,-2,-1],[-8,-3,-1,2],[1,4,7,-2]])

I tried

x = np.linalg.solve(a,b)

However, I know this is incorrect and it should be

np.array([[0,0,1,0],[0,1,0,0],[0,0,0,1],[1,0,0,0]])

What numpy code would deliver this matrix from the other two?

like image 986
talkingtoducks Avatar asked Sep 17 '25 13:09

talkingtoducks


2 Answers

Generally, if you have some PA = B and you want P then you need to solve the equation for P. Matrix multiplication is not commutative, so you have to right multiply both sides by the inverse of A. With numpy, the function to get the inverse of a matrix is np.linalg.inv().

Using the matrix multiplication operator @, you can right-multiply with b to get P, taking note that you will end up with floating point precision errors:

In [4]: b @ np.linalg.inv(a)
Out[4]:
array([[-1.38777878e-16, -3.05311332e-16,  1.00000000e+00,
        -1.31838984e-16],
       [ 0.00000000e+00,  1.00000000e+00,  6.93889390e-17,
         0.00000000e+00],
       [ 0.00000000e+00,  0.00000000e+00, -1.11022302e-16,
         1.00000000e+00],
       [ 1.00000000e+00, -4.44089210e-16,  5.55111512e-17,
         0.00000000e+00]])

As @Mad Physicist points out, you can compare this matrix with > 0.5 to convert it to a boolean matrix:

In [7]: bool_P = (b @ np.linalg.inv(a)) > 0.5

In [8]: bool_P @ a
Out[8]:
array([[-4,  2,  1,  0],
       [ 3,  0, -2, -1],
       [-8, -3, -1,  2],
       [ 1,  4,  7, -2]])

In [9]: bool_P @ a == b  # our original equation, PA = B
Out[9]:
array([[ True,  True,  True,  True],
       [ True,  True,  True,  True],
       [ True,  True,  True,  True],
       [ True,  True,  True,  True]])
like image 198
ddejohn Avatar answered Sep 19 '25 05:09

ddejohn


solve computes x in the equation Ax = B. You can use it, but the arguments have to match.

Your equation is XA = B. You can take the transpose of both sides to get ATXT = BT, which has the correct form. So you can get the result from

np.linalg.solve(A.T, B.T).T

To get a boolean result that's guaranteed to be zeros and ones, you can apply a threshold:

np.linalg.solve(A.T, B.T).T > 0.5
like image 45
Mad Physicist Avatar answered Sep 19 '25 04:09

Mad Physicist