2023.01.08 - [선형대수학/implement_linearAlgebra] - 소거법을 이용한 Ax = b 의 풀이
소거법을 이용한 Ax = b 의 풀이
R^3 공간에서 세 평면이 만나는 것을 시각화하기는 쉽지 않다. R^n 공간에서 초평면 n 개가 한 점에서 만남을 시각화하기도 어려움, 하지만 열벡터의 일차결합은 쉽다. 행렬 A 에는 반드시 3(또는 n)
teach-meaning.tistory.com
원래 행렬 A 는 마지막으로 얻은 행렬 U 와 어떤 관계가 있을까?
1 단계에서 4*4 크기의 문제는 1행의 배수를 다른 행에서 제거함으로써 3*3 크기의 문제로 축소했다.
위 식에서 우변의 첫 번째 행렬이 행렬 A 에서 제거되었다. 이것이 랭크 1인 행렬이다.
A = np.array(([1,2,3,4],[6,7,8,9],[7,13,12,11],[13,17,4,3]))
A
>>>
array([[ 1, 2, 3, 4],
[ 6, 7, 8, 9],
[ 7, 13, 12, 11],
[13, 17, 4, 3]])
for i in range(A.shape[0]):
exec(f"l{i}u{i} = []")
a = A[i][i]
exec(f"l{i}u{i}.append(A[i])")
for j in range(i+1, A.shape[0]):
exec(f"l{i}u{i}.append((A[j][i] / a) * A[i])")
A[j] = A[j] - (A[j][i] / a) * A[i]
l0u0
>>>
[array([1, 2, 3, 4]),
array([ 6., 12., 18., 24.]),
array([ 7., 14., 21., 28.]),
array([13., 26., 39., 52.])]
l1u1
>>>
[array([ 0, -5, -10, -15]),
array([ 0., -1., -2., -3.]),
array([ 0., -9., -18., -27.])]
l2u2
>>>
[array([ 0, 0, -7, -14]),
array([ 0., 0., -17., -34.])]
l3u3
>>>
[array([ 0, 0, 0, 12])]
A = l0u0 + l1u1 + l2u2 + l3u3
numpy array 로의 변환,
list_a = []
for i in range(A.shape[0]):
a = []
for j in range(A.shape[0]-i):
for k in range(A.shape[1]):
exec(f"a.append(l{i}u{i}[j][k])")
list_a.append(a)
for i in range(len(list_a)):
exec(f"l{i}u{i} = list_a[i]")
exec(f"l{i}u{i} = np.array(l{i}u{i}).reshape(len(list_a)-i,-1)")
l0u0
>>>
array([[ 1., 2., 3., 4.],
[ 6., 12., 18., 24.],
[ 7., 14., 21., 28.],
[13., 26., 39., 52.]])
l1u1
>>>
array([[ 0., -5., -10., -15.],
[ 0., -1., -2., -3.],
[ 0., -9., -18., -27.]])
l2u2
>>>
array([[ 0., 0., -7., -14.],
[ 0., 0., -17., -34.]])
l3u3
>>>
array([[ 0, 0, 0, 12]])
네 np array 를 합치기 위한 과정 수정,
for i in range(len(list_a)):
exec(f"l{i}u{i} = list_a[i]")
exec(f"l{i}u{i} = np.array(l{i}u{i}).reshape(len(list_a)-i,-1)")
if i != 0:
exec(f"l{i}u{i} = np.concatenate((np.zeros((i,4)), l{i}u{i}))")
l0u0
>>>
array([[ 1., 2., 3., 4.],
[ 6., 12., 18., 24.],
[ 7., 14., 21., 28.],
[13., 26., 39., 52.]])
l1u1
>>>
array([[ 0., 0., 0., 0.],
[ 0., -5., -10., -15.],
[ 0., -1., -2., -3.],
[ 0., -9., -18., -27.]])
l2u2
>>>
array([[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., -7., -14.],
[ 0., 0., -17., -34.]])
l3u3
>>>
array([[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 0.],
[ 0., 0., 0., 12.]])
new_A = np.zeros((4,4))
for i in range(len(list_a)):
exec(f"A = A + l{i}u{i}")
new_A
>>>
array([[ 1., 2., 3., 4.],
[ 6., 7., 8., 9.],
[ 7., 13., 12., 11.],
[13., 17., 4., 3.]])
A
>>>
array([[ 1., 2., 3., 4.],
[ 6., 7., 8., 9.],
[ 7., 13., 12., 11.],
[13., 17., 4., 3.]])
합이 동일한 것을 확인할 수 있다.
A = LU 를 얻을 수 있다.
위 코드의 수정
L = np.zeros((A.shape[0], A.shape[1]))
L
>>>
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
U = np.zeros((A.shape[0], A.shape[1]))
U[0] = A[0]
U
>>>
array([[1., 2., 3., 4.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
for i in range(A.shape[0]-1):
a = A[i][i]
if(a == 0):
continue
for j in range(i+1, A.shape[0]):
L[j][i] = (A[j][i] / a)
A[j] = A[j] - (A[j][i] / a) * A[i]
U[j] = A[j]
for i in range(A.shape[0]):
L[i][i] = 1
L
>>>
array([[ 1. , 0. , 0. , 0. ],
[ 6. , 1. , 0. , 0. ],
[ 7. , 0.2 , 1. , 0. ],
[13. , 1.8 , 2.42857143, 1. ]])
U
>>>
array([[ 1., 2., 3., 4.],
[ 0., -5., -10., -15.],
[ 0., 0., -7., -14.],
[ 0., 0., 0., 12.]])
L.dot(U)
>>>
array([[ 1., 2., 3., 4.],
[ 6., 7., 8., 9.],
[ 7., 13., 12., 11.],
[13., 17., 4., 3.]])
A
>>>
array([[ 1, 2, 3, 4],
[ 6, 7, 8, 9],
[ 7, 13, 12, 11],
[13, 17, 4, 3]])
LU 의 값이 A 와 동일한 것을 확인할 수 있다.
LU 분해 시 소거법의 아이디어를 이용해서 A = LU 를 이끌어 냈다.
즉, 나머지 n-1 개의 방정식에서 x_1 를 제거하여 문제의 크기를 n 에서 n-1 로 줄인다. 이 과정에서는 1 행의 배수를 뺏고, 제거한 행렬의 랭크는 1이다.
아이디언느 A 의 열을 다루는 대신 U 의 행을 이용하는 것이다.
핵심은 뺄셈하는 행이 추축행이고, 이는 행렬 U 안에 이미 존재하는 것,
이로써 행 교환 없이 A = LU 를 얻었다.
'선형대수학 > implement_linearAlgebra' 카테고리의 다른 글
소거법을 이용한 Ax = b 의 풀이 (0) | 2023.01.08 |
---|---|
A = LU (0) | 2023.01.08 |
implement_subspace(2) (2) | 2023.01.07 |
implement_subspace (1) | 2023.01.07 |
4.5 대칭 행렬 (0) | 2022.12.19 |