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的增長而增長?python

分析:問題的本質是求N秒後的指望距離。這裏有一點要注意,N秒後的指望距離和N秒後object最有可能出現的位置是兩個該問題!搞清了這一點以後,咱們就知道E(dist) = sigma(dist[i] * p[i]),其中dist[i]是離(0,0)的距離,p[i]是此距離的機率。由此,咱們能夠獲得一個直觀的概念,指望距離會隨着N的增長而增長。(實際上,用數學的機率分佈能夠證實)app

如下,用python來仿真這一過程,證實這一結論dom

代碼spa

#!/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()

運行結果:code

 

 改進:orm

咱們看到,一次試驗只能給人一個直觀映像,即,隨着step的增長,與原點的距離也在增長。可是,一次試驗的隨機性比較高,這致使結果的振動幅度比較大,沒法很好的看出dist和step的關係。如何改進這一點呢?數學

用取平均的方法來消除隨機偏差。這裏,咱們對500次試驗取平均。it

如下是改進後的試驗結果:io

如下是改進後的代碼:form

#!/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的結果圖示,和以上數學分析結果一致。

相關文章
相關標籤/搜索