행렬을 대각화해야 하는 제곱을 구한다. 이어서 수열의 일반항도 구한다.

처음에



행렬의 거듭제곱을 요구하고 싶을 때가 최근 자주 있어, 그 때마다 매번 조사하고 있었으므로 비망록적으로 남긴다.
예로서 피보나치 수열의 일반항의 도출 등이다.

행렬의 대각화는 무엇입니까? (수식)



행렬의 대각화란 다음과 같이 대각 성분만을 남겨 다른 것을 0으로 하는 것.
A = 
\begin{pmatrix}
a & b \\
c & d
\end{pmatrix}
→
\begin{pmatrix}
e & 0 \\
0 & f
\end{pmatrix}
\\こんなの

행렬의 N승 계산하는 귀찮다~
스칼라 배가되어 주면 편한데~
라는 동기 부여로 만들어졌다고 이해하고 있기 때문에, 그런 방침으로 수식화해 간다.
A \vec{x} =\begin{pmatrix}
1 & 2 \\
4 & 3
\end{pmatrix}
\begin{pmatrix}
x \\
y
\end{pmatrix}   

라고 하는 수식이 있어 A를 x에 왼쪽으로부터 건다고 하는 조작이 λ를 x에 걸린다고 하는 조작과 동일한 람다를 갖고 싶기 때문에 이하와 같은 식을 생각한다. E는 단위 행렬
A \vec{x} = λE \vec{x} 

이것을 이항하고
\begin{align}
A \vec{x} - λE \vec{x} = 0 \\
= (A - λE) \vec{x} \\ \\
= \begin{pmatrix}
1-λ & 2 \\
4 & 3-λ
\end{pmatrix}
\begin{pmatrix}
x \\
y
\end{pmatrix}
= \begin{pmatrix}
0 \\
0
\end{pmatrix}
\end{align}

이때 x와 y가 0이라면 아무것도 기쁘지 않기 때문에 x와 y가 0이 아닐 때를 생각한다.
(A-λE)가 선형 종속이면 x와 y를 취하는 방법에 의해 계산 결과를 0으로 하는 것이 가능하다.
예를 들면 다음과
\begin{align}
\begin{pmatrix}
2 & 2 \\
4 & 4
\end{pmatrix}
\begin{pmatrix}
x \\
y
\end{pmatrix}
= \begin{pmatrix}
0 \\
0
\end{pmatrix}\\
x=1\\
y=-1\\
とすれば成り立つ
\end{align}

그래서,
선형 종속이면 행렬식의 결과가 0이 되므로, det(A-λE)=0이 되는 λ를 조사한다
\begin{align}
\begin{vmatrix}
1-λ & 2 \\
4 & 3-λ
\end{vmatrix} 
= λ^2 - 4λ - 5 = (λ + 1)(λ - 5) = 0 \\
λ = -1, 5
\end{align}

다음으로 각 λ의 시간의 x와 y를 계산한다.
\begin{align}
λ = -1のとき\\ \begin{pmatrix}
2 & 2\\
4 & 4
\end{pmatrix}
\begin{pmatrix}
x\\
y
\end{pmatrix} = 
\begin{pmatrix}
0\\
0
\end{pmatrix}
\\
x = 1, y = - 1\\\\

λ = 5のとき\\
\begin{pmatrix}
-4 & 2\\
4 & -2
\end{pmatrix} 
\begin{pmatrix}
x\\
y
\end{pmatrix} =
\begin{pmatrix}
0\\
0
\end{pmatrix}
\\
x = 1, y = 2

\end{align}

각각 곱했을 때에 대응하는 x, y와 λ가 걸리게 하면 이하가 된다
여기서 λ를 대각 성분으로 한 행렬을 D,
람다에 대응하는 x와 y의 쌍을 P로 한다.

\begin{align}
\begin{pmatrix}
1 & 1\\
- 1 & 2
\end{pmatrix}
\end{align}
\begin{pmatrix}
-1 & 0\\
0 & 5
\end{pmatrix}
 = P D = AP 


※지금 구한 DP는 Ax와 같고, P는 x의 조이므로 AP=DP가 된다

지금 원하는 것은 대각화된 D이므로
PD = AP \\
D = P^{-1}AP

되어 대각화할 수 있다.
D를 K승하면
D = P^{-1}AP \\
D^k = (P^{-1}AP) * (P^{-1}AP) * .... * (P^{-1}AP) = P^{-1}A^kP\\
PD^kP^{-1} = A^k

와 변형하면 원래의 A를 K승한 것과 같은 결과가 된다

여기까지 전좌

사용하는 상황 (파이썬 사용)



이와 같은 수열이 주어져 일반항을 구해 주세요라고 말했을 때
S = 0, 2, 2, 6, 10, 22, 42, 86, 170, ...

우선 항수가 늘어날 때의 룰을 관찰한다.
분명히 다음 규칙으로 늘어난 것 같습니다.
項数=k\\
S_{k+1} = \left\{
\begin{array}{ll}
2S_k + 2 & k(mod2)=0 \\
2S_k - 2 & k(mod2)=1
\end{array}
\right.

곱하면 다음 항으로 천이하는 Sk가 Sk + 1로 천이하는 행렬 A를 생각한다.
\begin{align}
S_{k+1} = AS_k
\\
\begin{pmatrix}
S_{k+1} \\
2(-1)^{k+1}
\end{pmatrix}=
\begin{pmatrix}
2 & -1\\
0 & -1
\end{pmatrix}
\begin{pmatrix}
A_k \\
2(-1)^{k}
\end{pmatrix}
\end{align}

여기서 A를 대각화한다.
python군에서는 기쁜 일에 행렬을 건네주면 「행렬의 대각화는 무엇?」의 항의 P와 D를 취득할 수 있다.
여기에서는 P와 A, P^(-1)로부터 D를 구하고 있다
import sympy as sp

sp.init_printing()
A = sp.Matrix( [[2,-1],[0,-1]])

# 「行列の対角化って何?」の項のPと同じものを取得
P= A.eigenvects()[0][2][0].col_insert(1, A.eigenvects()[1][2][0])
P_inv = P.inv()

# 対角行列取得
D = P_inv * A * P

# 変数kを設定
k = sp.symbols("k")

# 一般項を出力
# 上の式がSkになっている
print(P * D**k * P.inv() * sp.Matrix([[0],[-2]])[0])

출력 결과
일반항은 하기 식

for k in range(10):
    ans = (P * D**k * P.inv() * sp.Matrix([[0],[-2]]))[0]
    print(f"{k}項目:{ans}")


일반 항의 출력 결과 확인

0개 항목:0
1개 항목:2
2개 항목:2
3개 항목:6
4개 항목: 10
5개 항목: 22
6개 항목: 42
7 품목:86
8개 항목:170
9개 항목: 342

이와 같이 행렬의 곱셈으로 표현할 수 있는 수열의 일반항은 행렬의 대각화로 간단하게 작성할 수 있는 경우가 있다.

예제 피보나치 시퀀스의 일반 용어 (파이썬 사용)



3항간 점화식의 경우도 살펴보자.
S = 0, 1, 1, 2, 3, 5, 8, 13, 21, ...

이렇게 표현할 수 있는
項数=k\\
S_{k+1} = S_{k} + S_{k-1}

곱하면 다음 항으로 천이하는 Sk가 Sk + 1로 천이하는 행렬 A를 생각한다.
\begin{align}
S_{k+1} = AS_k
\\
\begin{pmatrix}
S_{k+1} \\
S_{k}
\end{pmatrix}=
\begin{pmatrix}
1 & 1\\
1 & 0
\end{pmatrix}
\begin{pmatrix}
S_k \\
S_{k-1}
\end{pmatrix}
\end{align}

여기서 S를 대각화
import sympy as sp

sp.init_printing()
A = sp.Matrix( [[1,1],[1,0]])

# 「行列の対角化って何?」の項のPと同じものを取得
P= A.eigenvects()[0][2][0].col_insert(1, A.eigenvects()[1][2][0])
P_inv = P.inv()

# 対角行列取得
# D = P_inv * A * P
D = sp.Matrix(np.diag(list([A.eigenvects()[0][0], A.eigenvects()[1][0]])))

# 変数kを設定
k = sp.symbols("k")
# 一般項を出力

# sp.Matrix([[1],[0]]))はSk1とSk0
# [1]でSkの一般項が取得できる
sp.simplify(P * D**k * P_inv *  sp.Matrix([[1],[0]]))[1]

출력 결과
k번째 일반항이 다음

for k in range(10):
    ans = sp.simplify(P * D**k * P_inv *  sp.Matrix([[1],[0]]))[1]
    print(f"{k}項目:{ans}")

일반 항의 출력 결과 확인

0개 항목:0
1개 항목:1
2개 항목:1
3개 항목:2
4개 항목:3
5개 항목:5
6개 항목:8
7 품목:13
8개 항목: 21
9개 항목:34

좋은 웹페이지 즐겨찾기