import numpy as np
n = 100
a = np.random.rand(n)
b = a + 1e-9 * np.random.randn(n)
# Π‘Π½Π°ΡΠ°Π»Π° Π½ΠΎΡΠΌΠΈΡΡΠ΅ΠΌ Π²Π΅ΠΊΡΠΎΡ a
a = a / np.linalg.norm(a)
# Π£Π±ΠΈΡΠ°Π΅ΠΌ ΠΈΠ· b ΠΏΡΠΎΠ΅ΠΊΡΠΈΡ Π½Π° a (ΠΏΠΎΠΏΡΡΠΊΠ° ΡΠ΄Π΅Π»Π°ΡΡ c ΠΎΡΡΠΎΠ³ΠΎΠ½Π°Π»ΡΠ½ΡΠΌ ΠΊ a)
c = b - np.dot(b, a) * a
c = c / np.linalg.norm(c)
# Π‘ΠΊΠ°Π»ΡΡΠ½ΠΎΠ΅ ΠΏΡΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ΠΈΠ΅ c ΠΈ a ΠΏΠΎΠΊΠ° Π½Π΅ ΠΈΠ΄Π΅Π°Π»ΡΠ½ΠΎ ΠΌΠ°Π»ΠΎ:
print (np.dot(c, a))
# ΠΠ΅Π»Π°Π΅ΠΌ ΠΏΠΎΠ²ΡΠΎΡΠ½ΡΡ ΠΎΡΡΠΎΠ³ΠΎΠ½Π°Π»ΠΈΠ·Π°ΡΠΈΡ:
# Π‘Π½ΠΎΠ²Π° Π²ΡΡΠΈΡΠ°Π΅ΠΌ ΠΏΡΠΎΠ΅ΠΊΡΠΈΡ c Π½Π° a
c = c - np.dot(c, a) * a
c = c / np.linalg.norm(c)
# Π’Π΅ΠΏΠ΅ΡΡ ΡΠΊΠ°Π»ΡΡΠ½ΠΎΠ΅ ΠΏΡΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ΠΈΠ΅ Π³ΠΎΡΠ°Π·Π΄ΠΎ ΠΌΠ΅Π½ΡΡΠ΅!
print (np.dot(c, a))
-2.7671064037337878e-08
-6.591949208711867e-17
Π£ΠΏΡΠ°ΠΆΠ½Π΅Π½ΠΈΠ΅
Π ΡΡΠΎΠΌ ΡΠΏΡΠ°ΠΆΠ½Π΅Π½ΠΈΠΈ ΠΌΡ ΡΠ΅Π°Π»ΠΈΠ·ΡΠ΅ΠΌ ΠΊΠ»Π°ΡΡΠΈΡΠ΅ΡΠΊΠΈΠΉ ΠΈ ΠΌΠΎΠ΄ΠΈΡΠΈΡΠΈΡΠΎΠ²Π°Π½Π½ΡΠΉ ΠΏΡΠΎΡΠ΅ΡΡΡ ΠΡΠ°ΠΌΠ°-Π¨ΠΌΠΈΠ΄ΡΠ° Π΄Π»Ρ ΠΏΠΎΡΡΡΠΎΠ΅Π½ΠΈΡ QR-ΡΠ°Π·Π»ΠΎΠΆΠ΅Π½ΠΈΡ ΠΌΠ°ΡΡΠΈΡΡ.
ΠΡ
ΠΎΠ΄: ΠΌΠ°ΡΡΠΈΡΠ° A \in \mathbb{R}^{n \times n} ΠΡΡ
ΠΎΠ΄: ΠΌΠ°ΡΡΠΈΡΡ Q ΠΈ R ΡΠ°ΠΊΠΈΠ΅, ΡΡΠΎ A = QR , ΠΏΡΠΈ ΡΡΠΎΠΌ Q ΠΎΡΡΠΎΠ³ΠΎΠ½Π°Π»ΡΠ½Π°Ρ, Π° R Π²Π΅ΡΡ
Π½Π΅ΡΡΠ΅ΡΠ³ΠΎΠ»ΡΠ½Π°Ρ. ΠΡ ΡΡΠΎΠΊΡΡΠΈΡΡΠ΅ΠΌΡΡ Π½Π° ΠΌΠ°ΡΡΠΈΡΠ΅ Q , ΠΏΠΎΡΠΎΠΌΡ ΡΡΠΎ ΠΈΠΌΠ΅Ρ Π΅Ρ, ΠΌΡ ΠΌΠΎΠΆΠ΅ΠΌ Π»Π΅Π³ΠΊΠΎ ΠΏΠΎΠ»ΡΡΠΈΡΡ R ΠΏΠΎ ΡΠΎΡΠΌΡΠ»Π΅ R = Q^T A .
Π§ΠΈΡΠ»Π΅Π½Π½Π°Ρ Π½Π΅ΡΡΡΠΎΠΉΡΠΈΠ²ΠΎΡΡΡ . ΠΠ»Π°ΡΡΠΈΡΠ΅ΡΠΊΠΈΠΉ ΠΏΡΠΎΡΠ΅ΡΡ ΠΡΠ°ΠΌΠ°-Π¨ΠΌΠΈΠ΄ΡΠ° (CGS) ΠΌΠΎΠΆΠ΅Ρ ΠΏΡΠΈΠ²ΠΎΠ΄ΠΈΡΡ ΠΊ Π±ΠΎΠ»ΡΡΠΈΠΌ ΠΏΠΎΠ³ΡΠ΅ΡΠ½ΠΎΡΡΡΠΌ ΠΏΡΠΈ Π²ΡΡΠΈΡΠ»Π΅Π½ΠΈΠΈ ΠΎΡΡΠΎΠ½ΠΎΡΠΌΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠΉ ΡΠΈΡΡΠ΅ΠΌΡ Π²Π΅ΠΊΡΠΎΡΠΎΠ², ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎ ΠΏΡΠΈ ΠΏΠ»ΠΎΡ
ΠΎΠΉ ΠΎΠ±ΡΡΠ»ΠΎΠ²Π»Π΅Π½Π½ΠΎΡΡΠΈ ΠΈΡΡ
ΠΎΠ΄Π½ΠΎΠΉ ΠΌΠ°ΡΡΠΈΡΡ. Π ΠΌΠ°ΡΠΈΠ½Π½ΠΎΠΉ Π°ΡΠΈΡΠΌΠ΅ΡΠΈΠΊΠ΅ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ ΠΏΠΎΡΠ΅ΡΡ ΠΎΡΡΠΎΠ³ΠΎΠ½Π°Π»ΡΠ½ΠΎΡΡΠΈ .
ΠΠΎΠ΄ΠΈΡΠΈΡΠΈΡΠΎΠ²Π°Π½Π½ΡΠΉ ΠΏΡΠΎΡΠ΅ΡΡ (MGS) . ΠΠ΄Π΅Ρ Π·Π°ΠΊΠ»ΡΡΠ°Π΅ΡΡΡ Π² ΡΠΎΠΌ, ΡΡΠΎΠ±Ρ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»ΡΠ½ΠΎ Π²ΡΡΠΈΡΠ°ΡΡ ΠΏΡΠΎΠ΅ΠΊΡΠΈΠΈ Π½Π° ΡΠΆΠ΅ ΠΏΠΎΡΡΡΠΎΠ΅Π½Π½ΡΠ΅ ΠΎΡΡΠΎΠ½ΠΎΡΠΌΠΈΡΠΎΠ²Π°Π½Π½ΡΠ΅ Π²Π΅ΠΊΡΠΎΡΠ°, ΡΠ°Π³ Π·Π° ΡΠ°Π³ΠΎΠΌ. Π€ΠΎΡΠΌΠ°Π»ΡΠ½ΠΎ, Π΅ΡΠ»ΠΈ q_1, \dots, q_{k-1} ΡΠΆΠ΅ ΠΏΠΎΡΡΡΠΎΠ΅Π½Ρ, ΡΠΎ Π΄Π»Ρ k -Π³ΠΎ Π²Π΅ΠΊΡΠΎΡΠ°:
q_k := a_k, \quad
q_k := q_k - (q_k,\,q_1)\,q_1, \quad
q_k := q_k - (q_k,\,q_2)\,q_2, \quad \dots
Π ΡΠΎΡΠ½ΠΎΠΉ Π°ΡΠΈΡΠΌΠ΅ΡΠΈΠΊΠ΅ ΡΡΠΎ ΡΠΊΠ²ΠΈΠ²Π°Π»Π΅Π½ΡΠ½ΠΎ ΠΊΠ»Π°ΡΡΠΈΡΠ΅ΡΠΊΠΎΠΌΡ ΠΏΡΠΎΡΠ΅ΡΡΡ, Π½ΠΎ Π² ΠΌΠ°ΡΠΈΠ½Π½ΠΎΠΉ Π°ΡΠΈΡΠΌΠ΅ΡΠΈΠΊΠ΅ MGS, ΠΊΠ°ΠΊ ΠΏΡΠ°Π²ΠΈΠ»ΠΎ, Π΄Π°ΡΡ Π±ΠΎΠ»Π΅Π΅ ΡΡΡΠΎΠΉΡΠΈΠ²ΠΎΠ΅ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅.
Π‘Π»ΠΎΠΆΠ½ΠΎΡΡΡ . ΠΠ±Π° Π°Π»Π³ΠΎΡΠΈΡΠΌΠ° ΠΈΠΌΠ΅ΡΡ Π°ΡΠΈΠΌΠΏΡΠΎΡΠΈΡΠ΅ΡΠΊΡΡ ΡΠ»ΠΎΠΆΠ½ΠΎΡΡΡ ΠΏΠΎΡΡΠ΄ΠΊΠ° O(n^2 m) , Π³Π΄Π΅ m \times n β ΡΠ°Π·ΠΌΠ΅ΡΠ½ΠΎΡΡΡ ΠΈΡΡ
ΠΎΠ΄Π½ΠΎΠΉ ΠΌΠ°ΡΡΠΈΡΡ. ΠΠ»Ρ ΠΊΠ²Π°Π΄ΡΠ°ΡΠ½ΠΎΠΉ ΠΌΠ°ΡΡΠΈΡΡ n \times n ΡΠ»ΠΎΠΆΠ½ΠΎΡΡΡ O(n^3) .
QR-ΡΠ°Π·Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ . ΠΠΎ Π³ΠΎΡΠΎΠ²ΠΎΠΉ ΠΎΡΡΠΎΠ½ΠΎΡΠΌΠΈΡΠΎΠ²Π°Π½Π½ΠΎΠΉ ΠΌΠ°ΡΡΠΈΡΠ΅ Q ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡΠΈ Π²Π΅ΡΡ
Π½Π΅ΡΡΠ΅ΡΠ³ΠΎΠ»ΡΠ½ΡΡ R , Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΡΠΌΠ½ΠΎΠΆΠΈΠ² Q^T A . Π’ΠΎΠ³Π΄Π° A = Q R .
import numpy as np
def hilbert_matrix(n):
H = np.zeros((n, n), dtype= float )
for i in range (n):
for j in range (n):
H[i, j] = 1.0 / (i + j + 1 )
return H
def generate_matrix(n, type = 'random' ):
if type == 'random' :
A = np.random.randn(n, n)
elif type == 'hilbert' :
A = hilbert_matrix(n)
return A
def classical_gs(A):
m, n = A.shape
Q = np.zeros((m, n), dtype= float )
for k in range (n):
# ΠΠ΅ΡΡΠΌ ΠΈΡΡ
ΠΎΠ΄Π½ΡΠΉ ΡΡΠΎΠ»Π±Π΅Ρ
v = A[:, k].copy()
# Π‘ΡΠΈΡΠ°Π΅ΠΌ Π²ΡΠ΅ ΡΠΊΠ°Π»ΡΡΠ½ΡΠ΅ ΠΏΡΠΎΠΈΠ·Π²Π΅Π΄Π΅Π½ΠΈΡ \alpha_j = (q_j, v) Π·Π°ΡΠ°Π½Π΅Π΅
# (Π·Π΄Π΅ΡΡ q_j ΡΠΆΠ΅ ΠΎΡΡΠΎΠ½ΠΎΡΠΌΠΈΡΠΎΠ²Π°Π½Ρ ΠΈΠ· ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠΈΡ
ΡΠ°Π³ΠΎΠ²)
alphas = np.array([np.dot(Q[:, j], v) for j in range (k)])
# ΠΡΡΠΈΡΠ°Π΅ΠΌ ΡΡΠΌΠΌΡ \sum_j \alpha_j * q_j
for j in range (k):
v -= alphas[j] * Q[:, j]
### YOUR CODE HERE
### YOUR CODE HERE
Q[:, k] = np.zeros_like(v) # WRONG!
return Q
def modified_gs(A):
m, n = A.shape
Q = np.zeros((m, n), dtype= float )
for k in range (n):
v = A[:, k].copy()
# Π ΠΠΠΠΠ€ΠΠ¦ΠΠ ΠΠΠΠΠΠΠ Π°Π»Π³ΠΎΡΠΈΡΠΌΠ΅ Π½Π° ΠΊΠ°ΠΆΠ΄ΠΎΠΌ ΡΠ°Π³Π΅ j
# Π±Π΅ΡΡΠΌ ΡΠ΅ΠΊΡΡΠ΅Π΅ "ΡΠ²Π΅ΠΆΠ΅Π΅" v
### YOUR CODE HERE
for j in range (k):
pass
Q[:, k] = np.zeros_like(v) # WRONG!
return Q
# ΠΡΠΈΠΌΠ΅Ρ: ΠΏΡΠΎΠ²Π΅ΡΡΠ΅ΠΌ ΠΎΡΡΠΎΠ³ΠΎΠ½Π°Π»ΠΈΠ·Π°ΡΠΈΡ Π½Π° ΠΌΠ°ΡΡΠΈΡΠ΅ ΠΠΈΠ»ΡΠ±Π΅ΡΡΠ°
n = 10
A = generate_matrix(n, type = 'hilbert' )
Q_cgs = classical_gs(A)
Q_mgs = modified_gs(A)
# ΠΡΠ΅Π½ΠΈΠ²Π°Π΅ΠΌ "ΠΎΡΠΈΠ±ΠΊΡ ΠΎΡΡΠΎΠ³ΠΎΠ½Π°Π»ΡΠ½ΠΎΡΡΠΈ" ΠΊΠ°ΠΊ ||Q^T Q - I|| ΠΏΠΎ Π€ΡΠΎΠ±Π΅Π½ΠΈΡΡΡ
err_cgs = np.linalg.norm(Q_cgs.T @ Q_cgs - np.eye(n), ord = 'fro' )
err_mgs = np.linalg.norm(Q_mgs.T @ Q_mgs - np.eye(n), ord = 'fro' )
# Π€ΡΠΎΠ±Π΅Π½ΠΈΡΡΠΎΠ²Π° Π½ΠΎΡΠΌΠ° Π΅Π΄ΠΈΠ½ΠΈΡΠ½ΠΎΠΉ ΠΌΠ°ΡΡΠΈΡΡ I (ΡΡΠΎ sqrt(n))
norm_I_fro = np.linalg.norm(np.eye(n), ord = 'fro' )
rel_cgs_fro = err_cgs / norm_I_fro
rel_mgs_fro = err_mgs / norm_I_fro
print ("ΠΠ±ΡΠΎΠ»ΡΡΠ½Π°Ρ ΠΎΡΠΈΠ±ΠΊΠ° (CGS) =" , err_cgs)
print ("ΠΠ±ΡΠΎΠ»ΡΡΠ½Π°Ρ ΠΎΡΠΈΠ±ΠΊΠ° (MGS) =" , err_mgs)
print ("ΠΡΠ½ΠΎΡΠΈΡΠ΅Π»ΡΠ½Π°Ρ ΠΎΡΠΈΠ±ΠΊΠ° (CGS) =" , rel_cgs_fro)
print ("ΠΡΠ½ΠΎΡΠΈΡΠ΅Π»ΡΠ½Π°Ρ ΠΎΡΠΈΠ±ΠΊΠ° (MGS) =" , rel_mgs_fro)
ΠΠ±ΡΠΎΠ»ΡΡΠ½Π°Ρ ΠΎΡΠΈΠ±ΠΊΠ° (CGS) = 3.4653383412436143
ΠΠ±ΡΠΎΠ»ΡΡΠ½Π°Ρ ΠΎΡΠΈΠ±ΠΊΠ° (MGS) = 8.763548618214397e-05
ΠΡΠ½ΠΎΡΠΈΡΠ΅Π»ΡΠ½Π°Ρ ΠΎΡΠΈΠ±ΠΊΠ° (CGS) = 1.095836202143963
ΠΡΠ½ΠΎΡΠΈΡΠ΅Π»ΡΠ½Π°Ρ ΠΎΡΠΈΠ±ΠΊΠ° (MGS) = 2.7712774019178854e-05