-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathmandelbrot.py
259 lines (202 loc) · 8.79 KB
/
mandelbrot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
from numpy import *
import numpy as np
from time import time
from matplotlib import pyplot
import theano.tensor as T
from theano import function, config, shared
from sympy import expand_complex
from numexpr import evaluate
import numexpr as ne
def manelbrot(max_iter=20, res=1000, limits=[[-1.4, 1.4], [-2, 0.8]]):
y, x = ogrid[limits[0][0]:limits[0][1]:res*1j,
limits[1][0]:limits[1][1]:res*1j]
c = (x+y*1j).astype(np.complex64)
shape = c.real.shape
c_real_t = shared(c.real)
c_imag_t = shared(c.imag)
del c
del x
del y
#################################################################
z_real_t = shared(zeros(shape, dtype=np.float32))
z_imag_t = shared(zeros(shape, dtype=np.float32))
w_real = (z_real_t**2 - z_imag_t**2) + c_real_t
w_imag = (2.0*z_real_t*z_imag_t) + c_imag_t
mandel = function([], updates=[(z_real_t, w_real), (z_imag_t, w_imag)])
#################################################################
ww = ((z_real_t**2) + (z_imag_t**2))
diverge_t = shared(zeros(shape, dtype=np.float32))
conjug = function([], updates=[(diverge_t, ww)])
###############################################################
divtime_t = shared(max_iter + zeros(shape, dtype=np.int32))
i_t = shared(np.int32(0))
max_iter_t = shared(np.int32(max_iter))
www = (max_iter_t - i_t) * ((diverge_t > 4) & (divtime_t >= max_iter_t))
make_image = function([], updates=[(i_t, i_t + 1),
(divtime_t, divtime_t - www)])
for i in range(max_iter):
mandel()
conjug()
make_image()
print('iteration:\t%i' % (i+1))
return divtime_t.get_value()
def julia(c, func, max_iter=20, res=1000, limits=[[-1.4, 1.4], [-2, 0.8]]):
if type(func) is str:
func = expand_function(func)
y, x = ogrid[limits[0][0]:limits[0][1]:res*1j,
limits[1][0]:limits[1][1]:res*1j]
z = (x+y*1j).astype(np.complex64)
shape = z.real.shape
z_real_t = shared(z.real)
z_imag_t = shared(z.imag)
del z
del x
del y
#################################################################
c_real_t = shared(c[0] + zeros(shape, dtype=np.float32))
c_imag_t = shared(c[1] + zeros(shape, dtype=np.float32))
w_real = eval(func[0])
w_imag = eval(func[1])
mandel = function([], updates=[(z_real_t, T.cast(w_real, 'float32')), (z_imag_t, T.cast(w_imag, 'float32'))])
#################################################################
ww = ((z_real_t**2) + (z_imag_t**2))
diverge_t = shared(zeros(shape, dtype=np.float32))
conjug = function([], updates=[(diverge_t, ww)])
###############################################################
divtime_t = shared(max_iter + zeros(shape, dtype=np.int32))
i_t = shared(np.int32(0))
max_iter_t = shared(np.int32(max_iter))
www = (max_iter_t - i_t) * ((diverge_t > 4) & (divtime_t >= max_iter_t))
make_image = function([], updates=[(i_t, i_t + 1),
(divtime_t, divtime_t - www)])
for i in range(max_iter):
mandel()
conjug()
make_image()
print('iteration:\t%i' % (i+1))
return divtime_t.get_value()
def julia_raw(c, func, max_iter=20, res=1000, limits=[[-1.4, 1.4], [-2, 0.8]]):
y, x = ogrid[limits[0][0]:limits[0][1]:res*1j,
limits[1][0]:limits[1][1]:res*1j]
z = (x+y*1j).astype(np.complex64)
del x
del y
shape = z.shape
c = c * ones(shape, dtype=complex)
divtime = max_iter + zeros(shape, dtype=int)
for i in range(max_iter):
z = evaluate(func)
diverge = evaluate('z.real**2 + z.imag**2')
divtime[(diverge > 4) & (divtime==max_iter)] = i
print('iteration:\t%i' % (i+1))
return divtime
def get_quadrants(limits):
y_dif = (limits[0][1] - limits[0][0]) / 2.0
x_dif = (limits[1][1] - limits[1][0]) / 2.0
quadrants = [[[ limits[0][0] + y_dif, limits[0][1] ], [ limits[1][0] + x_dif, limits[1][1] ]],
[[ limits[0][0] + y_dif, limits[0][1] ], [ limits[1][0], limits[1][1] - x_dif ]],
[[ limits[0][0], limits[0][1] - y_dif ], [ limits[1][0], limits[1][1] - x_dif ]],
[[ limits[0][0], limits[0][1] - y_dif ], [ limits[1][0] + x_dif, limits[1][1] ]]]
return quadrants
def mandel_single(max_iter, res, limits, name='man'):
"""
Creates a single mandelbrot set picture with the given parameters
Arguments:
max_iter: Maximum amount of iterations to perform to generate image
res: Resolution of image in pixels
limits: x / y limits for generating image"""
t0 = time()
man = manelbrot(max_iter, res, limits)
t1 = time()
print('Done! Took %.2f seconds.' % (t1-t0))
pyplot.imsave('{}.png'.format(name), man)
def mandel_multi(max_iter, res, limits, base_name='mandel'):]
"""
Creates a 2x2 grid of mandelbrot set pictures
Arguments:
max_iter: Maximum amount of iterations to perform to generate image
res: Resolution of image in pixels, this resolution is applied to each section of the grid,
giving the combined picture a resolution of twice the res
limits: x / y limits for generating image of the combined image
base_name: base name of files generated"""
quadrants = get_quadrants(limits)
for key, quadrant in enumerate(quadrants):
t0 = time()
man = manelbrot(max_iter, res, quadrant)
t1 = time()
print('Done with quadrant %i! Took %.2f seconds.' % (key+1, t1-t0))
pyplot.imsave('%s_%i.png' % (base_name, key+1), man)
def julia_single(c, func, max_iter, res, limits, raw=False, name='julia'):
"""
Creates a single julia set picture with the given parameters
Arguments:
c: a constant complex number for which to base julia set ones
func: function for which to iterate over
max_iter: Maximum amount of iterations to perform to generate image
res: Resolution of image in pixels
limits: x / y limits for generating image
raw: bool: False: use optimized calculation routines, may fail for more compicated functions
True: Use basic calculation routines, slower but will work for almost any function
name: name of file to generate"""
t0 = time()
if raw:
man = julia_raw(complex(*c), func, max_iter, res, limits)
else:
try:
man = julia(c, func, max_iter, res, limits)
except:
print('Couldnt compile function, using raw calculation.')
man = julia_raw(complex(*c), func, max_iter, res, limits)
t1 = time()
print('Done! Took %.2f seconds.' % (t1-t0))
pyplot.imsave('{}.png'.format(name), man)
def julia_multi(c, func, max_iter, res, limits, raw=False, base_name='julia'):
"""
Creates a 2x2 grid of Julia set pictures
Arguments:
c: a constant complex number for which to base julia set ones
func: function for which to iterate over
max_iter: Maximum amount of iterations to perform to generate image
res: Resolution of image in pixels, this resolution is applied to each section of the grid,
giving the combined picture a resolution of twice the res
limits: x / y limits for generating image of the combined image
base_name: base name of files generated"""
quadrants = get_quadrants(limits)
for key, quadrant in enumerate(quadrants):
t0 = time()
if raw:
man = julia_raw(complex(*c), func, max_iter, res, limits)
else:
man = julia(c, func, max_iter, res, limits)
t1 = time()
print('Done with quadrant %i! Took %.2f seconds.' % (key+1, t1-t0))
pyplot.imsave('%s_%i.png' % (base_name, key+1), man)
def expand_function(func):
func = expand_complex(func).as_real_imag()
result = []
for part in func:
part = str(part)
part = part.replace('re(c)', 'c_real_t')
part = part.replace('im(c)', 'c_imag_t')
part = part.replace('re(z)', 'z_real_t')
part = part.replace('im(z)', 'z_imag_t')
part = part.replace('abs(', 'T.abs_(')
part = part.replace('exp(', 'T.exp(')
part = part.replace('inv(', 'T.inv(')
part = part.replace('sqr(', 'T.sqr(')
part = part.replace('sqrt(', 'T.sqrt(')
part = part.replace('cos(', 'T.cos(')
part = part.replace('sin(', 'T.sin(')
part = part.replace('cosh(', 'T.cosh(')
part = part.replace('sinh(', 'T.sinh(')
part = part.replace('log(', 'T.log(')
part = part.replace('arg(', 'T.angle(')
part = part.replace('I', '1j')
part = part.replace('im(', 'T.imag(')
part = part.replace('re(', 'T.real(')
result.append(part)
return result
def create_interval(center, radius):
x = center[0]
y = -center[1]
return [[y - radius, y + radius], [x - radius, x + radius]]