醉漢隨機行走/隨機漫步問題(Random Walk Randomized Algorithm Python)


世界上有些問題看似是隨機的(stochastic),沒有規律可循,但很可能是人類還未發現和掌握這類事件的規律,所以說它們是隨機發生的。

 

隨機漫步(Random  Walk)是一種解決隨機問題的方法,它與人類生活息息相關,例如醉漢行走的軌跡、布朗運動(Brownian Motion)、股票的漲跌等都可以用它來模擬。隨機漫步已經應用到數學,物理,生物學,醫學,經濟等領域。

 

假設某地有一個醉漢,每一秒鍾會朝“東”,“南”,“西”,“北”中的一個方向走一步,那么這個醉漢在走了500步之后會在什么地方?1000步呢?是不是隨着時間的增長,醉漢離原點越來越遠呢?這個問題看似很隨機,無法解決,但是如果用電腦程序來模擬,那么就可以很容易地把醉漢行走的軌跡,醉漢離原點的距離展現出來。

 

解決思路:

設計四個class,分別是:Location(表示醉漢所在的位置),Direction(表示醉漢行走的方向,如果要增加或修改方向,在這個class中修改即可),Field(表示一個醉漢所在的平面區域,如果要增加醉漢的數量,在這個class中修改即可),Drunk(表示醉漢本身)

 

代碼如下:

import math, random, pylab

class Location:
    def __init__(self,x,y):  #定義醉漢的位置,即平面上的一點,用x和y坐標表示
        self.x=x
        self.y=y
    def move(self,xc,yc):  #輸入x和y坐標的變動值,返回變動后的坐標
        return Location(self.x+xc,self.y+yc)
    def getLocation(self):
        return self.x,self.y
    def getDistance(self,other):  #輸入另一個點的坐標,根據x軸和y軸變動的距離,算出原點和另一個點之間的直線距離
        ox,oy=other.getLocation()
        xDist=ox-self.x
        yDist=oy-self.y
        return math.sqrt(xDist**2+yDist**2)

class Direction:
    possibleDirection=("S","W","E","N")  #可能的四種方向
    def __init__(self,direc):  #定義方向,如果此方向不在可能的四種方向里面,那么報錯
        if direc in self.possibleDirection:
            self.direc=direc
        else:
            raise ValueError("in direction:__init__")
    def move(self,dist):  #輸入移動距離,根據不同的方向返回平面距離
        if self.direc=="S": return (0,-dist)
        if self.direc=="W": return (-dist,0)
        if self.direc=="E": return (dist,0)
        if self.direc=="N": return (0,dist)
        else: raise ValueError("in direction: move")

class Field:
    def __init__(self,drunk,loc):  #定義醉漢和其所在的平面
        self.drunk=drunk
        self.loc=loc
    def move(self,direc,dist):  #輸入方向和移動距離,獲得x和y坐標的變動值,在原點上移動該值,獲得變動后的坐標
        oldLoc=self.loc
        xc,yc=direc.move(dist)
        self.loc=oldLoc.move(xc,yc)
    def getLocation(self):
        return self.loc
    def getDrunk(self):
        return self.drunk

class Drunk:
    def __init__(self,name):
        self.name=name
    def move(self,field,step=1):
        if field.getDrunk()!=self:
            raise ValueError("No such drunk is found on the field")
        for i in range(step):
            direc=Direction(random.choice(Direction.possibleDirection))
            field.move(direc,1)

def performTrial(step,f):
    startLoc=f.getLocation()
    distances=[0]
    for t in range(1,step+1):
        f.getDrunk().move(f)
        newLoc=f.getLocation()
        distance=newLoc.getDistance(startLoc)
        distances.append(distance)
    return distances

drunk=Drunk("Baichi")
for i in range(3):
    f=Field(drunk,Location(0,0))
    distances=performTrial(500,f)
    pylab.plot(distances)
pylab.title("Baichi Walk")
pylab.xlabel("Time")
pylab.ylabel("Distance")
pylab.show()

 

運行結果如下:

 

可以看出,隨着時間的推移,醉漢離原點越來越遠。

 

人們通常想當然地以為醉漢隨機朝四種方向行走,來來回回,兜兜轉轉,估計最后還是走到離原點不遠的地方。但其實醉漢每走一步,之前的基點都會隨之變化。(走第一步時,100%的幾率會離原點更遠;走第二步時,75%的幾率會離原點更遠,只有25%的幾率會回到原點。這就是因為走第一步時,基點是原點,而走第二步時,基點變成了走完第一步后所在的點。)

 

在現實生活中,假如有一天你的股票大跌,這意味着你想要收回成本的可能性就很低了。因為基點已經被拉低。。。(啊啊啊啊。。。不要告訴我這個慘痛的事實啊!!!)

 

參考:麻省理工學院公開課:計算機科學及編程導論(第17集)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM