隨機算法
1. 蒙特卡羅模擬
蒙特卡羅(Monte Carlo)方法,又稱隨機抽樣或統計試驗方法,是以概率和統計理論方法為基礎的一種計算方法
使用隨機數(或更常見的偽隨機數)來解決很多計算問題的方法。
將所求解的問題同一定的概率模型相聯系,用電子計算機實現統計模擬或抽樣,以獲得問題的近似解。
① π的計算
② 計算積分 y = x**2
③ 排隊上廁所問題
import numpy as np import pandas as pd import matplotlib.pyplot as plt % matplotlib inline
# π的計算 from matplotlib.patches import Circle n = 10000 # 投點次數 r = 1.0 # 半徑 a, b = (0.0, 0.0) # 圓心 # 圓的信息 x_min, x_max = a-r, a+r y_min, y_max = b-r, b+r # 正方形區域邊界 x = np.random.uniform(x_min, x_max, n) # 均勻分布 y = np.random.uniform(y_min, y_max, n) # 在正方形區域內隨機投點 # numpy.random.uniform(low,high,size) → 從一個均勻分布[low,high)中隨機采樣,均勻分布 fig = plt.figure(figsize=(6, 6)) axes = fig.add_subplot(1, 1, 1) plt.plot(x, y, 'ro', markersize = 1) plt.axis('equal') # 制圖 d = np.sqrt((x - a)**2 + (y - b) ** 2) res = sum(np.where(d < r, 1, 0)) # 計算點到圓心的距離 # 統計落在圓內的點的數目 pi = 4 * res / n print(pi) circle = Circle(xy = (a,b),radius = r, alpha = 0.5 ,color = 'gray') axes.add_patch(circle) plt.grid(True, linestyle = "--",linewidth = "0.8") plt.show() # 繪制圓形
# 計算積分 y = x**2 n = 10000 # 投點次數 x_min, x_max = 0.0, 1.0 y_min, y_max = 0.0, 1.0 # 矩形區域邊界 x = np.random.uniform(x_min, x_max, n) # 均勻分布 y = np.random.uniform(y_min, y_max, n) # 在矩形區域內隨機投點 def f(x): return x**2 # 創建函數 y = x**2 res = sum(np.where(y < f(x), 1, 0)) # 統計 落在函數 y=x^2圖像下方的點的數目 integral = res / n print('integral: ', integral) # 計算 定積分的近似值 fig = plt.figure(figsize = (6,6)) axes = fig.add_subplot(111) axes.plot(x, y,'ro',markersize = 1) plt.axis('equal') # 繪制散點圖 xi = np.linspace(0,1,100) yi = xi ** 2 plt.plot(xi,yi,'--k') plt.fill_between(xi, yi, 0, color ='gray',alpha=0.5,label='area') plt.grid() # 繪制 y = x**2 面積圖
# 廁所排隊問題 # 1、兩場電影結束時間相隔較長,互不影響; # 2、每場電影結束之后會有20個人想上廁所; # 3、這20個人會在0到10分鍾之內全部到達廁所); # 4、每個人上廁所時間在1-3分鍾之間 # 首先模擬最簡單的情況,也就是廁所只有一個位置,不考慮兩人共用的情況則每人必須等上一人出恭完畢方可進行。 # 分析:對於每個人都有如下幾個參數: # 到達時間 / 等待時間 / 開始上廁所時間 / 結束時間 arrivingtime = np.random.uniform(0,10,size = 20) arrivingtime.sort() workingtime = np.random.uniform(1,3,size = 20) # np.random.uniform 隨機數:均勻分布的樣本值 startingtime = [0 for i in range(20)] finishtime = [0 for i in range(20)] waitingtime = [0 for i in range(20)] emptytime = [0 for i in range(20)] # 開始時間都是0 #print('arrivingtime\n',arrivingtime,'\n') #print('workingtime\n',workingtime,'\n') #print('startingtime\n',startingtime,'\n') #print('finishtime\n',finishtime,'\n') #print('waitingtime\n',waitingtime,'\n') #print('emptytime\n',emptytime,'\n') print('------') startingtime[0] = arrivingtime[0] # 第一個人之前沒有人,所以開始時間 = 到達時間 finishtime[0] = startingtime[0] + workingtime[0] # 第一個人完成時間 = 開始時間 + “工作”時間 waitingtime[0] = startingtime[0]-arrivingtime[0] # 第一個人不用等待 for i in range(1,len(arrivingtime)): if finishtime[i-1] > arrivingtime[i]: startingtime[i] = finishtime[i-1] else: startingtime[i] = arrivingtime[i] emptytime[i] = arrivingtime[i] - finishtime[i-1] finishtime[i] = startingtime[i] + workingtime[i] waitingtime[i] = startingtime[i] - arrivingtime[i] print('第%d個人:到達時間 開始時間 “工作”時間 完成時間 等待時間\n' %i, arrivingtime[i], startingtime[i], workingtime[i], finishtime[i], waitingtime[i], '\n') print('arerage waiting time is %f' %np.mean(waitingtime)) print('------') # 判斷:如果下一個人在上一個人完成之前到達,則 開始時間 = 上一個人完成時間, # 否則 開始時間 = 到達時間,且存在空閑時間 = 到達時間 - 上一個人完成時間 fig = plt.figure(figsize = (6,4)) plt.plot(waitingtime, '-go') plt.grid(True,linestyle='--', color = 'gray',linewidth = '0.8') plt.title('蒙特卡羅模擬 - 排隊上廁所問題') plt.show() # 圖表繪制
--->>
------ 第1個人:到達時間 開始時間 “工作”時間 完成時間 等待時間 1.47846212718 2.90015955179 2.43550313768 5.33566268947 1.42169742461 第2個人:到達時間 開始時間 “工作”時間 完成時間 等待時間 1.50766524856 5.33566268947 1.70026811206 7.03593080153 3.82799744091 第3個人:到達時間 開始時間 “工作”時間 完成時間 等待時間 1.68971606051 7.03593080153 2.55933351317 9.59526431469 5.34621474102 第4個人:到達時間 開始時間 “工作”時間 完成時間 等待時間 3.22500117584 9.59526431469 2.23730595589 11.8325702706 6.37026313886 第5個人:到達時間 開始時間 “工作”時間 完成時間 等待時間 3.68624845537 11.8325702706 1.96298225381 13.7955525244 8.14632181522 第6個人:到達時間 開始時間 “工作”時間 完成時間 等待時間 3.748728758 13.7955525244 1.13434491219 14.9298974366 10.0468237664 第7個人:到達時間 開始時間 “工作”時間 完成時間 等待時間 3.76353770932 14.9298974366 2.97251793218 17.9024153688 11.1663597273 第8個人:到達時間 開始時間 “工作”時間 完成時間 等待時間 4.04448060386 17.9024153688 1.52642253332 19.4288379021 13.8579347649 第9個人:到達時間 開始時間 “工作”時間 完成時間 等待時間 5.15292640194 19.4288379021 2.8327295047 22.2615674068 14.2759115002 第10個人:到達時間 開始時間 “工作”時間 完成時間 等待時間 6.39798292569 22.2615674068 2.48704326285 24.7486106697 15.8635844811 第11個人:到達時間 開始時間 “工作”時間 完成時間 等待時間 6.46150544161 24.7486106697 2.75523182998 27.5038424996 18.287105228 第12個人:到達時間 開始時間 “工作”時間 完成時間 等待時間 6.83020450863 27.5038424996 2.82170691612 30.3255494157 20.673637991 第13個人:到達時間 開始時間 “工作”時間 完成時間 等待時間 7.54986448877 30.3255494157 1.32813398415 31.6536833999 22.775684927 第14個人:到達時間 開始時間 “工作”時間 完成時間 等待時間 7.74933683577 31.6536833999 2.01805818046 33.6717415804 23.9043465641 第15個人:到達時間 開始時間 “工作”時間 完成時間 等待時間 8.42722353547 33.6717415804 1.0300259968 34.7017675772 25.2445180449 第16個人:到達時間 開始時間 “工作”時間 完成時間 等待時間 8.76080737972 34.7017675772 1.69860652295 36.4003741001 25.9409601974 第17個人:到達時間 開始時間 “工作”時間 完成時間 等待時間 9.02778847556 36.4003741001 2.19029299704 38.5906670971 27.3725856245 第18個人:到達時間 開始時間 “工作”時間 完成時間 等待時間 9.0683463525 38.5906670971 1.74875934398 40.3394264411 29.5223207446 第19個人:到達時間 開始時間 “工作”時間 完成時間 等待時間 9.51437407844 40.3394264411 1.52156911323 41.8609955544 30.8250523627 arerage waiting time is 15.743466 ------