In [ ]:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
%matplotlib inline
Randomization Parameters
k_1: $ \frac{1}{k_1} $ probability that a square with only one neighbour comes alive.
k_2: $ \frac{1}{k_2} $ probability that a square with two neighbours dies.
k_3: $ \frac{1}{k_3} $ probability that a square with three neighbour dies.
k_4: $ \frac{1}{k_4} $ probability that a square with four neighbours comes alive.
In [ ]:
k_1 = 1000
k_2 = 1000
k_3 = 1000
k_4 = 1000
Initial layout parameters
width: The width of the board in pixels (squares).
height: The height of the board in pixels (squares).
q: $ \frac{1}{q} $ probability that a square is initially alive.
In [ ]:
width = 1024
height = 512
q = 10
The initial state of the board
In [ ]:
Z = (np.random.randint(0,q,(height,width)) == 0).astype(int)
Plotting parameters
dpi: The dpi to use when rendering the plots
history: Display an average color for a square over the last history steps. A setting of one will display the usual game of life output, and higher values will show grey trails as things move around the board.
frames: The number of iteratiions (and hence frames) to create the animation of.
output_file: The place to save the file to. Note that this will be relative to the working directory of the ipython notebook instance that you are running.
In [ ]:
dpi = 72.0
history = 50
frames = 1000
output_file = "im.mp4"
The iteration step
Z: Should be a matrix of ones and zeros which represents the state of the board. The board will then be iterated and returned as a matrix of ones and zeros.
This function will add in the randomness according to the parameters listed above.
In [ ]:
def iterate(Z):
# Count neighbours
N = (Z[0:-2,0:-2] + Z[0:-2,1:-1] + Z[0:-2,2:] +
Z[1:-1,0:-2] + Z[1:-1,2:] +
Z[2: ,0:-2] + Z[2: ,1:-1] + Z[2: ,2:])
# Apply rules
birth = (N==3) & (Z[1:-1,1:-1]==0)
survive = ((N==2) | (N==3)) & (Z[1:-1,1:-1]==1)
# Add randomess
R_1 = (N==1) * (np.random.randint(0,k_1, np.array(Z.shape) - np.array([2,2])) == 0)
R_2 = (N==2) * (np.random.randint(0,k_2, np.array(Z.shape) - np.array([2,2])) == 0)
R_3 = (N==3) * (np.random.randint(0,k_3, np.array(Z.shape) - np.array([2,2])) == 0)
R_4 = (N==4) * (np.random.randint(0,k_4, np.array(Z.shape) - np.array([2,2])) == 0)
Z[...] = 0
Z[1:-1,1:-1][birth | survive] = 1
Z[1:-1,1:-1][R_1] = 1
Z[1:-1,1:-1][R_2] = 0
Z[1:-1,1:-1][R_3] = 0
Z[1:-1,1:-1][R_2] = 1
return Z
Plot iteration
This will iterate the plot. This function is passed to animation.FuncAnimation.
In [ ]:
ars = []
def iterate_plot(*args):
global Z
global ars
global history
Z = iterate(Z)
ars.append(Z.copy())
if len(ars) > history:
ars.pop(0)
im.set_array(sum(ars) / 50.)
return im
Produce the plot
In [ ]:
size = np.array(Z.shape)
figsize= size[1]/float(dpi),size[0]/float(dpi)
fig = plt.figure(figsize=figsize, dpi=dpi, facecolor="white")
fig.add_axes([0.0, 0.0, 1.0, 1.0], frameon=False)
plt.xticks([]), plt.yticks([])
im = plt.imshow(Z,interpolation='nearest', cmap=plt.cm.gray_r)
ani = animation.FuncAnimation(fig, iterate_plot, interval=50, frames=frames)
ani.save(output_file, codec="libx264")
plt.show()
In [ ]: