Mercurial > public > think_complexity
diff CircularCA.py @ 40:ae310a2f42b4
Create a circular cellular automaton for ch 6, exercise 1.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Sat, 12 Jan 2013 15:03:31 -0600 |
parents | |
children | 039249efe42f |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CircularCA.py Sat Jan 12 15:03:31 2013 -0600 @@ -0,0 +1,83 @@ +"""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, ratio=2): + """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 + * ratio: the ratio of columns to rows + + """ + self.table = self.make_table(rule) + self.n = n + # a ghost column is added to either end + self.m = ratio * n + 3 # 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 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] + + +if __name__ == '__main__': + + import sys + from CADrawer import PyplotDrawer + + def main(script, rule, n): + rule = int(rule) + n = int(n) + ca = CircularCA(rule, n) + ca.start_single() + ca.loop(n - 1) + + drawer = PyplotDrawer() + drawer.draw(ca) + drawer.show() + + + main(*sys.argv)