Sneak Preview: GIF of Life
As luck would have it, my day job will require me to teach a mini-class on writing computer simulations for scientific purposes next week, and one of the examples I thought I’d include turned out to be just the thing I needed to provide an illustration for the review of John Allen Paulos’ Irreligion (2007) I’ve got in the works. Since the details are a little beyond the scope of that review, I might as well make another post out of them.
First, the punchline:

This is a fifty-frame animation of Conway’s Game of Life which begins with a 32×32 grid of random values and successively advances by applying the transition rules of that famous automaton. The purpose of the exercise is twofold: first, to demonstrate some basic programming techniques and show how much you can do in Python with half an hour of free time; and second, to see how persistent and cyclic features arise from random configurations.
I chose to establish periodic boundary conditions, so that patterns leaving one side wrap around to the other (readers of my generation will recall the game Asteroids). This means we’re playing Life on a torus — is there anything donuts can’t do? As before, we’ll be using the Python language with a few extra modules for stuff like visual output.
Now, the code!
#!/usr/bin/python
# conway.py
# Blake Stacey
# (bstacey at alum.removethis.mit.andthis.edu)
import math, scipy, random, pylab
def iTest(x, p):
if(x <= p):
return 0
else:
return 1
fP = 0.5 # probability of dead square
iGridEdge = 32 # size of grid
iTrials = 50 # number of times to loop
random.seed()
imThis = scipy.array(scipy.rand(iGridEdge, iGridEdge))
imThat = scipy.array(scipy.zeros((iGridEdge, iGridEdge)))
for i in range(iGridEdge):
for j in range(iGridEdge):
imThis[i][j] = iTest(imThis[i][j], fP)
pylab.ion()
pylab.hold(False)
for t in range(iTrials):
for i in range(iGridEdge):
for j in range(iGridEdge):
# bounds checking
iPlus = (i + 1) % iGridEdge
iMinus = (i - 1) % iGridEdge
jPlus = (j + 1) % iGridEdge
jMinus = (j - 1) % iGridEdge
# count number of neighbors
iNext = (imThis[i][jPlus]
+ imThis[iPlus][j]
+ imThis[iMinus][j]
+ imThis[i][jMinus]
+ imThis[iPlus][jPlus]
+ imThis[iMinus][jMinus]
+ imThis[iPlus][jMinus]
+ imThis[iMinus][jPlus])
iCurrent = imThis[i][j]
# update rule
if(iCurrent == 0):
if(iNext == 3):
imThat[i][j] = 1
else:
imThat[i][j] = 0
else:
if(iNext <= 1):
imThat[i][j] = 0
elif(iNext > 3):
imThat[i][j] = 0
elif((iNext == 2) or (iNext == 3)):
imThat[i][j] = 1
# end loop over elements
# swap buffers
imOther = imThis
imThis = imThat
imThat = imOther
# print summary statistic and display image
print sum(sum(imThis)) / float((iGridEdge * iGridEdge))
pylab.imshow(imThis, cmap = pylab.cm.prism)
pylab.draw()
By sticking a pylab.savefig command after the pylab.imshow call, the images can be written to files:
pylab.imshow(imThis, cmap = pylab.cm.prism)
pylab.savefig("frame_" + str(t) + ".png")
pylab.draw()
There’s an awful lot of whitespace in the resulting images, and the quickest hack for, well, hacking it off is to use ImageMagick:
convert -crop 682x682+272+83 frame_0.png trimmed_0.png
I actually did all fifty frames with a bash loop:
for i in `seq 0 49`; do convert -crop 682x682+272+83
frame_$i.png $i.png; done
Noting that the images had more resolution than was really necessary, I sized them down:
for i in `seq 0 49`; do convert -resize 100x100 $i.png
resize_$i.png; done
Then I made the frames into an animated GIF, realized that they were out of order because the single-digit names were not prefixed with 0, fixed that problem, and made a new animation:
convert -delay 20 -loop 0 resize*.png animation.gif
The result was the image seen above. Here, I used a random initial configuration, because I had allotted myself half an hour to do the whole thing and I didn’t feel like specifying anything more detailed. However, you can put in a feature like a glider with code like this:
imThis = scipy.array(scipy.zeros((iGridEdge, iGridEdge)))
imThat = scipy.array(scipy.zeros((iGridEdge, iGridEdge)))
imThis[5][5] = 1
imThis[5][6] = 1
imThis[5][7] = 1
imThis[6][5] = 1
imThis[7][6] = 1
Lately, I’ve found myself growing tired of the usual creationist-bashing and snarky atheology which is the easiest type of science blogging to produce. Consequently, I plan to transition Sunclipse over to more math and physics posts, more “breakfast experiments” with programming and data mining, and more happy ramblings in the “bibliophilia” category.
![[sex and science]](http://www.sunclipse.org/downloads/sexandscience3.png)


This is great, it will be a lot more fun hacking around with this example than the usual boring examples I’d be using while getting to know Python better. Looking forward to more math and physics goodies too, thanks.
Paul Hutchinson said this on January 11th, 2008 at 21:23 pm
As before, a port (which, of course, has many spiritual siblings).
The algorithm said this on January 11th, 2008 at 21:27 pm
I’ve been meaning to tinker with some Python, as well as cellular automata. Thanks for the example of both.
Bronze Dog said this on January 11th, 2008 at 21:31 pm
Thank you, everyone, for the kind words, and for the Javascript port.
Blake Stacey said this on January 12th, 2008 at 00:15 am
You don’t mind I can borrow and modify this code for non specific initial configurations? I wanted to show some of friends various patterns like the beehives and oscillators, but was too lazy to sit and code it from scratch. Besides, I can use this as an opportunity to get familiar with python :)
Thanks for the lovely post.
anon1 said this on January 12th, 2008 at 01:30 am
Whoops, typo there. “non specific” should read “specific”
anon1 said this on January 12th, 2008 at 01:31 am
Sure, go ahead. Installation instructions for the various libraries used are here.
Blake Stacey said this on January 12th, 2008 at 01:56 am
Unfortunately, though Life is interesting, it’s been tainted by Wolfram’s grandiosity in my head.
I’m just thinking, though, in re Paul’s comments about the “usual boring examples”, if God built the universe as a giant cellular automaton, is there a “Hello World!” galaxy around somewhere?
John Armstrong said this on January 12th, 2008 at 16:31 pm
One reason to write about these things is to redeem them from the Wolfram experience, and make sure the general rubric of “complexity” is not just “that stuff Wolfram goes on about.”
;-)
Blake Stacey said this on January 12th, 2008 at 18:48 pm
I’ve been fascinated by the Game of Life ever since I was quite young; I don’t know why. It’s just incredible how such complex and unexpected behavior can arise from such simple rules. 32×32 cells is pretty puny, though. I wrote a LabVIEW GoL simulator as a programming exercise not long ago.
Eric Olson said this on January 12th, 2008 at 20:39 pm
Hey, you aren’t following PEP 8!
Reinis said this on January 26th, 2008 at 18:20 pm
Yeah, I import multiple modules on the same line, my tabs and spaces are all screwed up, and I never put enough kitten blood in my morning milkshake.
Blake Stacey said this on January 26th, 2008 at 18:58 pm