changeset 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 49db586c727a
children d4d9650afe1e
files CircularCA.py
diffstat 1 files changed, 83 insertions(+), 0 deletions(-) [+]
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)