Lab 10 - FouadM0426/comp.physics-spring-2025 GitHub Wiki
In this final lab we will be working on random walking in multiple dimensions
- Random function This is an example of how the random function will work, using np.random.random we will be using the example of rolling a die. The data will be represented using a histography
import numpy as np
import matplotlib.pyplot as plt
def rolldie():
return np.random.randint(1,7)
print(rolldie())
rolls10 = [rolldie() for i in range(10)]
rolls100 = [rolldie() for i in range(100)]
rolls1000 = [rolldie() for i in range(1000)]
plt.subplot(1,3,1)
plt.hist(rolls10)
plt.title('10 rolls')
plt.subplot(1,3,2)
plt.hist(rolls100)
plt.title('100 rolls')
plt.subplot(1,3,3)
plt.hist(rolls1000)
plt.title('1000 rolls')
plt.show()
Random walking in 1 dimension, in our case the walker can only move by 1 length and the direction is either left or right we will be using the random function by creating a function that will allow the person to move to the left if the random generated number is less than .5, if it is greater he will move towards the right
def randomwalker(Nsteps=100, stepsize=1):
x = np.zeros(Nsteps)
for i in range(1,Nsteps):
if np.random.random() < 0.5:
x[i] = x[i-1] - stepsize
else:
x[i] = x[i-1] + stepsize
return x
print(randomwalker())
x1 = randomwalker()
x2 = randomwalker()
plt.plot(x1, 'bs', label='Walker 1')
plt.plot(x2, 'ro', label='Walker 2')
plt.xlabel('Step Number')
plt.ylabel('Position')
plt.legend()
plt.show()
For this next part we will be calculating the mean square distance for a large ensemble of walkers This will be accomplished by using a sample of 500, each walker will be taking 100 steps and will create a line of best fit to best show the x^2 plot
Nwalkers = 500
Nsteps = 100
# create an array xsq_sum to store 100 values of the x^2
xsq_sum = np.zeros(Nsteps)
# create a loop to call your function 500 times (or Nwalkers times)
for i in range(Nwalkers):
x = randomwalker(Nsteps)
# after each call, square the x values that are returned and add them to xsum
xsq_sum += x**2
# once the loop is over, divide xsum by the number of walkers to get xsq_ave
xsq_ave = xsq_sum / Nwalkers
print(xsq_ave)
plt.plot(xsq_ave, 'bs')
plt.xlabel('Step Number')
plt.ylabel('<x^2>')
plt.show()
# fit a polynomial to your data
pfit = np.polyfit(np.arange(Nsteps), xsq_ave, 1)
print(pfit)
# plot the best-fit polynomial with the data
plt.plot(np.arange(Nsteps), xsq_ave, 'bs', label='Data')
plt.plot(np.arange(Nsteps), np.polyval(pfit, np.arange(Nsteps)), 'r-', label='Best Fit')
2-D random walking, we will adding another dimension of thinking towards this portion now that the walker can move in random directions it will begin to complicate the code.
def randomwalker2d(Nsteps=100):
x = np.zeros(Nsteps)
y = np.zeros(Nsteps)
for i in range(1,Nsteps):
theta = np.random.random() * 2 * np.pi
x[i] = x[i-1] + np.cos(theta)
y[i] = y[i-1] + np.sin(theta)
return x, y
print(randomwalker2d())
x, y = randomwalker2d()
plt.plot(x, y, 'bs')
plt.xlabel('x')
plt.ylabel('y')
plt.title('random walker')
plt.show()
adding a line of best fit towards the plot
Nwalkers = 500
Nsteps = 100
rsq_sum = np.zeros(Nsteps)
for i in range(Nwalkers):
x, y = randomwalker2d(Nsteps)
rsq_sum += x**2 + y**2
rsq_ave = rsq_sum / Nwalkers
pfit = np.polyfit(np.arange(Nsteps), rsq_ave, 1)
print(pfit)
plt.plot(np.arange(Nsteps), rsq_ave, 'bs', label='Data')
plt.plot(np.arange(Nsteps), np.polyval(pfit, np.arange(Nsteps)), 'r-', label='Best Fit')
plt.xlabel
plt.ylabel('<r^2>')
plt.legend()
plt.show()
Brownian motion, we will be using this on the part 2 random walking code above to create an enclosed box with random walking will occur within
def brownianmotion(Nsteps=100, L=10):
x = np.zeros(Nsteps)
y = np.zeros(Nsteps)
x[0] = L/2
y[0] = L/2
i =1
while i < Nsteps:
random_direction = np.random.random() * 2 * np.pi
x[i] = x[i-1] + np.cos(random_direction)
y[i] = y[i-1] + np.sin(random_direction)
if x[i] < 0 or x[i] > L or y[i] < 0 or y[i] > L:
continue
i += 1
return x, y
print(brownianmotion())
x, y = brownianmotion()
plt.plot(x, y, 'bs')
plt.xlabel('x')
plt.ylabel('y')
plt.show()
x,y = brownianmotion(1000)
plt.plot(x, y, 'bs')
plt.xlabel('x')
plt.ylabel('y')
plt.show()
NOW we will animate the Brownian motion from the code above
from matplotlib.animation import FuncAnimation
from matplotlib import rc
# ANIMATION CODE
# number of steps of random walker
nsteps = 10
print(f"Our animation will have {nsteps} timesteps")
L = 10 # length of the box that the particle is in
# call your random walker function to get the
# x and y positions
# pass in the length of the box L and the number of steps nsteps
xrand, yrand = brownianmotion(nsteps,L)
fig = plt.figure()
# set the range of our axes to the size of the box
ax = plt.axes(xlim=(0, L), ylim=(0,L))
# We also need to create an empty point that we'll draw into each frame
# This looks weird but it's just a regular plot...with no data in it!
point, = ax.plot([], [], 'ro', markersize=20)
# We need an initialization function that empties the point at the start
# of the animation
#
# These initialization routines are fairly common in other programs and
# routines.
#
# Note that all this is doing is emptying out the data!
def init():
point.set_data([], [])
return point,
# Now we need an animate function that takes in the step number
# and sets the values for the points
def animate(i):
xpos = [xrand[i]]
ypos = [yrand[i]]
point.set_data(xpos, ypos)
return point,
# Note that the number of frames is the number of steps here, though it doesn't have to be
# interval is the time in milliseconds between frames
# blit is whether or not to *only* draw the new stuff, see what happens when it's False
anim_walker = FuncAnimation(fig, animate, init_func=init,
frames=nsteps, interval=100, blit=True)
# We need this so it doesn't draw an extra figure
plt.close()
rc('animation', html='jshtml')
anim_walker
Recording.2025-04-27.230810.mp4
adding a line to the animation above
from matplotlib.animation import FuncAnimation
from matplotlib import rc
# ANIMATION CODE
# number of steps of random walker
nsteps = 100
print(f"Our animation will have {nsteps} timesteps")
L = 10 # length of the box that the particle is in
# call your random walker function to get the
# x and y positions
# pass in the length of the box L and the number of steps nsteps
xrand, yrand = brownianmotion(nsteps,L)
fig = plt.figure()
# set the range of our axes to the size of the box
ax = plt.axes(xlim=(0, L), ylim=(0,L))
# We also need to create an empty point that we'll draw into each frame
# This looks weird but it's just a regular plot...with no data in it!
point, = ax.plot([], [], 'ro', markersize=20)
line, = ax.plot([], [], 'b-', linewidth=2)
# We need an initialization function that empties the point at the start
# of the animation
#
# These initialization routines are fairly common in other programs and
# routines.
#
# Note that all this is doing is emptying out the data!
def init():
point.set_data([], [])
line.set_data([], [])
return point, line
# Now we need an animate function that takes in the step number
# and sets the values for the points
def animate(i):
xpos = [xrand[i]]
ypos = [yrand[i]]
point.set_data(xpos, ypos)
# Update the line data with all points up to the current step
line.set_data(xrand[:i+1], yrand[:i+1]) # Plot the path as a line
return point,line
# Note that the number of frames is the number of steps here, though it doesn't have to be
# interval is the time in milliseconds between frames
# blit is whether or not to *only* draw the new stuff, see what happens when it's False
anim_walker = FuncAnimation(fig, animate, init_func=init,
frames=nsteps, interval=100, blit=True)
# We need this so it doesn't draw an extra figure
plt.close()
rc('animation', html='jshtml')
anim_walker