用Python實現基於蒙特卡洛算法小實驗

用Python實現基於蒙特卡洛算法小實驗算法

用Python實現基於蒙特卡洛算法小實驗

蒙特卡洛算法思想bash

蒙特卡洛(Monte Carlo)法是一類隨機算法的統稱,提出者是大名鼎鼎的數學家馮·諾伊曼,他在20世紀40年代中期用馳名世界的賭城—摩納哥的蒙特卡洛來命名這種方法。dom

通俗的解釋一下蒙特卡洛算法的思想。假如籃子裏有1000個蘋果,讓你每次閉着眼睛拿1個,挑出最大的。因而你閉着眼睛隨機拿了一個,而後再隨機拿一個與第一個比,留下大的,再隨機拿一個,與前次留下的比較,又能夠留下大的……你每拿一次,留下的蘋果至少是當前最大的,循環往復這樣,拿的次數越多,挑出最大蘋果的可能性也就越大,但除非你把1000個蘋果都挑一遍,不然你沒法確定最終挑出來的就是最大的一個。也就是說,蒙特卡洛算法是樣本越多,越能找到最佳的解決辦法,但只是儘可能找最好的,不保證必定是最好的。函數

與它造成對比的是拉斯維加斯算法思想。假若有一把鎖,有1000把鑰匙進行選擇,但只有1把是對的。因而你每次隨機拿1把鑰匙去試,打不開就再換1把。你試的次數越多,打開最優解的機會就越大,但在打開以前,那些錯的鑰匙都是沒有用的。因此拉斯維加斯算法就是儘可能找最好的解決辦法,可是不保證能找到。假設試了999次後沒有任何一把鑰匙能打開鎖,真正的鑰匙是第1000把,可是樣本並無第1000次選擇,那麼拉斯維加斯算法就不能找到打開鎖的鑰匙。學習

蒙特卡洛和拉斯維加斯自己是兩座著名賭城,由於賭博中體現了許多隨機算法,因此藉此命名。它們只是歸納了隨機算法的特性,算法自己可能複雜,也可能簡單,在這兩類隨機算法之間的選擇,每每受到問題的侷限。若是問題要求在有限採樣內,必須給出一個解,但不要求是最優解,那就要用蒙特卡羅算法。反之,若是問題要求必須給出最優解,但對採樣沒有限制,那就要用拉斯維加斯算法。ui

蒙特卡洛算法實驗spa

這麼看來蒙特卡洛方法的理論支撐實際上是機率論或統計學中的大數定律。基本原理簡單描述是先大量模擬,而後計算一個事件發生的次數,再經過這個發生次數除以總模擬次數,獲得想要的結果。下面咱們以三個經典的小實驗來學習下蒙特卡洛算法思想。3d

1.計算圓周率pi(π)值code

實驗原理:在正方形內部有一個相切的圓,圓面積/正方形面積之比是(PixRxR)/(2Rx2R)= Pi/4。在這個正方形內隨機產生n個點,假設點落在圓內的機率爲P,那麼P=圓面積/正方形面積,則P= Pi/4。如何計算點落在圓內的機率P?能夠計算點與中心點的距離,判斷是否落在圓的內部,若這些點均勻分佈,用M表示落到圓內投點數 , N表示總的投點數,則圓周率Pi=4P=4xM/N。orm

實驗步驟:

(1)將圓心設在原點(0,0),以R爲半徑造成圓,則圓面積爲PixRxR

(2)將該圓外接正方形, 座標爲(-R,-R)(R,-R)(R, R)(-R,R),則該正方形面積爲R*R

(3)隨即取點(X,Y),使得-R <=X<=R而且-R <=Y<=R,即點在正方形內

(4)經過公式 XxX+YxY<= RxR判斷點是否在圓周內(直角三角形邊長公式)。

(5)設全部點(也就是實驗次數)的個數爲N,落在圓內的點(知足步驟4的點)的個數爲M,則P=M/N,因而Pi=4xM/N。

(6)運行結果爲3.143052

def cal_pai_mc(n=1000000):
 r = 1.0
 a, b = (0.0, 0.0)
 x_neg, x_pos = a - r, a + r
 y_neg, y_pos = b - r, b + r
 m = 0
 for i in range(0, n+1):
 x = random.uniform(x_neg, x_pos)
 y = random.uniform(y_neg, y_pos)
 if x**2 + y**2 <= 1.0:
 m += 1
 return (m / float(n)) * 4
複製代碼

2.計算函數定積分值

實驗原理:若要求函數f(x)從a到b的定積分,咱們能夠用一個比較容易算得面積的矩型包圍在函數的積分區間上(假設其面積爲Area),定積分值其實就是求曲線下方的面積。隨機地向這個矩形框裏面投點,統計落在函數f(x)下方的點數量佔全部點數量的比例爲P,那麼就能夠據此估算出函數f(x)從a到b的定積分爲Area×P。此處咱們將a和b設爲0和1,函數f(x)=x2。

運行結果爲0.333749

def cal_integral_mc(n = 1000000):
 x_min, x_max = 0.0, 1.0
 y_min, y_max = 0.0, 1.0
 m = 0
 for i in range(0, n+1):
 x = random.uniform(x_min, x_max)
 y = random.uniform(y_min, y_max)
 # x*x > y 表示該點位於曲線的下面。
 if x*x > y:
 m += 1
 #所求的積分值即爲曲線下方的面積與正方形面積的比
 return m / float(n)
複製代碼

3.計算函數極值,可避免陷入局部極值

實驗原理:極值是「極大值」 和 「極小值」的統稱。若是一個函數在某點的一個鄰域內到處都有肯定的值,函數在該點的值大於或等於在該點附近任何其餘點的函數值,則稱函數在該點的值爲函數的「極大值」。若是函數在該點的值小於或等於在該點附近任何其餘點的函數值,則稱函數在該點 的值爲函數的「極小值」。此處在區間[-2,2]上隨機生成一個數,求出其對應的y,找出其中最大值認爲是函數在[-2,2]上的極大值。

運行結果發現極大值185.1204262706596, 極大值點爲1.5144491499169481

def cal_extremum_mc(n = 1000000):
 y_max = 0.0
 x_min, x_max = -2.0, 2.0
 y = lambda x:200*np.sin(x)*np.exp(-0.05*x)#匿名函數
 for i in range(0, n+1):
 x0 = random.uniform(x_min, x_max)
 if y(x0) > y_max:
 y_max = y(x0)
 x_max = x0
 return y_max, x_max
複製代碼

以上三個例子也稱爲基於蒙特卡洛的投點法,由此得出的值並非一個精確值,而是一個近似值。當投點的數量愈來愈大時,這個近似值也越接近真實值。

更多的Python相關學習教程知識點也會慢慢的更新,進本都是經驗的總結,你們有什麼想看好這想學的Python知識,也能夠留言哦!

相關文章
相關標籤/搜索