annotate 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
rev   line source
bgneal@40 1 """Chapter 6, exercise 1 in Allen Downey's Think Complexity book.
bgneal@40 2
bgneal@40 3 "Create a new class called CircularCA that extends CA so that the cells are
bgneal@40 4 arranged in a ring. Hint: you might find it useful to add a column of 'ghost
bgneal@40 5 cells' to the array."
bgneal@40 6
bgneal@40 7 """
bgneal@40 8
bgneal@40 9 import numpy
bgneal@40 10
bgneal@40 11 from CA import CA
bgneal@40 12
bgneal@40 13
bgneal@40 14 class CircularCA(CA):
bgneal@40 15 """A circular cellular automaton; the cells are arranged in a ring."""
bgneal@40 16
bgneal@40 17 def __init__(self, rule, n=100, ratio=2):
bgneal@40 18 """Parameters:
bgneal@40 19
bgneal@40 20 * rule: an integer in the range 0-255 that represents the CA rule
bgneal@40 21 using Wolfram's encoding
bgneal@40 22 * n: the number of rows (time steps) in the result
bgneal@40 23 * ratio: the ratio of columns to rows
bgneal@40 24
bgneal@40 25 """
bgneal@40 26 self.table = self.make_table(rule)
bgneal@40 27 self.n = n
bgneal@40 28 # a ghost column is added to either end
bgneal@40 29 self.m = ratio * n + 3 # add 2 ghost columns
bgneal@40 30 self.array = numpy.zeros((n, self.m), dtype=numpy.int8)
bgneal@40 31 self.next = 0
bgneal@40 32
bgneal@40 33 def start_single(self):
bgneal@40 34 self.array[0, 1] = 1
bgneal@40 35 self.next = 1
bgneal@40 36
bgneal@40 37 def step(self):
bgneal@40 38 """Executes one time step by computing the next row of the array."""
bgneal@40 39 i = self.next
bgneal@40 40 self.next += 1
bgneal@40 41 assert i > 0, 'call start_single() or start_random() first'
bgneal@40 42
bgneal@40 43 a = self.array
bgneal@40 44 t = self.table
bgneal@40 45
bgneal@40 46 # update the ghost cells to enable wrapping
bgneal@40 47 a[i - 1, 0] = a[i - 1, self.m - 2]
bgneal@40 48 a[i - 1, self.m - 1] = a[i - 1, 1]
bgneal@40 49
bgneal@40 50 for j in xrange(1, self.m - 1):
bgneal@40 51 a[i, j] = t[tuple(a[i - 1, j-1:j+2])]
bgneal@40 52
bgneal@40 53
bgneal@40 54 def get_array(self, start=0, end=None):
bgneal@40 55 """Gets a slice of columns from the CA, with slice indices
bgneal@40 56 (start, end).
bgneal@40 57
bgneal@40 58 """
bgneal@40 59 # do not return the ghost columns
bgneal@40 60 if end==None:
bgneal@40 61 return self.array[:, start+1:self.m-1]
bgneal@40 62 else:
bgneal@40 63 return self.array[:, start+1:end+1]
bgneal@40 64
bgneal@40 65
bgneal@40 66 if __name__ == '__main__':
bgneal@40 67
bgneal@40 68 import sys
bgneal@40 69 from CADrawer import PyplotDrawer
bgneal@40 70
bgneal@40 71 def main(script, rule, n):
bgneal@40 72 rule = int(rule)
bgneal@40 73 n = int(n)
bgneal@40 74 ca = CircularCA(rule, n)
bgneal@40 75 ca.start_single()
bgneal@40 76 ca.loop(n - 1)
bgneal@40 77
bgneal@40 78 drawer = PyplotDrawer()
bgneal@40 79 drawer.draw(ca)
bgneal@40 80 drawer.show()
bgneal@40 81
bgneal@40 82
bgneal@40 83 main(*sys.argv)