记录一下做的小课题
关于一维,二维,单粒子,多粒子的布朗运动模拟以及图像绘制
因为是随机游走,作图的时候要注意画布(坐标轴)大小要根据随机的最大值倍数设计,要不然会和难看(过大或过小)
在做多粒子模拟(模块4)的时候遇到了一点麻烦,找不到显示距离的文本迭代的办法,要么根本不变,要么每次叠加,糊成一团,最后用了x轴label,这个自带update的函数,用起来真是十分省心。还有就是批量实例化也调整了很久,最终plt生成图像的那一段应该可以适当优化。
作图汉字乱码依旧要用两行代码解决:
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
最终代码:
#类模块
import numpy as np
import matplotlib.pyplot as plt
class Brownian():
def __init__(self,x0=0):
assert (type(x0)==float or type(x0)==int or x0 is None)
self.x0 = float(x0)
def gen_random_walk(self,n_step=100):
if n_step < 30:
print("数据太少了!")
w = np.ones(n_step)*self.x0
for i in range(1,n_step):
yi = np.random.choice([1,-1])
# Weiner process
w[i] = w[i-1]+(yi/np.sqrt(n_step))
return w
def gen_normal(self,n_step=100):
if n_step < 30:
print("WARNING! The number of steps is small. It may not generate a good stochastic process sequence!")
w = np.ones(n_step)*self.x0
for i in range(1,n_step):
# Sampling from the Normal distribution
yi = np.random.normal()
# Weiner process
w[i] = w[i-1]+(yi/np.sqrt(n_step))
return w
#可执行模块1:一维随机游走
import matplotlib.pyplot as plt
from Brown import Brownian
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
b = Brownian()
branch = 50
nstep = 5000
for i in range(branch):
plt.plot(b.gen_random_walk(nstep),linewidth = 0.5)
pass
plt.title('一维随机游走 '+ str(branch)+'条轨迹 '+str(nstep)+'步')
plt.savefig('一维随机游走50轨迹.png')
plt.show()
#可执行模块2:单粒子等步长随机游走
import random
import matplotlib.animation as animation
import matplotlib.pyplot as plt
import numpy as np
import math
from Brown import Brownian
def init():
xmax, xmin, ymax, ymin = x.max(), x.min(), y.max(), y.min()
scale_factor = 1.15
xmax, xmin, ymax, ymin = xmax * scale_factor, xmin * scale_factor, ymax * scale_factor, ymin * scale_factor
mmax = max(xmax,ymax)
mmin = min(xmin,ymin)
plt.xlim(mmin, mmax)
plt.ylim(mmin, mmax)
# plt.xlim(xmin, xmax)
# plt.ylim(ymin, ymax)
pass
def update(frames):
xdata.append(x[frames])
ydata.append(y[frames])
line.set_data(xdata,ydata)
return line,
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
fig, ax = plt.subplots()
xdata = []
ydata = []
line, = plt.plot(xdata,ydata,marker='.',markersize=5,linewidth=0.7,color = 'red')
# 随机游走(二维)
nstep = 100
steplength = 0.5
chalist = []
b1 = Brownian()
b2 = Brownian()
x = b1.gen_normal(nstep)
# 通过等步长构建y
y = [0]*nstep
for i in range(nstep-1):
chalist.append((x[i+1] - x[i])**2)
pass
steplength = math.sqrt(max(chalist)+min(chalist))
for i in range(nstep-1):
m = steplength**2-(x[i+1] - x[i])**2
chazhi = math.sqrt(m)
y[i+1] = y[i] + random.choice([chazhi,chazhi*(-1)])
pass
y = np.array(y)
ani = animation.FuncAnimation(
fig,
update,
frames = nstep,
init_func=init
)
plt.title('随机游走(二维等步长) '+ str(nstep) + '步')
ani.save('二维随机游走(等步长).gif')
plt.show()
#可执行模块3:单粒子随机游走
import matplotlib.animation as animation
import matplotlib.pyplot as plt
from Brown import Brownian
def init():
xmax, xmin, ymax, ymin = x.max(), x.min(), y.max(), y.min()
scale_factor = 1.25
xmax, xmin, ymax, ymin = xmax * scale_factor, xmin * scale_factor, ymax * scale_factor, ymin * scale_factor
plt.xlim(xmin, xmax)
plt.ylim(ymin, ymax)
pass
def update(frames):
xdata.append(x[frames])
ydata.append(y[frames])
line.set_data(xdata,ydata)
return line,
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
fig, ax = plt.subplots()
xdata = []
ydata = []
line, = plt.plot(xdata,ydata,marker='.',markersize=5,linewidth=0.7)
# 随机游走(二维)
nstep = 30
b1 = Brownian()
b2 = Brownian()
x = b1.gen_normal(nstep)
y = b2.gen_normal(nstep)
ani = animation.FuncAnimation(
fig,
update,
frames = nstep,
init_func=init
)
plt.title('随机游走(二维) '+ str(nstep) + '步')
ani.save('二维随机游走.gif')
plt.show()
#可执行模块4:10粒子随机游走
import matplotlib.animation as animation
import matplotlib.pyplot as plt
import numpy as np
from Brown import Brownian
def init():
global xmin,ymin
xmax, xmin, ymax, ymin = 0,0,0,0
for i in x:
if xmax < max(i):
xmax = max(i)
if xmin > min(i):
xmin = min(i)
pass
for i in y:
if ymax < max(i):
ymax = max(i)
if ymin > min(i):
ymin = min(i)
pass
scale_factor = 1.10
xmax, xmin, ymax, ymin = xmax * scale_factor, xmin * scale_factor, ymax * scale_factor, ymin * scale_factor
plt.xlim(xmin, xmax)
plt.ylim(ymin, ymax)
pass
def update(frames):
global dis
for i in range(branch):
datax[i].append(x[i][frames])
datay[i].append(y[i][frames])
dis = np.sqrt(datax[i][frames] ** 2 + datay[i][frames] ** 2) + dis
line[i].set_data(datax[i], datay[i])
pass
text1 =str('距原点平均值:' + str(round(float(dis)/10,4)))
ax.set_xlabel(text1,fontsize=18)
dis = 0
return line
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
fig, ax = plt.subplots(figsize = (15,15))
nstep = 50
branch = 10
dis = 0
xmin = 0
ymin = 0
datax = list(range(branch))
datay = list(range(branch))
# 构建一系列空列表,datax,datay的每个元素都是一个空列表
# datax,datay用来迭代数据(append)
for i in range(branch):
datax[i] = []
datay[i] = []
pass
# 储存实例
ex = list(range(branch))
ey = list(range(branch))
for i in range(branch):
ex[i] = Brownian()
ey[i] = Brownian()
pass
# 储存遍历数据
x,y = [],[]
# 批量实例化,对每个粒子的x(y)坐标进行赋值 x(y)列表每个元素为一串随机数组
for i in range(branch):
x.append(list(ex[i].gen_normal(nstep)))
y.append(list(ey[i].gen_normal(nstep)))
pass
# 创建图像
line = ln = plt.plot([], [],
[], [],
[], [],
[], [],
[], [],
[], [],
[], [],
[], [],
[], [],
[], [],
marker='.',markersize=5,linewidth=0.7)
plt.title('随机游走(二维) '+ str(nstep) + '步'+str(branch) + '粒子',fontsize=18)
ani = animation.FuncAnimation(
fig,
update,
frames = nstep,
init_func=init
)
ani.save('二维随机游走(多粒子).gif')
plt.show()
#可执行模块5:粒子落点正态分布
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
def init():
xmax, xmin, ymax, ymin = x.max(), x.min(), y.max(), y.min()
scale_factor = 1.15
xmax, xmin, ymax, ymin = xmax * scale_factor, xmin * scale_factor, ymax * scale_factor, ymin * scale_factor
plt.xlim(xmin, xmax)
plt.ylim(ymin, ymax)
pass
def update(frames):
xdata = x[frames]
ydata = y[frames]
plt.plot(xdata,ydata,'bo',markersize=3.)
pass
# 散点数
n = 500
x,y = np.random.randn(2,n)
fig, ax = plt.subplots()
xdata = []
ydata = []
ani = animation.FuncAnimation(
fig,
update,
frames = n,
init_func=init,
interval = 15
)
ani.save('散点正态分布.gif')