蒙特卡羅法也稱統計模擬法、統計試驗法。是把概率現象作為研究對象的數值模擬方法,下面講兩個例子加深理解。
-
三門問題
你參加一個有獎競猜節目,現在面前有三個門,只有其中一個門后有獎,其余門后為空。你隨機選中一個門后,主持人打開另外兩個門中的一個門后,為空,接着,你有一個換門的機會,換還是不換?
不考慮其他因素
該問題已經有解,如果不換,那么主持人的操作跟你就沒有關系了,所以中獎概率為\(\frac{1}{3}\);如果換的話,你剛開始選門有三種情況,有一種是最開始選中了獎品,結果換到了其他門,而有兩種可能是最開始選中了沒有獎品的門,最后換到了有獎的門,那么中獎的概率就為 \(\frac{2}{3}\)。假設你現在不知道這個結論,那應該如何求解呢?代碼模擬,也叫蒙特卡洛模擬,關鍵是量大和隨機(區別於枚舉)。
模擬結果如下(代碼見最后):
-
蒙特卡洛求非線性規划初始值
非線性規划詳見數學規划模型
有如下的非線性規划模型:
\[\begin{align} &min\quad f(x) = x_1^2 + x_1x_2+x_3^2\\[0.3cm] &s.t = \begin{cases} x_1 + x_2 + x_3 \leq 100\\[0.2cm] x_1^2 + x_2^2 + x_1x_2x_3 \leq 200\\[0.2cm] x_1,x_2,x_3 \geq 0 \end{cases} \end{align} \]在對該非線性規划模型使用 Matlab 求解之前,需要設定 \(x_1,x_2,x_3\) 的初始值,初始值的選取對非線性規划求解非常重要,這里可以用蒙特卡洛來選取較好的初始值。
import random
import time
def game(result):
random.seed(time.time())
prize = random.randrange(1, 4) # 獎品所在門號
first = random.randrange(1, 4) # 第一次選中的門
# 主持人打開了一個空門
# 不換
if first == prize:
result[0] += 1 # 堅持得一分
else:
pass # 不得獎
# 換
if first != prize:
result[1] += 1 # 換得一分
else:
pass # 不得獎
def simulation():
result, times = [0.0, 0.0], 1000*1000
for i in range(times):
game(result)
print("共計模擬游戲 %d 次\n 換門中獎 %d 次,概率為 %lf\n 不換中獎 %d 次,概率為 %lf"
% (times, result[1], result[1]/times, result[0], result[0]/times))
if __name__ == "__main__":
simulation()