
I recently got my copy of Stephan Wolfram's new book, 'A New Kind of Science' (2002) which focuses on complexity using computer expriments with cellular automata, ala the Game of Life (but the rules are often even simpler). The early part of the book focuses on grids populated according to simple rules, starting from a top row with just one black cell (the rest white) and working downward. Cells are considered in groups of 3, with the cell directly below the middle one turning white or black based on the mapping rule, i.e. based on how a given combination of 3 (white or black = 8 possibilities) gives a next generation cell in the next row. For example, rule 30 looks like this:
import nks p = nks.Pattern(30) p.sayrule() 111 --> 0 110 --> 0 101 --> 0 100 --> 1 011 --> 1 010 --> 1 001 --> 1 000 --> 0
The combinations on the left are fixed (always the same 8 in that order) whereas the string of 0s and 1s defines a unique binary number from 0 to 255. If I fill with 0s to 8 positions, and ask for 30 in binary, I get:
nks.base2(30,8) '00011110'
...which is the same rule as above. So if in the top row you had 20 whites plus a middle black:
p = nks.Pattern(30,width=20) p.gen '000000000010000000000'
Then successive rows would be:
p.next() '000000000111000000000'
and:
p.next() '000000001100100000000'
Complexity comes in with some rules (including 30) in a dramatic fashion, whereas other rules give terminal, static results, or an expanding fractal of nested, self-similar patterns (which we might consider complex, yet here the term is reserved for more unpredictable, more apparently random patterns). The beginning of the generation process of rule 30 is depicted here: http://www.inetarena.com/~pdx4d/ocn/graphics/nks30a.png and after a few more rows: http://www.inetarena.com/~pdx4d/ocn/graphics/nks30b.png and finally (to a lot more rows): http://www.inetarena.com/~pdx4d/ocn/graphics/nks30c.png This last picture is the default output of:
import nks p = nks.Pattern(30) p.run()
(I have the user then manually opening Povray to render nks30.pov -- an automated render invoked from within Python would be another option (but I like to tweak settings and re-render, so manual is better)). It turns out the Wolfram has been exploiting the randomness in this pattern to serve as a random number generator for Mathematica all this time (pg. 317). So, the pictures above come from using my usual Python + Povray combo. Another approach would be to populate pixels directly using PIL or some similar set of tools. But I wanted quick results through recycling existing code I've already written. Another side effect is we get little spheres in place of the flat squares used in Wolfram's book. That's OK. The patterns are what's important. I basically just use literal strings of 0s and 1s to generate the pictures. I don't keep a whole grid in memory -- each successive row overwrites the one before, so there's only the previous row and the next one to mess with at any given time. The Pattern object accepts any rule from 0 to 255 as input and the run() method creates the Povray file to 388 generations (the default). The first draft of my source code is at: http://www.inetarena.com/~pdx4d/ocn/python/nks.py Note dependencies on povray.py and coords.py -- both posted in the same subdirectory. And of course you need Povray, available from http://www.povray.org/ Kirby