Jeg holder for tiden på med
The Emperor's New Mind, en nokså omfattende bok om fysikk og matematikk og livet og slikt, av Roger Penrose. Poenget hans er visstnok at det ikke er mulig å simulere en menneskelig bevissthet med en vanlig datamaskin, uansett hvor kraftig den måtte være, skjønt jeg har ikke kommet til den delen av boken ennå. På veien til denne konklusjonen er han imidlertid innom mye annet interessant som egentlig gjør boken verdt å lese i seg selv. En av tingene han streifer innom er
Mandelbrot-settet, og inspirert av det jeg leste bestemte jeg meg for å kikke litt nærmere på dette selv.
Jeg regner med alle har sett et bilde av Mandelbrot-settet, eller Mandelbrot-mannen som det gjerne også kalles, men det er kanskje ikke alle som vet hvordan man lager dette bildet. Selv har jeg lest om det ved et par anledninger tidligere, men det var ikke før jeg leste om det boken til Penrose jeg innså at det faktisk er ganske lettvint å programmere en utregning av dette settet.
Oppskriften går som følger: Begynn med et komplekst tall,
c. Dette tallet kaller vi
z0. Regn så ut et nytt tall,
z1 =
z02 +
c. Regn så ut enda et nytt tall,
z2 =
z12 +
c. Etc, etc. Rent formelt skal man gjøre dette uendelig mange ganger, men i praksis nøyer vi oss med ganske mange ganger, for eksempel 100. Så regner man ut absoluttverdien av det siste tallet, i dette eksempelet
z100. Hvis absoluttverdien er større enn 2 er
c ikke med i Mandelbrot-settet, og hvis absoluttverdien er mindre eller lik 2 er
c med i Mandelbrot-settet. Ved å følge denne prosedyren for 1280 x 800 punkter i det komplekse planet, og farge punktene svarte hvis de er med i settet, og hvite hvis ikke, genererte jeg denne figuren:
![](http://web.phys.ntnu.no/~nordam/131007/mandelbrot1_l.png)
Mandelbrot-settet (sånn omtrent).
Det som er så ekstremt funky med Mandelbrot-settet er naturligvis at man kan zoome inn så mye man vil, og stadig vil det dukke opp nye og spennende strukturer, og forsåvidt også gamle og spennende strukturer som gjentar seg. Bildet under er for eksempel laget ved å zoome inn på et lite område i det forrige bildet, og bildet under der igjen er laget ved å zoome inn enda mer. Og slik kan man holde på, i det uendelige.
![](http://web.phys.ntnu.no/~nordam/131007/mandelbrot2_l.png)
Look closer, som Jørgen sa.
![](http://web.phys.ntnu.no/~nordam/131007/mandelbrot3_l.png)
Look even closelier, som Jørgen også sa.
Jeg sa at koden for å lage disse bildene er relativt enkel, og jeg har laget et (forhåpentligvis) nokså grundig forklart python-script som gjør jobben. Jeg klipper og limer:
#!/usr/bin/env python
# Numpy has mathematical functions
import numpy as np
# Will use Python Imaging Library (PIL) to save picture
from PIL import Image
# Some parameters
pixels = (1000, 1000)
x_lims = (-2.0, 2.0)
y_lims = (-2.0, 2.0)
max_iter = 16
max_value = 2
def f(z, c):
# Function which does the iterations
# Takes z_{n} as input, returns z_{n+1}
return z**2 + c
def draw_picture(picture, filename):
# Save the image to file
im = Image.fromarray(picture, 'L')
im.save(filename)
def main():
# Setting up the area to calculate for
# Create two vectors, the number of points is given by
# the variable pixels, the points are equally spaced
# in the ranges given by x_lims and y_lims
x_range = np.linspace(x_lims[0], x_lims[1], pixels[0])
y_range = np.linspace(y_lims[0], y_lims[1], pixels[1])
# Create an array to hold the picture data
# The type uint8 is suitable for saving as an 8 bit
# black and white picture
picture = np.zeros(pixels, dtype = np.uint8)
# Loop over points in complex plane,
# constructed from x_range and y_range
for i in range(pixels[0]):
for j in range(pixels[1]):
# Create initial complex numbers
x = x_range[i]
y = y_range[j]
c = x + 1j * y
z = 0 + 0j
# Iterate until abs(z) > max_value
# or max number of iterations
for k in range(max_iter):
# Calculate new value of z from old value
z = f(z, c)
# Check the absolute value
if abs(z) > max_value:
# If the absolute value is greater than
# max_value, set the pixel to white and
# step out of the loop.
# All other pixels remain black.
picture[i, j] = 255
break
# Draw and save picture
draw_picture(picture, "mandelbrot.png")
if __name__ == '__main__':
main()
Dette programmet bruker litt under 20 sekunder på min laptop på å lage et bilde som minner om det første i denne artikkelen. Det er naturligvis mye kjappere enn i hine hårde dager, da de første bildene av Mandelbrot-settet ble laget, men i dag er det ingen som har tid til å vente på denslags. Som man kan se bruker programmet over for-løkker i Python til å loope over 1000 punkter i
x-retning og 1000 punkter
y-retning. Ved å skrive om dette til å bruke optimerte funksjoner fra Numpy kan vi få en ganske betydelig gevinst, og jeg har skrevet en litt modifisert versjon av det samme programmet, som gjør den samme jobben på ca 0.3 sekunder. Den som er interessert kan laste ned begge programmene her:
Comments