问题:平面内一个物体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 pylab
import random
import math
def 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
return
result = []
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/python
import pylab
import random
import math
def 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 result
def performTrial(steps, tries):
distLists = []
for i in range(0, tries):
result = simulate(steps)
distLists.append(result)
return distLists
def 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()
return
if __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的结果图示,和以上数学分析结果一致。