Random walks¶
Faisal Qureshi
faisal.qureshi@ontariotechu.ca
http://www.vclab.ca
Copyright information¶
© Faisal Qureshi
License¶
This work is licensed under a Creative Commons Attribution-NonCommercial 4.0 International License.In [1]:
import numpy as np
import random
import matplotlib.pyplot as plt
Location
class¶
In [2]:
class Location:
def __init__(self, loc):
self.loc = np.array(loc)
def move_by(self, l):
return Location(np.add(self.loc, l.loc))
def dist_from(self, o):
return np.sqrt(np.sum((self.loc - o.loc)**2))
def __str__(self):
return str(self.loc)
Testing Location
class¶
In [3]:
# Testing Location class
a = Location([0,1])
b = Location([2,4])
print ('Location a', a)
print ('Location b', b)
print ('Distance between a and b', a.dist_from(b))
print ('Move', a, 'by [3,4] gets us', a.move_by(Location([3,4])))
Location a [0 1] Location b [2 4] Distance between a and b 3.605551275463989 Move [0 1] by [3,4] gets us [3 5]
Field
class¶
In [15]:
class Field:
def __init__(self):
self.walkers = {}
# Must override this method to ensure that Field is properly resetted
def reset(self):
self.walkers = {}
def add(self, walker, loc):
"""
Add a walker at location loc
"""
if walker in self.walkers:
raise ValueError('Walker already present')
else:
self.walkers[walker] = loc
def move(self, walker):
"""
Updates walker's location by its step
"""
if not walker in self.walkers:
raise ValueError('Cannot find this walker')
cur_loc = self.walkers[walker]
step = walker.step()
new_loc = cur_loc.move_by(step)
self.walkers[walker] = new_loc
def get_loc(self, walker):
"""
Returns the location of this walker
"""
if not walker in self.walkers:
raise ValueError('Cannot find this walker')
return self.walkers[walker]
Walker
class¶
In [16]:
class Walker:
def __init__(self, name):
self.name = name
# Over-ride this function to create different Walkers.
def select_a_step(self, step_choices):
return random.choice(step_choices)
# Over-ride this function to create different Walkers
def step(self):
step_choices = [Location([0,1]), Location([0,-1]), Location([1,0]), Location([-1,0])]
return self.select_a_step(step_choices)
def __str__(self):
return self.name
walk
method¶
Simulates a single random walk
In [21]:
def walk(f, w, num_steps, show_locations=False):
"""
Returns distance from the staring location and the ending location
"""
start = f.get_loc(w) # Get walker's starting position
for s in range(num_steps): # Now move walker num_steps time
f.move(w)
if show_locations:
print(w.name, '(', s, ')', f.get_loc(w))
return start.dist_from(f.get_loc(w)), f.get_loc(w).loc # Compute distance between starting and ending location
In [22]:
random.seed(0)
f = Field()
w = Walker('zombie')
f.add(w, Location([0,0]))
print (walk(f, w, 10, False))
(2.0, array([-2, 0]))
simulate_walks
method¶
Simulating multiple runs of a fixed length random walk
In [49]:
def simulate_walks(num_steps, num_trials, start_loc, field, walker):
"""
Simulations a num_steps long random walk for num_trials times.
Returns distances and ending locations for each trial
"""
start = start_loc
distances = np.array([0.0])
ending_locations = start.loc
zombie = walker
f = field
for t in range(num_trials):
f.reset()
f.add(zombie, start)
d, e = walk(f, zombie, num_steps)
distances = np.vstack([distances, d])
ending_locations = np.vstack([ending_locations, e])
return distances, ending_locations
In [73]:
start_loc = Location([0,0])
num_steps = 1000
num_trials = 1000
d, e = simulate_walks(num_steps=num_steps, num_trials=num_trials, start_loc=start_loc, field=Field(), walker=Walker('zombie'))
In [74]:
print ('average distance', np.mean(d))
average distance 28.566847210576537
In [75]:
plt.figure(figsize=(4,4))
plt.scatter(e[1:,0],e[1:,1],alpha=0.1)
plt.axis('equal')
plt.xlabel('x')
plt.ylabel('y')
plt.title('Ending locations')
plt.show()
In [76]:
plt.figure(figsize=(4,4))
plt.hist(d[1:])
plt.ylabel('# Trials')
plt.xlabel('Distances')
plt.title('Distances')
plt.show()
In [39]:
class FieldWithTraps(Field):
def __init__(self, w, h, num_traps):
Field.__init__(self)
self.w = w
self.h = h
self.num_traps = num_traps
self.traps = []
for i in range(self.num_traps):
x = random.random()*self.w
y = random.random()*self.h
self.traps.append(Location([x,y]))
def reset(self):
Field.reset(self)
self.traps = []
for i in range(self.num_traps):
x = random.random()*self.w
y = random.random()*self.h
self.traps.append(Location([x,y]))
def move(self, walker):
if not walker in self.walkers:
raise ValueError('Cannot find this walker')
step = walker.step() # Notice that step is a delta Location
new_loc = self.walkers[walker].move_by(step)
for l in self.traps:
if np.all(l.loc == new_loc.loc):
x = random.random()*w
y = random.random()*h
self.walkers[walker] = Location([x,y])
return
self.walkers[walker] = new_loc
In [52]:
d, e = simulate_walks(num_steps=100, num_trials=100, start_loc=Location([0,0]), field=FieldWithTraps(30,30,300), walker=Walker('zombie'))
print ('average distance', np.mean(d))
--------------------------------------------------------------------------- NameError Traceback (most recent call last) Cell In[52], line 1 ----> 1 d, e = simulate_walks(num_steps=100, num_trials=100, start_loc=Location([0,0]), field=FieldWithTraps(30,30,300), walker=Walker('zombie')) 2 print ('average distance', np.mean(d)) NameError: name 'FieldWithTraps' is not defined
In [ ]:
plt.figure(figsize=(7,7))
plt.scatter(e[1:,0],e[1:,1])
plt.axis('equal')
plt.xlabel('x')
plt.ylabel('y')
plt.title('Ending locations')
plt.show()
plt.figure(figsize=(7,7))
plt.hist(d)
plt.ylabel('# Trials')
plt.xlabel('Distances')
plt.title('Distances')
plt.show()
In [42]:
class WalkerUp(Walker):
def __init__(self, name):
Walker.__init__(self, name)
def step(self):
step_choices = [Location([0,1.1]), Location([0,-.9]), Location([1,0]), Location([-1,0])]
return self.select_a_step(step_choices)
d, e = simulate_walks(num_steps=1000, num_trials=500, start_loc=Location([0,0]), field=Field(), walker=WalkerUp('baloon'))
print ('average distance', np.mean(d))
plt.figure(figsize=(7,7))
plt.scatter(e[1:,0],e[1:,1])
plt.axis('equal')
plt.xlabel('x')
plt.ylabel('y')
plt.xlim(-200,200)
plt.ylim(-200,200)
plt.title('Ending locations')
plt.show()
plt.figure(figsize=(7,7))
plt.hist(d)
plt.ylabel('# Trials')
plt.xlabel('Distances')
plt.title('Distances')
plt.show()
average distance 55.492779746593264
In [ ]: