view 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 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, 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)