Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

📚 The CoCalc Library - books, templates and other resources

132922 views
License: OTHER
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
import scipy.ndimage
12
13
import matplotlib
14
matplotlib.use('TkAgg')
15
import matplotlib.pyplot as pyplot
16
17
import fractal
18
19
20
def vfunc(con, rand, p=0.05, f=0.005):
21
"""Computes an update in the forest fire model.
22
23
con: an element from the convolution array
24
rand: an element from a random array
25
26
The output is 0 for an empty cell, 1 for a tree, and 10 for
27
a burning tree.
28
"""
29
# tree + neighbor on fire = burning
30
if con >= 110:
31
return 10
32
33
# no tree, check for a new tree
34
if con < 100:
35
if rand < p:
36
return 1
37
else:
38
return 0
39
40
# otherwise, tree + no neighbor on fire, check spark
41
if rand < f:
42
return 10
43
else:
44
return 1
45
46
update_func = numpy.vectorize(vfunc, [numpy.int8])
47
48
49
class Forest(object):
50
"""Implements the Bak-Chen-Tang forest fire model.
51
52
n: the number of rows and columns
53
"""
54
55
def __init__(self, n, mode='wrap'):
56
"""Attributes:
57
n: number of rows and columns
58
mode: how border conditions are handled
59
array: the numpy array that contains the data.
60
weights: the kernel used for convolution
61
"""
62
self.n = n
63
self.mode = mode
64
self.array = numpy.zeros((n, n), numpy.int8)
65
self.weights = numpy.array([[1,1,1],
66
[1,100,1],
67
[1,1,1]])
68
69
def get_array(self, start=0, end=None):
70
"""Gets a slice of columns from the CA, with slice indices
71
(start, end). Avoid copying if possible.
72
"""
73
if start==0 and end==None:
74
return self.array
75
else:
76
return self.array[:, start:end]
77
78
def loop(self, steps=1):
79
"""Executes the given number of time steps."""
80
[self.step() for i in xrange(steps)]
81
82
def step(self):
83
"""Executes one time step."""
84
con = scipy.ndimage.filters.convolve(self.array,
85
self.weights,
86
mode=self.mode)
87
rand = numpy.random.rand(self.n, self.n)
88
self.array = update_func(con, rand)
89
90
def count(self):
91
data = []
92
a = numpy.int8(self.array == 1)
93
for i in range(self.n):
94
total = numpy.sum(a[:i, :i])
95
data.append((i+1, total))
96
return zip(*data)
97
98
99
class ForestViewer(object):
100
"""Generates an animated view of the forest."""
101
def __init__(self, forest, cmap=matplotlib.cm.gray_r):
102
self.forest = forest
103
self.cmap = cmap
104
105
self.fig = pyplot.figure()
106
pyplot.axis([0, forest.n, 0, forest.n])
107
pyplot.xticks([])
108
pyplot.yticks([])
109
110
self.pcolor = None
111
self.update()
112
113
def update(self):
114
"""Updates the display with the state of the forest."""
115
if self.pcolor:
116
self.pcolor.remove()
117
118
a = self.forest.array
119
self.pcolor = pyplot.pcolor(a, vmax=10, cmap=self.cmap)
120
self.fig.canvas.draw()
121
122
def animate(self, steps=10):
123
"""Creates the GUI and then invokes animate_callback.
124
125
Generates an animation with the given number of steps.
126
"""
127
self.steps = steps
128
self.fig.canvas.manager.window.after(1000, self.animate_callback)
129
pyplot.show()
130
131
def animate_callback(self):
132
"""Runs the animation."""
133
for i in range(self.steps):
134
self.forest.step()
135
self.update()
136
137
138
def main(script, n=50, steps=50, *args):
139
140
n = int(n)
141
steps = int(steps)
142
143
forest = Forest(n)
144
145
for i in range(steps):
146
forest.step()
147
xs, ys = forest.count()
148
149
slope, inter = fractal.fit_loglog(xs, ys, n/4)
150
print i+1, slope
151
152
fractal.plot_loglog(xs, ys)
153
154
import CADrawer
155
drawer = CADrawer.EPSDrawer()
156
drawer.draw(forest)
157
drawer.save('forest.eps')
158
159
if __name__ == '__main__':
160
import sys
161
162
profile = False
163
if profile:
164
import cProfile
165
cProfile.run('main(*sys.argv)')
166
else:
167
main(*sys.argv)
168
169