问题:平面内一个物体Object的初始坐标(0,0),此后,每秒进行一个移动,每次移动1,方向是上下左右。即,newLocation = oldLocation + (x, y),其中(x,y) = (0,1) or (0, -1) or (1, 0) or (-1, 0)。那么,N秒后,Object离初始坐标的距离,会不会随着N的增加而增加?
分析:问题的本质是求N秒后的期望距离。这里有一点要注意,N秒后的期望距离和N秒后object最有可能出现的位置是两个该问题!搞清了这一点之后,我们就知道E(dist) = sigma(dist[i] * p[i]),其中dist[i]是离(0,0)的距离,p[i]是此距离的概率。由此,我们可以得到一个直观的概念,期望距离会随着N的增加而增加。(实际上,用数学的概率分布可以证明)
以下,用python来仿真这一过程,证明这一结论
代码
#!/usr/bin/python import pylabimport randomimport mathdef distance(location): return math.sqrt( location[0]**2 + location[1]**2 )def simulate(count): location = [0, 0] countLeft = 0 countRight = 0 countUp = 0 countDown = 0 for i in range(0, count): direction = random.choice(["left", "right", "up", "down"])# print "direction = ", direction if (direction == "left"): location[0] -= 1 countLeft += 1 if (direction == "right"): location[0] += 1 countRight += 1 if (direction == "up"): location[1] += 1 countUp += 1 if (direction == "down"): location[1] -= 1 countDown += 1# print "location = ", location dist = distance(location) result.append(dist) print countLeft, countRight, countDown, countUp returnresult = []simulate(10000)pylab.title('random walk simulation')pylab.xlabel('time/s')pylab.ylabel('distance/m')pylab.plot(result)pylab.show()
运行结果:
改进:
我们看到,一次试验只能给人一个直观映像,即,随着step的增加,与原点的距离也在增加。但是,一次试验的随机性比较高,这导致结果的振动幅度比较大,无法很好的看出dist和step的关系。如何改进这一点呢?
用取平均的方法来消除随机误差。这里,我们对500次试验取平均。
以下是改进后的试验结果:
以下是改进后的代码:
#!/usr/bin/pythonimport pylabimport randomimport mathdef distance(location): return math.sqrt( location[0]**2 + location[1]**2 )def simulate(count): location = [0, 0] countLeft = 0 countRight = 0 countUp = 0 countDown = 0 result = [] for i in range(0, count): direction = random.choice(["left", "right", "up", "down"])# print "direction = ", direction if (direction == "left"): location[0] -= 1 countLeft += 1 if (direction == "right"): location[0] += 1 countRight += 1 if (direction == "up"): location[1] += 1 countUp += 1 if (direction == "down"): location[1] -= 1 countDown += 1# print "location = ", location dist = distance(location) result.append(dist) return resultdef performTrial(steps, tries): distLists = [] for i in range(0, tries): result = simulate(steps) distLists.append(result) return distListsdef main(): steps = 3 tries = 500 distLists = performTrial(steps, tries) averageList = [0] for i in range(0, steps): total = 0 for j in range(0, tries): total += distLists[j][i] average = total/tries averageList.append(average)# print 'total=', total# print 'average=', average# print averageList pylab.plot(averageList) pylab.title('random walk simulation') pylab.xlabel('time/s') pylab.ylabel('distance/m') pylab.show() returnif __name__ == '__main__': main()
最后用简单的例子来证明正确性:
steps = 0 dist = 0
steps = 1 dist = 1
steps = 2 dist = (2+0+sqrt(2)+sqrt(2))/4 = 1.21
step3 = 3 dist = (3+1+sqrt(5)+sqrt(5)+...+...)/16 = 1.59
如下是steps=3, tries=500的结果图示,和以上数学分析结果一致。