QR分解
Schmidt变换

import numpy as np
np.set_printoptions(precision=4, suppress=True)
def gram_schmidt(A):
Q = np.zeros_like(A)
cnt = 0
for a in A.T:
q = np.copy(a)
for i in range(0, cnt):
q -= np.dot(a,Q[:, i].T)/(np.dot(Q[:, i].T, Q[:, i])) * Q[:, i]
Q[:, cnt] = q
cnt += 1
for i in range(A.shape[1]):
Q[:, i] /= np.linalg.norm(Q[:, i])
R = np.dot(Q.T, A)
return Q, R
A = np.array([[0, -20, -14], [3, 27, -4], [4, 11, -2]], dtype=float)
Q, R = gram_schmidt(A)
print("Q:\n", Q)
print("R:\n", R)
print(np.dot(Q, R))
Q:
[[ 0. -0.8 -0.6 ]
[ 0.6 0.48 -0.64]
[ 0.8 -0.36 0.48]]
R:
[[ 5. 25. -4.]
[ 0. 25. 10.]
[ 0. 0. 10.]]
[[ -0. -20. -14.]
[ 3. 27. -4.]
[ 4. 11. -2.]]
Givens变换

import numpy as np
np.set_printoptions(precision=4, suppress=True)
def givens_rotation(A):
r, c = np.shape(A)
Q = np.identity(r)
R = np.copy(A)
(rows, cols) = np.tril_indices(r, -1)
for (row, col) in zip(rows, cols):
if R[row, col]!= 0:
r_ = np.hypot(R[row, col], R[col, col])
c = R[col, col] / r_
s = -R[row, col] / r_
G = np.identity(r)
G[[col, row],[col, row]] = c
G[row, col] = s
G[col, row] = -s
R = np.dot(G, R)
Q = np.dot(Q, G.T)
return (Q, R)
A = np.array([[0, -20, -14], [3, 27, -4], [4, 11, -2]], dtype=float)
(Q, R) = givens_rotation(A)
print("Q:\n", Q)
print("R:\n", R)
print("QR = A:\n", np.dot(Q, R))
print(np.allclose(np.dot(Q, R), A))
Q:
[[ 0. -0.8 -0.6 ]
[ 0.6 0.48 -0.64]
[ 0.8 -0.36 0.48]]
R:
[[ 5. 25. -4.]
[ 0. 25. 10.]
[-0. 0. 10.]]
QR = A:
[[ 0. -20. -14.]
[ 3. 27. -4.]
[ 4. 11. -2.]]
True
Householder变换

import numpy as np
np.set_printoptions(precision=4, suppress=True)
def householder_reflection(A):
r, c = np.shape(A)
Q = np.identity(r)
R = np.copy(A)
for cnt in range(r-1):
x = R[cnt:, cnt]
e = np.zeros_like(x)
e[0] = np.linalg.norm(x)
u = x - e
v = u / np.linalg.norm(u)
Q_cnt = np.identity(r)
Q_cnt[cnt:, cnt:] -= 2 * np.outer(v, v)
R = np.dot(Q_cnt, R)
Q = np.dot(Q, Q_cnt)
return (Q, R)
A = np.array([[0, -20, -14], [3, 27, -4], [4, 11, -2]], dtype=float)
(Q, R) = householder_reflection(A)
print("Q:\n", Q)
print("R:\n", R)
print("QR = A:\n", np.dot(Q, R))
print(np.allclose(np.dot(Q, R), A))
Q:
[[ 0. -0.8 -0.6 ]
[ 0.6 0.48 -0.64]
[ 0.8 -0.36 0.48]]
R:
[[ 5. 25. -4.]
[ 0. 25. 10.]
[ 0. 0. 10.]]
QR = A:
[[ 0. -20. -14.]
[ 3. 27. -4.]
[ 4. 11. -2.]]
True