Random Walk Simulation (Python)

问题:平面内一个物体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的结果图示,和以上数学分析结果一致。

 

 

 

 

 

转载于:https://my.oschina.net/u/158589/blog/60821

原文链接:加载失败,请重新获取