# Import modules
import numpy as np
import matplotlib.pyplot as plt
75 Random walk
A random walk, in the context of Brownian motion, refers to the erratic, unpredictable movement of particles suspended in a fluid, as they constantly collide with the much smaller molecules of the fluid in a manner that appears random and directionless. This concept, first observed by botanist Robert Brown in pollen grains floating in water.
The goal of this exercise is to write a Python script that simulates the random movement of a particle (e.g. a soil colloid in an aqueous suspension).
Solution using a for
loop
# Set random seed for reproducible results
1)
np.random.seed(
# Initialize list with particle position
= [0]
x = [0]
y
# Define number of particle steps
= 1000
N
# Iterate and track the particle over each step
for t in range(1,N):
# Generate random step (+1, 0, or -1)
= np.random.randint(-1,2)
x_step = np.random.randint(-1,2)
y_step
# Update position
= x[t-1] + x_step
x_new = y[t-1] + y_step
y_new
# Append new position
x.append(x_new) y.append(y_new)
# Plot random walk
=(5,5))
plt.figure(figsize=5, linestyle='-', marker='.', color='grey',zorder=0)
plt.plot(x, y, markersize0], y[0], marker='o', facecolor='green', label='Start',zorder=1)
plt.scatter(x[-1], y[-1], marker='^', facecolor='tomato', label='End', zorder=2)
plt.scatter(x['X coordinate')
plt.xlabel('Y coordinate')
plt.ylabel(
plt.legend() plt.show()
Solution without using a for
loop
# Set random seed for reproducibility
1)
np.random.seed(
# Number of particle steps
= 1000
N
= np.array([0])
x = np.array([0])
y
# Generate set of random steps
= np.random.randint(-1,2,N)
x_steps = np.random.randint(-1,2,N)
y_steps
# Cumulative sum (cumulative effect) of random choices
= np.concatenate((x, x_steps)).cumsum()
x = np.concatenate((y, y_steps)).cumsum() y
# Plot random walk
=(5,5))
plt.figure(figsize=5, linestyle='-', marker='.', color='grey',zorder=0)
plt.plot(x, y, markersize0], y[0], marker='o', facecolor='green', label='Start',zorder=1)
plt.scatter(x[-1], y[-1], marker='^', facecolor='tomato', label='End', zorder=2)
plt.scatter(x['X coordinate')
plt.xlabel('Y coordinate')
plt.ylabel(
plt.legend() plt.show()
Why are the two solutions different?
Setting the random seed using np.random.seed(1)
ensures that you get the same sequence of random numbers every time you run your code from the start, given that the sequence of random number generation calls is the same.
The key point is that the random number generator’s state progresses with each call, so the sequence of numbers you get depends on the number of times you’ve called the generator. The initial seed only sets the starting point of the sequence, but each call to generate a random number advances the state, leading to different subsequent numbers. That’s why the series of numbers generated in the loop and the array generated after the loop are different, despite both sequences being deterministic and reproducible when starting from the same seed.
Here is some code to visualize the difference in the generated steps:
1)
np.random.seed(= 10
N = []
loop_nums for n in range(N):
-1,2))
loop_nums.append(np.random.randint(
print(loop_nums)
print(np.random.randint(-1,2,N))
[0, -1, -1, 0, 0, -1, -1, 0, -1, 0]
[-1 1 0 1 -1 1 0 1 -1 -1]