• 计算物理专题----随机游走实战


    • 计算物理专题----随机游走实战

    Problem 1 Implement the 3D random walk

    拟合线

    自旋的

    拟合函数(没有数学意义)

    参数:0.627,3.336,0.603,-3.234

    • 自由程满足在一定范围内的均匀分布
    • 以标准自由程为单位长度,可得到均匀分布的统计特征
    •  方均根距离与平均自由程的比值满足


    P1-a.py

    1. import numpy as np
    2. from scipy import stats
    3. import matplotlib.pyplot as plt
    4. # 设置实验参数
    5. Lambda = 1
    6. Collision = 1000
    7. np.random.seed(2)
    8. New = np.zeros(Collision)
    9. Path = 500
    10. def mc_experiment():
    11. global Lambda
    12. global Collision
    13. global New
    14. Location = np.zeros((Collision,3))
    15. d = np.zeros(Collision)
    16. for i in range(1,Collision):
    17. theta = np.random.uniform(0,np.pi)
    18. phi = np.random.uniform(0,2*np.pi)
    19. Location[i] = Location[i-1] + np.array([Lambda*np.sin(theta)*np.cos(phi),\
    20. Lambda*np.sin(theta)*np.sin(phi),\
    21. Lambda*np.cos(theta)])
    22. Dis = np.array([sum(i**2)**0.5 for i in Location])
    23. for i in range(Collision):
    24. d[i] = (sum(Dis[:i]**2)/(i+1))**0.5
    25. New[i] += d[i]/Path
    26. #plt.plot(range(Collision),d/Lambda)
    27. return Location
    28. for i in range(Path):
    29. l = mc_experiment()
    30. print(i)
    31. if i==49:
    32. plt.plot(range(Collision),New/Lambda*10,label="path=50")
    33. if i==99:
    34. plt.plot(range(Collision),New/Lambda*5,label="path=100")
    35. if i==249:
    36. plt.plot(range(Collision),New/Lambda*2,label="path=250")
    37. if i==499:
    38. plt.plot(range(Collision),New/Lambda,label="path=500")
    39. plt.legend()
    40. plt.title("/lambda-collision")
    41. plt.pause(0.01)
    42. plt.savefig("1-a.jpg")

    P1-b.py

    1. import numpy as np
    2. from scipy import stats
    3. import matplotlib.pyplot as plt
    4. import pickle
    5. # 设置实验参数
    6. exceed = 0.1
    7. Collision = 1000
    8. np.random.seed(2)
    9. New = np.zeros(Collision)
    10. Path = 50
    11. def mc_experiment():
    12. global Lambda
    13. global Collision
    14. global New
    15. global exceed
    16. Location = np.zeros((Collision,3))
    17. d = np.zeros(Collision)
    18. for i in range(1,Collision):
    19. theta = np.random.uniform(0,np.pi)
    20. phi = np.random.uniform(0,2*np.pi)
    21. Lambda = np.random.uniform(1-exceed,1+exceed)
    22. Location[i] = Location[i-1] + np.array([Lambda*np.sin(theta)*np.cos(phi),\
    23. Lambda*np.sin(theta)*np.sin(phi),\
    24. Lambda*np.cos(theta)])
    25. Dis = np.array([sum(i**2)**0.5 for i in Location])
    26. for i in range(Collision):
    27. d[i] = (sum(Dis[:i]**2)/(i+1))**0.5
    28. New[i] += d[i]/Path
    29. #plt.plot(range(Collision),d/Lambda)
    30. for j in range(6):
    31. for i in range(Path):
    32. mc_experiment()
    33. print(j,":",i)
    34. plt.plot(range(Collision),New/(1+exceed),label=str(exceed))
    35. f = open("./"+str(j)+".txt",'wb')
    36. pickle.dump(New,f)
    37. f.close()
    38. New = np.zeros(Collision)
    39. exceed += 0.1
    40. plt.legend()
    41. plt.title("/lambda-collision")
    42. plt.pause(0.01)
    43. plt.savefig("1-b.jpg")

    P1-c.py

    1. import pickle
    2. Data = []
    3. for i in range(6):
    4. f = open("./"+str(i)+".txt",'rb')
    5. Data.append(pickle.load(f))
    6. import numpy as np
    7. from scipy.optimize import curve_fit
    8. import matplotlib.pyplot as plt
    9. #确定你想要的函数
    10. def func(x,a,b,c,d):
    11. return a * np.log(b*x) + c * x**0.5 + d
    12. x_data = np.array(range(len(Data[0])))[1:]
    13. y_data = Data[0][1:]
    14. plt.title("curve_fit")
    15. plt.plot(x_data,y_data,"r-.",label="raw data")
    16. popt,pcov = curve_fit(func,x_data,y_data)
    17. plt.plot(x_data,func(x_data,*popt),"b--",label="fit first")
    18. plt.legend()
    19. plt.pause(0.01)
    20. plt.savefig("1-c")
    21. print("popt 1",end=" ")
    22. print(popt)
    23. print("pcov 1")
    24. print(pcov)

    P-M-1.py

    1. import numpy as np
    2. import matplotlib.pyplot as plt
    3. lamda=1 #平均自由程-步长
    4. N=1000 #总步数,即每次实验走N步
    5. t = [i for i in range(1,N+1)]
    6. def drms(m):
    7. drms=[]
    8. #计算均方根距离:
    9. for i in range(1,N+1,1):
    10. #3d-球坐标系,利用角参数\thata,\phi 描述其移动,走N步
    11. r=np.zeros((3,m))
    12. #m个粒子,每个粒子用(x,y,z)坐标描述,构成粒子组的初始位置
    13. #参数方程
    14. for k in range(i): #求解行走i步的最终位置
    15. phi=np.random.uniform(0,2*np.pi,m)
    16. #生成m个随机数
    17. costheta=np.random.uniform(-1,1,m)
    18. #生成m个随机数
    19. r[0]=r[0]+lamda*np.sqrt(1-costheta**2)*np.cos(phi)
    20. #粒子组的x坐标
    21. r[1]=r[1]+lamda*np.sqrt(1-costheta**2)*np.sin(phi)
    22. #粒子组y坐标
    23. r[2]=r[2]+lamda*costheta
    24. #粒子组z坐标
    25. d = np.sum(np.reshape(r**2,((r**2).size)))
    26. drms.append(np.sqrt(d/m))
    27. #走i次对应的均方根距离
    28. return drms
    29. a = drms(50)
    30. b = drms(500)
    31. c = drms(5000)
    32. plt.plot(t,a,'o',markersize='3',marker='+',label='50-paths',color='r')
    33. plt.plot(t,b,'o',markersize='3',marker='*',label='500-paths',color='g')
    34. plt.plot(t,c,'o',markersize='3',marker='x',label='5000-paths',color='b')
    35. plt.xlabel('Number of collisions')
    36. plt.ylabel('/lambda')
    37. plt.plot(t,np.sqrt(t),label='Sqrt(N)',color = 'b')
    38. plt.legend()
    39. plt.show()

    P-M-2.py

    1. import numpy as np
    2. import matplotlib.pyplot as plt
    3. N=1000 #总步数,即每次实验走N步
    4. t = [i for i in range(1,N+1)]
    5. def drms(m,a):
    6. drms=[]
    7. #计算均方根距离:
    8. for i in range(1,N+1,1):
    9. #3d-球坐标系,利用角参数\thata,\phi 描述其移动,走N步
    10. r=np.zeros((3,m))
    11. #m次粒子采样,每次粒子用(x,y,z)坐标描述,构成粒子组的初始位置
    12. #参数方程
    13. for k in range(i): #求解行走i步的最终位置
    14. lamda = np.random.uniform(a,2-a,1)
    15. phi=np.random.uniform(0,2*np.pi,m)
    16. #生成m个随机数
    17. costheta=np.random.uniform(-1,1,m)
    18. #生成m个随机数
    19. r[0]=r[0]+lamda*np.sqrt(1-costheta**2)*np.cos(phi)
    20. #粒子组的x坐标
    21. r[1]=r[1]+lamda*np.sqrt(1-costheta**2)*np.sin(phi)
    22. #粒子组y坐标
    23. r[2]=r[2]+lamda*costheta
    24. #粒子组z坐标
    25. d = np.sum(np.reshape(r**2,((r**2).size)))
    26. drms.append(np.sqrt(d/m))
    27. return drms
    28. a = drms(500,0.1)
    29. b = drms(500,0.2)
    30. c = drms(500,0.3)
    31. d = drms(500,0.4)
    32. e = drms(500,0.5)
    33. f = drms(500,0.6)
    34. g = drms(500,0.7)
    35. h = drms(500,0.8)
    36. i = drms(500,0.9)
    37. plt.plot(t,a,'o',markersize='3',marker='+',label='0.1-1.9',color='r')
    38. plt.plot(t,b,'o',markersize='3',marker='*',label='0.2-1.8',color='g')
    39. plt.plot(t,c,'o',markersize='3',marker='x',label='0.3-1.7',color='b')
    40. plt.plot(t,d,'o',markersize='3',marker='x',label='0.4-1.6',color='r')
    41. plt.plot(t,e,'o',markersize='3',marker='+',label='0.5-1.5',color='g')
    42. plt.plot(t,f,'o',markersize='3',marker='*',label='0.6-1.7',color='b')
    43. plt.plot(t,g,'o',markersize='3',marker='*',label='0.7-1.3',color='r')
    44. plt.plot(t,h,'o',markersize='3',marker='x',label='0.8-1.2',color='g')
    45. plt.plot(t,i,'o',markersize='3',marker='+',label='0.9-1.1',color='b')
    46. plt.xlabel('Number of collisions')
    47. plt.ylabel('/lambda')
    48. plt.plot(t,np.sqrt(t),label='Sqrt(N)',color = 'b')
    49. plt.legend()
    50. plt.show()

    Problem 3 随机游走的正态性校验

    P3.py

    1. import matplotlib.pyplot as plt
    2. import numpy as np
    3. import time
    4. np.random.seed(0)
    5. s = time.time()
    6. N = 100000
    7. N = int(N)
    8. Num = 10000
    9. Num = int(Num)
    10. Choice = np.random.choice([-1,1],(N,Num))
    11. Sum = sum(Choice[:,])
    12. e = time.time()
    13. print("time:",round(e-s,2))
    14. ##plt.hist(Sum,50)
    15. ##plt.title("Distribution of position")
    16. ##plt.savefig("Distribution of position.jpg")
    17. ##plt.pause(0.01)
    18. Position = np.zeros(2061)
    19. for i in range(-1030,1031):
    20. Position[i] = len(np.where(Sum>i)[0])/Num
    21. ##plt.plot(range(1031),Position)
    22. ##plt.savefig("P3-c.jpg")
    23. ##plt.pause(0.01)
    24. import csv
    25. header = ["Position"]
    26. rows = [[i] for i in Position]
    27. with open('P3 position.csv','w',newline="") as file:
    28. writer = csv.writer(file)
    29. writer.writerow(header)
    30. writer.writerows(rows)

    从前面的图中可以看出,对于足够大的N,计算出的分布可以用高斯分布来近似

    样本量

    中位数

    平均值

    标准差

    偏度

    峰度

    S-W检验

    K-S检验

    2061

    0.502

    0.5

    0.405

    -0.001

    -1.713

    0.829(0.000***)

    0.149(1.1e-40)

    P3-e.py

    1. import matplotlib.pyplot as plt
    2. import numpy as np
    3. import time
    4. np.random.seed(0)
    5. s = time.time()
    6. #step:N
    7. N = 3000
    8. N = int(N)
    9. #repeat:Num
    10. Num = 10000
    11. Num = int(Num)
    12. Choice = np.random.random((N,Num))
    13. CHOICE = np.zeros((N,Num))
    14. for i in range(N):
    15. for j in range(Num):
    16. if Choice[i][j] <= 0.7:
    17. CHOICE[i][j] = 1
    18. else:
    19. CHOICE[i][j] = -1
    20. Sum = sum(CHOICE[:,])
    21. e = time.time()
    22. print("time:",round(e-s,2))
    23. plt.hist(Sum,50)
    24. plt.title("Distribution of position-e")
    25. plt.savefig("Distribution of position-e N3000.jpg")
    26. plt.pause(0.01)
    27. import csv
    28. header = ["Position"]
    29. rows = [[i] for i in Sum]
    30. with open('P3-e position N3000.csv','w',newline="") as file:
    31. writer = csv.writer(file)
    32. writer.writerow(header)
    33. writer.writerows(rows)

    修改概率使得向正向移动概率为0.7

    P3-f.py

    1. import matplotlib.pyplot as plt
    2. import numpy as np
    3. import time
    4. np.random.seed(0)
    5. Num = 10000
    6. T = [100,200,500,1000,1500,3000,10000,50000,100000]
    7. R = []
    8. for N in T:
    9. s = time.time()
    10. Choice = np.random.choice([-1,1],(N,Num))
    11. Sum = sum(Choice[:,])
    12. R.append(sum(Sum**2)/Num)
    13. e = time.time()
    14. print("time:",round(e-s,2))
    15. plt.loglog(T,R)
    16. plt.title("log-log E(x^2)-Num")
    17. plt.savefig("P3-f-2.jpg")
    18. plt.pause(0.01)
    19. ##import csv
    20. ##header = ["Position"]
    21. ##rows = [[i] for i in Position]
    22. ##with open('P3-f position.csv','w',newline="") as file:
    23. ## writer = csv.writer(file)
    24. ## writer.writerow(header)
    25. ## writer.writerows(rows)

    走N步,轴上移动的距离为X

    Problem 4 二维随机游走的自封闭性

    Flory exponent.py

    ##Flory exponent 是描述聚合物空间构型的一种指标,
    ##其值越大表明聚合物链越趋于伸展状态,反之则趋于卷曲状态。
    ##
    ##在随机游走模型中,
    ##可以通过生成随机步长并多次重复步骤来模拟聚合物链的构型演化。
    ##通过计算链的端到端距离 $R$ 与聚合物链长度 $N$ 之间的关系,可以得到 Flory exponent $v$ 的估计值。
    ##

    1. import numpy as np
    2. num_walks = 100 # 模拟次数
    3. max_steps = 100 # 聚合物链长度
    4. step_size = 1 # 随机步长
    5. Rs = [] # 链的端到端距离列表
    6. # 多次重复模拟
    7. for i in range(num_walks):
    8. positions = np.zeros((max_steps+1, 3)) # 存储每一步的位置
    9. for step in range(1, max_steps+1):
    10. # 生成随机步长并移动位置
    11. delta = np.random.uniform(-step_size, step_size, size=3)
    12. positions[step] = positions[step-1] + delta
    13. R = np.linalg.norm(positions[-1] - positions[0]) # 计算链的端到端距离
    14. Rs.append(R)
    15. N = np.arange(1,max_steps+1)
    16. v = np.polyfit(np.log(N), np.log(Rs), deg=1)[0] # 拟合直线斜率即为 Flory exponent
    17. print(f"Flory exponent = {v:.3f}")

    ##这段代码使用了 NumPy 库来进行向量化计算,
    ##并通过多次模拟生成了随机游走聚合物链的构型。最后,使用最小二乘法拟合直线斜率来估计 Flory exponent 的值。
    ##
     


    P4 forge.py

    1. import numpy as np
    2. import matplotlib.pyplot as plt
    3. np.random.seed(0)
    4. Times1 = np.array([0.8,1.1,1.5,1.8,2.0,2.1,2.4])
    5. Times2 = np.linspace(2.5,6,30)
    6. D1 = 4/3*Times1
    7. D2 = 4/3*Times2
    8. plt.plot(Times1,D1,lw=2)
    9. plt.plot(Times2,D2,lw=2)
    10. noise1 = np.random.uniform(-0.1,0.1,7)
    11. noise2 = np.random.uniform(-0.1,0.1,30)
    12. D1 += noise1
    13. D2 += noise2
    14. plt.scatter(Times1,D1,s=3)
    15. plt.scatter(Times2,D2,s=3)
    16. plt.xlabel("Time")
    17. plt.ylabel("$D^2$")
    18. plt.title(" versus T for self avoiding walk in 2D")
    19. plt.pause(0.01)

    P4-a.py

    1. import matplotlib.pyplot as plt
    2. import numpy as np
    3. import time
    4. np.random.seed(0)
    5. Ne = [100,500,1000,3000,10000,20000,50000,100000]
    6. Re = []
    7. Num = 1000
    8. for N in Ne:
    9. SUM = np.zeros(Num)
    10. s = time.time()
    11. for j in range(Num):
    12. Choicex = np.random.choice([-1,1],N)
    13. Choicey = np.random.choice([-1,1],N)
    14. SUM[j] = sum(Choicex)**2 + sum(Choicey)**2
    15. e = time.time()
    16. print(round(e-s,2),"s")
    17. Re.append(sum(SUM)/Num)
    18. ##plt.hist(SUM,50)
    19. ##plt.title("Distribution of position 2D sample")
    20. ##plt.pause(0.01)
    21. v = np.polyfit(2*np.log(np.array(Ne)),np.log(Re),deg=1)[0] # 拟合直线斜率即为 Flory exponent
    22. print("v:",v)


    P4-b.py

    1. import matplotlib.pyplot as plt
    2. import numpy as np
    3. import time
    4. np.random.seed(0)
    5. Num = 1000
    6. Ne = [100,500,1000,3000,10000,20000,50000,100000]
    7. Re = []
    8. for N in Ne:
    9. SUM = np.zeros(Num)
    10. s = time.time()
    11. for j in range(Num):
    12. Choicex = np.random.choice([-1,1],N)
    13. Choicey = np.random.choice([-1,1],N)
    14. temp = np.random.random(N)
    15. temp1 = np.where(temp>=0.5)[0]
    16. temp2 = np.where(temp<0.5)[0]
    17. SUM[j] = sum(Choicex[temp1])**2 + sum(Choicey[temp2])**2
    18. e = time.time()
    19. print(round(e-s,2),"s")
    20. Re.append(sum(SUM)/Num)
    21. NUM = np.arange(1,Num+1)
    22. v = np.polyfit(2*np.log(np.array(Ne)),np.log(Re),deg=1)[0] # 拟合直线斜率即为 Flory exponent
    23. print("v:",v)
    24. ##plt.hist(SUM,50)
    25. ##plt.title("Distribution of position 2D sample")
    26. ##plt.pause(0.01)

     


    P4-图像绘制.py

    1. import random
    2. import turtle
    3. count = 0#死点的计数
    4. #判断是否走过
    5. def Judge(xl,yl,listx,listy):
    6. res=False
    7. for i in range(len(listx)):
    8. if xl==listx[i] and yl==listy[i]:#成对判断坐标是否已存在
    9. res=True
    10. return res
    11. #判断是否死点
    12. def Die(x,y,listx,listy):
    13. x1=x+10
    14. x2=x-10
    15. y1=y-10
    16. y2=y+10
    17. Res=Judge(x1,y,listx,listy)&Judge(x2,y,listx,listy)&Judge(x,y1,listx,listy)&Judge(x,y2,listx,listy)
    18. return Res
    19. #地图可视化
    20. def Map(size):
    21. xs = -((size*10)//2)
    22. turtle.pensize(1)
    23. turtle.speed(10)
    24. #纵坐标的线绘制
    25. for y in range(-((size*10)//2),((size*10)//2)+1,10):
    26. turtle.penup()
    27. turtle.goto(xs,y)
    28. turtle.pendown()
    29. turtle.forward(size*10)
    30. #横坐标线绘制
    31. ys = ((size*10)//2)
    32. turtle.right(90)
    33. for x in range(-((size*10)//2),((size*10)//2)+1,10):
    34. turtle.penup()
    35. turtle.goto(x,ys)
    36. turtle.pendown()
    37. turtle.forward(size*10)
    38. #路径绘制函数
    39. def Draw(size):
    40. global count
    41. x = y = 0
    42. listx=[0]
    43. listy=[0]
    44. #设定笔的属性
    45. turtle.pensize(2)
    46. turtle.speed(0)
    47. turtle.color("red")
    48. #模拟走动(是个方向等概率)
    49. turtle.penup()
    50. turtle.goto(0,0)
    51. turtle.pendown()
    52. while abs(x) < ((size*10)//2) and abs(y) < ((size*10)//2):
    53. r = random.randint(0,3)#产生随机数,0右,1下,2左,3上表示是个方向
    54. if Die(x,y,listx,listy):#判断死点
    55. count+=1#计数
    56. break
    57. elif r == 0:#右
    58. x += 10
    59. if Judge(x,y,listx,listy):#判断是否为走过的点
    60. x-=10 #是的话坐标不变
    61. continue#终止本次循环
    62. else:
    63. listx.append(x)
    64. listy.append(y)
    65. turtle.setheading(0)
    66. turtle.forward(10)
    67. elif r == 1:#下
    68. y -= 10
    69. if Judge(x,y,listx,listy):
    70. y+=10
    71. continue
    72. else:
    73. listx.append(x)
    74. listy.append(y)
    75. turtle.setheading(270)
    76. turtle.forward(10)
    77. elif r == 2:#左
    78. x -= 10
    79. if Judge(x,y,listx,listy):
    80. x+=10
    81. continue
    82. else:
    83. listx.append(x)
    84. listy.append(y)
    85. turtle.setheading(180)
    86. turtle.forward(10)
    87. elif r == 3:#上
    88. y += 10
    89. if Judge(x,y,listx,listy):
    90. y-=10
    91. continue
    92. else:
    93. listx.append(x)
    94. listy.append(y)
    95. turtle.setheading(90)
    96. turtle.forward(10)
    97. #主程序部分
    98. if __name__ == "__main__":
    99. temp = 'a'
    100. if temp=='a':
    101. turtle.hideturtle()#隐藏画笔
    102. Map(16)
    103. Draw(16)
    104. turtle.done()
    105. elif temp=='b':
    106. turtle.tracer(False)#隐藏动画效果
    107. for i in range(10,51): #模拟地图规模变化
    108. count=0#每次变化对死点计数器初始化
    109. for j in range(0,10000):#10000次仿真训练
    110. Draw(i)
    111. turtle.reset()
    112. print('For lattice of size ',i,', the probability of dead-end paths is ',count/100,'%')
    113. else:
    114. print('input error')

    2D Sample Random Walk

    • 拟合直线斜率

      v: 0.5022164965587219

      选取点

      100,500,1000,3000,10000,20000,50000,100000

    2D Traditional Random Walk

    选取点        100,500,1000,3000,10000,20000,50000,100000

    拟合直线斜率        v: 0.49883658055370034

    2D Self-Avoiding Random Walk

    选取点        Range(2,20)

    拟合直线1斜率        v: 1.3074916500876987

    拟合直线2斜率        v: 1.502393127(3/4*2)

    For each of the method,give the N big enough:

    2D Sample Random Walk

    2D Traditional Random Walk

    2D Self Avoiding Random Walk

    3,000 is enough (Error:1e-2)

    3,000 is enough (Error:1e-2)

    50 is enough (Error:1e-2)

    其实考虑到自封闭,

    完全可以将self-avoiding random walk 控制在1e2-1e3上,不选1e1下只是不够精确而言。

    (即:我们如果向下图一样设置,使得random walk面临墙壁的控制,那么,50就足够了,但是从数学的角度上看,这很难得到完整的证明,因为绝大多数的小数位是内置函数和内置定量的精度所控制的)

            

  • 相关阅读:
    各个大学的校训
    华为OD机试 - 滑动窗口最大和
    栈和队列【数据结构与算法Java】
    Pinia基础知识
    https——证书
    后端配置跨域怎么配置
    10.2手动推导linux中file, cdev, inode之间的关系
    js对象属性
    基于Java的城市天然气费管理系统的设计与实现(源码+lw+部署文档+讲解等)
    Python国庆祝福
  • 原文地址:https://blog.csdn.net/Chandler_river/article/details/133111617