몬테카를로 기법은 결과를 계산하기 위해 반복적인 무작위 샘플링에 의존하는 알고리즘으로서 거의 모든 자연과학, 공학 분야에 응용됩니다. 이번 포스트에서는 간단한 몬테카를로 시뮬레이션으로 파이를 ($\pi$) 계산해보도록 하겠습니다.
테일러 급수 이용하기
$\pi$를 계산하는 표준 방법은 수학적인 정의를 적용하는 것입니다. 우리는 $\pi/4$의 탄젠트 (tangent) 값이 1임을 알고 있으므로 다음과 같이 탄젠트 함수의 역수인 arctangent로 $\pi$를 정의할 수 있습니다.
$\pi=4*arctan(1)$
공학 수학을 배우신 분들이라면 arctangent 함수는 다음과 같이 테일러 급수로 전개할 수 있음을 아실 겁니다. (테일러 급수는 미적분학에서 무한 번 미분이 가능한 함수를 도함수들의 한 점에서의 값으로 계산된 항의 무한합으로 표현하는 방법으로 자세한 내용은 위키피디아를 참조하시길 바랍니다)
$arctan(x) = \Sigma_{i=0} (-1)^{i} \frac{x^{2i+1}}{2i+1}$
따라서 위 식에 $x=1$을 적용하면 $\pi$를 구할 수 있습니다. 다만, 수치적으로 무한대 계산을 불가능하므로 정확히는 $\pi$의 근사치를 구할 수 있겠죠. 파이썬으로도 다음과 같이 간단히 구현할 수 있습니다.
def pi_taylor(n):
pi = 0
for i in range(n):
pi += 4./(2*i+1)*(-1)**i
print(i, pi)
pi_taylor(1000)
Plouffe 공식
1995년에 발표된 Plouffe 공식으로 $\pi$를 구할 수 있습니다. 코드를 돌려보면 100회 반복했을 때 $\pi$에 거의 근접한 것을 볼 수 있습니다.
$\pi=\Sigma_{i=0}\frac{1}{16^i}(\frac{4}{8i+1}-\frac{2}{8i+4}-\frac{1}{8i+5}-\frac{1}{8i+6})$
from decimal import Decimal
def pi_plauffe(n):
pi = Decimal(0)
a, b, c, d = Decimal(4), Decimal(2), Decimal(1), Decimal(1)/Decimal(16)
for i in range(n):
i8 = Decimal(8)*i
pi += (d**i)*(a/(i8+1)-b/(i8+4)-c/(i8+5)-c/(i8+6))
return pi
pi_plauffe(100)
>>> Decimal('3.141592653589793238462643381')
- 위 코드에서는 소수점 단위의 정확한 계산을 위하여 고정소수점을 사용하는 decimal 모듈을 사용했습니다. decimal 모듈은 이진수 기반의 파이썬 float 연산을 십진수로 처리하여 정확한 소수점 자리를 표현할 때 사용합니다.
원의 면적 이용하기
$\pi$가 반지름 1인 원의 면적이라는 것에 근거해서 구할 수도 있습니다. 반지금 1인 원의 4분의 1을 정사각형 안에 그리고 정사각형 안에 균등 분포된 점 $(x, y)$를 무작위로 만들고 원 안에 얼마나 들어있는지를 확인하면 됩니다. 즉, 원 안에 있는 점의 개수와 전체 점의 개수 비율은 원의 면적 $\pi/4$을 정사각형의 면적 (1)로 나눈 값에 비례합니다. 이를 코드로 구현하면 다음과 같습니다.
from random import *
def pi_mc(n):
pi = 0
counter = 0
for i in range(n):
x = random()
y = random()
if x**2 + y**2 < 1:
counter += 1
pi = 4.*float(counter) / (i+1)
return pi
pi_mc(1000)
>>> 3.092
값을 보시면 아시겠지만 1000회를 돌렸음에도 Plouffe 수식보다 수렴이 한참 늦습니다. 따라서 $\pi$를 구하는 문제에서는 실질적인 가치가 없지만 어떠한 특정 유형의 문제에는 이러한 방법만 적용할 수 있습니다. 즉, 면적을 구하고자 난수를 사용했고 이 난수를 통해 원의 면적을 계산하는 적분을 근사하였는데, 이것이 바로 몬테카를로 시뮬레이션의 핵심 개념입니다. 따라서 수식 자체를 알 수 없거나 정확히 계산하기에는 너무 복잡할 경우 몬테카를로 기법을 활용할 수 있는 것이죠.
'Theory > Algorithms' 카테고리의 다른 글
몬테카를로 시뮬레이션 (3) - 부트스트랩 알고리즘 (bootstrap) (0) | 2022.03.09 |
---|---|
몬테카를로 시뮬레이션 (2) - 온라인 판매자 예제 (0) | 2022.02.26 |
Cholesky Decomposition (촐레스키 분해) - 파이썬 구현 (0) | 2022.02.20 |
Trie (0) | 2021.07.15 |
Sparse Matrix (희소행렬) 구현하기 (0) | 2021.07.05 |