Mercurial > public > think_complexity
view CircularCA.py @ 42:039249efe42f
Chapter 6, exercise 2, #4. Wrote a program to output the center column of
a rule 30 CA as a stream of bytes. It is very slow though. It has to run a very
long time to produce enough data for dieharder. Committing it now but will have
to let it run overnight or something to generate a large file.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Sun, 13 Jan 2013 16:24:00 -0600 |
parents | ae310a2f42b4 |
children | 6cd37534c12e |
line wrap: on
line source
"""Chapter 6, exercise 1 in Allen Downey's Think Complexity book. "Create a new class called CircularCA that extends CA so that the cells are arranged in a ring. Hint: you might find it useful to add a column of 'ghost cells' to the array." """ import numpy from CA import CA class CircularCA(CA): """A circular cellular automaton; the cells are arranged in a ring.""" def __init__(self, rule, n=100, m=50): """Parameters: * rule: an integer in the range 0-255 that represents the CA rule using Wolfram's encoding * n: the number of rows (time steps) in the result * m: the number of columns """ self.table = self.make_table(rule) self.n = n # a ghost column is added to either end self.m = m + 2 # add 2 ghost columns self.array = numpy.zeros((n, self.m), dtype=numpy.int8) self.next = 0 def start_single(self): self.array[0, 1] = 1 self.next = 1 def step(self): """Executes one time step by computing the next row of the array.""" i = self.next self.next += 1 assert i > 0, 'call start_single() or start_random() first' a = self.array t = self.table # update the ghost cells to enable wrapping a[i - 1, 0] = a[i - 1, self.m - 2] a[i - 1, self.m - 1] = a[i - 1, 1] for j in xrange(1, self.m - 1): a[i, j] = t[tuple(a[i - 1, j-1:j+2])] def loop(self, steps=1): """Executes the given number of time steps.""" for i in xrange(steps): self.step() def get_array(self, start=0, end=None): """Gets a slice of columns from the CA, with slice indices (start, end). """ # do not return the ghost columns if end==None: return self.array[:, start+1:self.m-1] else: return self.array[:, start+1:end+1] def wrap(self): """Copies the last row to row 0, then resets the CA to start back at the top. """ a = self.array a[0, :] = a[self.next - 1, :] self.next = 1 if __name__ == '__main__': import sys from CADrawer import PyplotDrawer def main(script, rule, n, m): rule = int(rule) n = int(n) m = int(m) ca = CircularCA(rule, n, m) ca.start_single() ca.loop(n - 1) drawer = PyplotDrawer() drawer.draw(ca) drawer.show() main(*sys.argv)