随机算法
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 ',arrivingtime,' ') #print('workingtime ',workingtime,' ') #print('startingtime ',startingtime,' ') #print('finishtime ',finishtime,' ') #print('waitingtime ',waitingtime,' ') #print('emptytime ',emptytime,' ') 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个人:到达时间 开始时间 “工作”时间 完成时间 等待时间 ' %i, arrivingtime[i], startingtime[i], workingtime[i], finishtime[i], waitingtime[i], ' ') 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 ------