Mercurial > public > think_complexity
comparison CA.py @ 46:d83a72eec954
Forgot to add these. Needed for Chapter 6.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Thu, 25 Jul 2013 21:27:36 -0500 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
45:1804f09a7adb | 46:d83a72eec954 |
---|---|
1 """ Code example from Complexity and Computation, a book about | |
2 exploring complexity science with Python. Available free from | |
3 | |
4 http://greenteapress.com/complexity | |
5 | |
6 Copyright 2011 Allen B. Downey. | |
7 Distributed under the GNU General Public License at gnu.org/licenses/gpl.html. | |
8 """ | |
9 | |
10 import numpy | |
11 | |
12 class CA(object): | |
13 """A CA is a cellular automaton; the parameters for __init__ are: | |
14 | |
15 rule: an integer in the range 0-255 that represents the CA rule | |
16 using Wolfram's encoding. | |
17 n: the number of rows (timesteps) in the result. | |
18 ratio: the ratio of columns to rows. | |
19 """ | |
20 | |
21 def __init__(self, rule, n=100, ratio=2): | |
22 """Attributes: | |
23 table: rule dictionary that maps from triple to next state. | |
24 n, m: are the number of rows, columns. | |
25 array: the numpy array that contains the data. | |
26 next: the index of the next empty row. | |
27 """ | |
28 self.table = self.make_table(rule) | |
29 self.n = n | |
30 self.m = ratio*n + 1 | |
31 self.array = numpy.zeros((n, self.m), dtype=numpy.int8) | |
32 self.next = 0 | |
33 | |
34 def make_table(self, rule): | |
35 """Returns a table for the given CA rule. The table is a | |
36 dictionary that maps 3-tuples to binary values. | |
37 """ | |
38 table = {} | |
39 for i, bit in enumerate(binary(rule, 8)): | |
40 t = binary(7-i, 3) | |
41 table[t] = bit | |
42 return table | |
43 | |
44 def start_single(self): | |
45 """Starts with one cell in the middle of the top row.""" | |
46 self.array[0, self.m/2] = 1 | |
47 self.next += 1 | |
48 | |
49 def start_random(self): | |
50 """Start with random values in the top row.""" | |
51 self.array[0] = numpy.random.random([1,self.m]).round() | |
52 self.next += 1 | |
53 | |
54 def loop(self, steps=1): | |
55 """Executes the given number of time steps.""" | |
56 [self.step() for i in xrange(steps)] | |
57 | |
58 def step(self): | |
59 """Executes one time step by computing the next row of the array.""" | |
60 i = self.next | |
61 self.next += 1 | |
62 | |
63 a = self.array | |
64 t = self.table | |
65 for j in xrange(1,self.m-1): | |
66 a[i,j] = t[tuple(a[i-1, j-1:j+2])] | |
67 | |
68 def get_array(self, start=0, end=None): | |
69 """Gets a slice of columns from the CA, with slice indices | |
70 (start, end). Avoid copying if possible. | |
71 """ | |
72 if start==0 and end==None: | |
73 return self.array | |
74 else: | |
75 return self.array[:, start:end] | |
76 | |
77 | |
78 def binary(n, digits): | |
79 """Returns a tuple of (digits) integers representing the | |
80 integer (n) in binary. For example, binary(3,3) returns (0, 1, 1)""" | |
81 t = [] | |
82 for i in range(digits): | |
83 n, r = divmod(n, 2) | |
84 t.append(r) | |
85 | |
86 return tuple(reversed(t)) | |
87 | |
88 | |
89 def print_table(table): | |
90 """Prints the rule table in LaTeX format.""" | |
91 t = table.items() | |
92 t.sort(reverse=True) | |
93 | |
94 print '\\beforefig' | |
95 print '\\centerline{' | |
96 print '\\begin{tabular}{|c|c|c|c|c|c|c|c|c|}' | |
97 print '\\hline' | |
98 | |
99 res = ['prev'] | |
100 for k, v in t: | |
101 s = ''.join([str(x) for x in k]) | |
102 res.append(s) | |
103 print ' & '.join(res) + ' \\\\ \n\\hline' | |
104 | |
105 res = ['next'] | |
106 for k, v in t: | |
107 res.append(str(v)) | |
108 print ' & '.join(res) + ' \\\\ \n\\hline' | |
109 | |
110 print '\\end{tabular}}' | |
111 | |
112 |