Microsoft MVP성태의 닷넷 이야기
Math: 22. 행렬로 바라보는 피보나치 수열 [링크 복사], [링크+제목 복사]
조회: 12824
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

행렬로 바라보는 피보나치 수열

다음의 책을 보니 재미있는 내용이 있습니다. ^^

프로그래머를 위한 선형대수
; http://www.yes24.com/24/goods/39446808

(평을 보시면 아시겠지만, 저 역시 추천하고 싶은 책입니다. ^^)

249페이지에 보면 "자기회귀모델(AR: AutoRegressive)"의 이산시간에 대한 예로,

오늘의 ζ(t)는 어제의 ζ(t - 1), 이틀 전의 ζ(t - 2), 사흘 전의 ζ(t - 3)과 오늘의 u(t)에 따라 다음과 같이 정해진다.

ζ(t) = -0.5ζ(t - 1) + 0.34ζ(t - 2) + 0.08ζ(t - 3) + 2u(t)

초기 조건 ζ(0) = 0.78, ζ(-1) = 0.8, ζ(-2) = 1.5

소개가 되면서 다음과 같이 행렬 표현을 합니다.




저걸 보니, 피보나치 수열이 생각났습니다.

황금비율 증명 - 피보나치 수와 연분수의 관계
; https://www.sysnet.pe.kr/2/0/1312

역시 초깃값이 주어지고 x(t)는 x(t - 1)에 의해 결정되니까요. 따라서 위와 같은 기준으로 피보나치 수열을 바라보면 다음과 같이 정리가 됩니다.

ζ(t) = 1ζ(t - 1) + 1ζ(t - 2)

초기 조건 ζ(0) = 1, ζ(-1) = 0

간단하게 t = 1 ~ 4까지 테스트하면 이렇게 되고,

t = 1일 때, ζ(1) = ζ(1 - 1) + ζ(1 - 2) = ζ(0) + ζ(-1) = 1 + 0 = 1
t = 2일 때, ζ(2) = ζ(2 - 1) + ζ(2 - 2) = ζ(1) + ζ(0) = 1 + 1 = 2
t = 3일 때, ζ(3) = ζ(3 - 1) + ζ(3 - 2) = ζ(2) + ζ(1) = 2 + 1 = 3
t = 4일 때, ζ(4) = ζ(4 - 1) + ζ(4 - 2) = ζ(3) + ζ(2) = 3 + 2 = 5

이를 행렬로 표현하면 다음과 같습니다.




마찬가지로 t = 1 ~ 4까지에 대해 행렬로 계산하면 이렇게 됩니다.







따라서 (초깃값 2개를 넘어) n 번째 피보나치 수열은,




보는 바와 같이 행렬 [1 1; 1 0]에 대해 n 승을 하고 그 값을 [1 0] 행렬에 곱하면 n 번째 피보나치 수열이 구해지는 것입니다. 실제로 octave 같은 도구를 이용해 다음과 같이 행렬 계산을 바로 해볼 수 있습니다.

function fib_1()
  
a = [1 1; 1 0]
b = [1;0]
a ^ 1 * b
a ^ 2 * b
a ^ 3 * b
a ^ 4 * b
a ^ 5 * b

endfunction

위의 함수를 실행하면 2*1 행렬이 5개가 출력되는 데 그것의 첫 번째 원소들을 보면 1, 2, 3, 5, 8로 피보나치 수열이 나옵니다.




행렬로 표현된 피보나치 계산에서 고윳값/고유벡터를 이용해 풀어보면 재미있는 결과가 나옵니다.

[선형대수학 #3] 고유값과 고유벡터 (eigenvalue & eigenvector)
; http://darkpgmr.tistory.com/105

행렬 [1 1; 1 0]에 대한 고윳값, 고유벡터를 계산해 보면,




위의 행렬식을 구하면,

= (1 - λ)(0 - λ) - 1
= λ2 - λ -1


위와 같이 구한 특성 다항식을 특성 방정식에 따라 0 값이 나오는 해를 구하면,

det(A - λ E) = 0

λ2 - λ -1 = 0

근의 공식에 따라,






와 같이 계산됩니다. 고윳값을 구했으니 고유벡터까지 구해볼까요? ^^



연립 방정식으로 풀으면,

(1 - λ)vx + vy = 0
vx - λvy = 0
vx = λvy

따라서, vx가 vy의 λ배로 이뤄진 무수히 많은 벡터 = [λt, t]


그럼 고유 벡터를 아무거나 다음과 같이 선정할 수 있습니다.



따라서 고윳값 λ의 2가지 값에 대해,






이 중에서 고유 벡터를 [(1 + sqrt(5)) / 2, 1]인 쌍으로 골라 보겠습니다. 이를 다시 Gram-Schmidt 정규 직교로 바꾸면,

Matlab/Octave로 Gram-Schmidt 정규 직교 집합 구하는 방법
; https://www.sysnet.pe.kr/2/0/11235

(0.52573, -0.85065), (-0.85065, -0.52573)로 구할 수 있습니다. 즉, 이 2개의 벡터 각각에 대응하는 λ배의 모든 벡터들이 고유 벡터들이 됩니다.




실제로 위의 과정들을 간단하게 octave로 구할 수 있습니다.

a = [1 1; 1 0]
[ev, ei] = eig(a)

ev = 
    0.52573 -0.85065
   -0.85065 -0.52573

ei =

Diagonal Matrix

   -0.61803   0
   0          1.61803

또한, Av = λv인 것도 다음과 같이 쉽게 계산해볼 수 있습니다.

a * [0.52573, -0.85065]'
ans =

  -0.32492
   0.52573

-0.61803 * [0.52573 -0.85065]'
ans =

  -0.32492
   0.52573




피보나치 수열의 고윳값과 고유벡터를 구했으니 n 번째 값을 구하는 방법에 대해 행렬의 성질로 다시 살펴보겠습니다.

"[선형대수학 #3] 고유값과 고유벡터 (eigenvalue & eigenvector)" 글에 보면 다음과 같은 공식이 나옵니다.

A = 행렬
P = 행렬 A의 고유벡터들을 열벡터로 하는 행렬
Λ = 교윳값들을 대각 원소로 하는 대각 행렬

AP = PΛ
A = PΛP-1

이를 기반으로 A의 n 승을 다음과 같이 쉽게 구할 수 있는 방법을 포함하고 있습니다.

Ak = (PΛP-1)k
   = (PΛP-1)(PΛP-1)......(PΛP-1)
   = PΛkP-1
   = Pdiag(λk1,......,λkn)P-1

따라서, 가령 5번째 피보나치 수를 구하고 싶다면 고유 벡터와 그것의 역행렬만 구한 후 고윳값 2개를 대각 행렬로 갖는 것만 5 승을 해주면 되는 것입니다. 이것을 octave로 다음과 같이 테스트할 수 있습니다.

ev * ei ^ 5 * inverse(ev)
ans =

    8.0000  5.0000
    5.0000  3.0000

즉, 고윳값을 알기 전에는 다음과 같은 행렬 계산이었지만,




고윳값을 알게 된 이상, 그것은 대각행렬의 n 승으로 바뀌었기 때문에 단순히 스칼라 값인 고윳값 2개만 n 승을 해주면 되는 문제로 바뀐 것입니다.




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 9/11/2017]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... [31]  32  33  34  35  36  37  38  39  40  41  42  43  44  45  ...
NoWriterDateCnt.TitleFile(s)
12851정성태11/1/20217489스크립트: 34. 파이썬 - MySQLdb 기본 예제 코드
12850정성태10/27/20218662오류 유형: 765. 우분투에서 pip install mysqlclient 실행 시 "OSError: mysql_config not found" 오류
12849정성태10/17/20217767스크립트: 33. JavaScript와 C#의 시간 변환 [1]
12848정성태10/17/20218745스크립트: 32. 파이썬 - sqlite3 기본 예제 코드 [1]
12847정성태10/14/20218604스크립트: 31. 파이썬 gunicorn - WORKER TIMEOUT 오류 발생
12846정성태10/7/20218357스크립트: 30. 파이썬 __debug__ 플래그 변수에 따른 코드 실행 제어
12845정성태10/6/20218192.NET Framework: 1120. C# - BufferBlock<T> 사용 예제 [5]파일 다운로드1
12844정성태10/3/20216192오류 유형: 764. MSI 설치 시 "... is accessible and not read-only." 오류 메시지
12843정성태10/3/20216650스크립트: 29. 파이썬 - fork 시 기존 클라이언트 소켓 및 스레드의 동작파일 다운로드1
12842정성태10/1/202124980오류 유형: 763. 파이썬 오류 - AttributeError: type object '...' has no attribute '...'
12841정성태10/1/20218482스크립트: 28. 모든 파이썬 프로세스에 올라오는 특별한 파일 - sitecustomize.py
12840정성태9/30/20218577.NET Framework: 1119. Entity Framework의 Join 사용 시 다중 칼럼에 대한 OR 조건 쿼리파일 다운로드1
12839정성태9/15/20219627.NET Framework: 1118. C# 11 - 제네릭 타입의 특성 적용파일 다운로드1
12838정성태9/13/20219287.NET Framework: 1117. C# - Task에 전달한 Action, Func 유형에 따라 달라지는 async/await 비동기 처리 [2]파일 다운로드1
12837정성태9/11/20218197VC++: 151. Golang - fmt.Errorf, errors.Is, errors.As 설명
12836정성태9/10/20217800Linux: 45. 리눅스 - 실행 중인 다른 프로그램의 출력을 확인하는 방법
12835정성태9/7/20219052.NET Framework: 1116. C# 10 - (15) CallerArgumentExpression 특성 추가 [2]파일 다운로드1
12834정성태9/7/20217417오류 유형: 762. Visual Studio 2019 Build Tools - 'C:\Program' is not recognized as an internal or external command, operable program or batch file.
12833정성태9/6/20216890VC++: 150. Golang - TCP client/server echo 예제 코드파일 다운로드1
12832정성태9/6/20217743VC++: 149. Golang - 인터페이스 포인터가 의미 있을까요?
12831정성태9/6/20216278VC++: 148. Golang - 채널에 따른 다중 작업 처리파일 다운로드1
12830정성태9/6/20218523오류 유형: 761. Internet Explorer에서 파일 다운로드 시 "Your current security settings do not allow this file to be downloaded." 오류
12829정성태9/5/202110169.NET Framework: 1115. C# 10 - (14) 구조체 타입에 기본 생성자 정의 가능파일 다운로드1
12828정성태9/4/20218295.NET Framework: 1114. C# 10 - (13) 단일 파일 내에 적용되는 namespace 선언파일 다운로드1
12827정성태9/4/20218244스크립트: 27. 파이썬 - 웹 페이지 데이터 수집을 위한 scrapy Crawler 사용법 요약
12826정성태9/3/202110463.NET Framework: 1113. C# 10 - (12) 문자열 보간 성능 개선 [1]파일 다운로드1
... [31]  32  33  34  35  36  37  38  39  40  41  42  43  44  45  ...