Linear Algebra#
Perron–Frobenius theorem#
Theorem 1 (Perron–Frobenius theorem)
a real square matrix with positive entries has a unique largest real eigenvalue and that the corresponding eigenvector can be chosen to have strictly positive components, and also asserts a similar statement for certain classes of nonnegative matrices.
Matrix dot product#
import numpy as np
from math import sqrt
U = np.matrix([[1/sqrt(2)+1j/2, -1j/2],
[1/2, 1/2+1j/sqrt(2)]])
X = np.matrix([[0,1],[1,0]])
Y = np.matrix([[0,-1j],[1j,0]])
Z = np.matrix([[1,0],[0,-1]])
# U.getH()
np.matmul(U,X)
print(np.matmul(U,X,U.H))
print(np.matmul(np.dot(U,X),U.getH()))
print(np.matmul(np.matmul(U,X),U.H))
print(np.dot(np.dot(U,X),U.getH()))
print(np.dot(np.dot(U,Y),U.getH()))
print(np.dot(np.dot(U,Z),U.getH()))
[[0. -0.5j 0.70710678+0.5j ]
[0.5 +0.70710678j 0.5 +0.j ]]
[[-0.5 +0.j 0.70710678-0.5j]
[ 0.70710678+0.5j 0.5 +0.j ]]
[[-0.5 +0.j 0.70710678-0.5j]
[ 0.70710678+0.5j 0.5 +0.j ]]
[[-0.5 +0.j 0.70710678-0.5j]
[ 0.70710678+0.5j 0.5 +0.j ]]
[[ 7.07106781e-01+0.j 8.86511593e-17-0.70710678j]
[ 1.11022302e-16+0.70710678j -7.07106781e-01+0.j ]]
[[ 0.5 +0.j 0.70710678+0.5j]
[ 0.70710678-0.5j -0.5 +0.j ]]
print(np.matmul(U,U.getH()))
[[1.+0.j 0.+0.j]
[0.+0.j 1.+0.j]]
print(np.dot(U,U.getH()))
[[1.+0.j 0.+0.j]
[0.+0.j 1.+0.j]]
Matrix exponentiation#
from scipy.linalg import expm, sinm, cosm
import numpy as np
# hadmard gate
h = np.array([[1.0, 1.0], [1.0, -1.0]])
expm(1j*h/np.sqrt(2)*np.pi/2)
array([[6.123234e-17+0.70710678j, 0.000000e+00+0.70710678j],
[0.000000e+00+0.70710678j, 6.123234e-17-0.70710678j]])
Solve matrix inverse#
## solve A(4,3)*B(3,2)=C(4,2)
import numpy as np
from numpy.linalg import inv, matrix_rank, det
from numpy import dot, transpose
# np.set_printoptions(precision=5)
A = np.random.randn(4, 3)
C = np.random.randn(4, 2)
print(matrix_rank(A))
print('A=',A)
print('C=',C)
AT_A = dot(transpose(A),A)
print('AT_A=',AT_A)
print('rank of AT_A:',matrix_rank(AT_A))
A_left_inverse = dot(inv( AT_A ), transpose(A))
print(dot(inv( AT_A ), AT_A ))
print(dot(A,A_left_inverse))
B = dot(A_left_inverse, C)
print('B=',B)
# print(dot(A,dot(A_left_inverse, C)))
print('A*B=',dot(A,B))
3
A= [[-0.58467778 0.82158951 0.10574808]
[-0.50681406 0.4223986 0.42152069]
[-0.04623778 0.53622639 -0.99689905]
[ 0.44557443 0.77302169 -0.43747922]]
C= [[-0.7486619 -0.82060587]
[-0.72422963 0.28541297]
[-1.23958652 0.95226842]
[ 0.66498058 -0.7678366 ]]
AT_A= [[ 0.7993831 -0.3747979 -0.42429632]
[-0.3747979 1.73853117 -0.60781324]
[-0.42429632 -0.60781324 1.37405814]]
rank of AT_A: 3
[[ 1.00000000e+00 1.60143113e-16 -2.82515649e-16]
[ 7.02571532e-17 1.00000000e+00 -1.73973845e-16]
[ 1.17481372e-16 7.45963956e-18 1.00000000e+00]]
[[ 0.62772876 0.46182522 0.13355035 0.05066688]
[ 0.46182522 0.42707759 -0.16567737 -0.06285536]
[ 0.13355035 -0.16567737 0.95208952 -0.01817648]
[ 0.05066688 -0.06285536 -0.01817648 0.99310413]]
B= [[ 2.24272868 -1.26220417]
[ 0.29783903 -1.09075364]
[ 1.232111 -1.29426549]]
A*B= [[-0.93627883 -0.2950351 ]
[-0.49147935 -0.36658968]
[-1.17227993 0.76372268]
[ 0.69051563 -0.83936786]]
a = np.array([[1., 2., 3.], [3., 5., 3.]])
aT_a = dot(transpose(a),a)
print(aT_a)
print(det(aT_a))
print('rank:',matrix_rank(aT_a))
ainv = inv(aT_a)
print(ainv)
np.allclose(dot(ainv, aT_a), np.eye(3))
[[10. 17. 12.]
[17. 29. 21.]
[12. 21. 18.]]
1.6710489201527266e-14
rank: 2
[[ 4.84725486e+15 -3.23150324e+15 5.38583873e+14]
[-3.23150324e+15 2.15433549e+15 -3.59055916e+14]
[ 5.38583873e+14 -3.59055916e+14 5.98426526e+13]]
False