As an exercise in programming Fortran 90, I wrote something to generate Buddhabrot pictures. Buddhabrot plots are related to the Mandelbrot set. Instead of just trying to display the Mandelbrot set itself, you track the “path” of the sequence
for various complex numbers , which are not in the Mandelbrot set. Wikipedia explains this process better:
The Buddhabrot is rendered by first creating a 2-dimensionalarray of counters, each counter corresponding to a final pixel of the image and initialized to zero. Then, a random sampling of c points are iterated through the Mandelbrot function. For points which do escape within a chosen maximum number of iterations, and therefore are not in the Mandelbrot set, their values are sent through the Mandelbrot function again and this time its path is plotted into the array. After a large number of c values have been iterated, grayscale shades are then chosen based on the values recorded in the array. The result is a density plot highlighting regions where z values spend the most time on their way to infinity. This could also be thought of as a probability distribution where the bright regions correspond to regions of high probability (of trajectories passing through the region) and the dark regions correspond to regions of low probability.
How to generate the Mandelbrot set
Really – don’t read this. Just look it up on Wikipedia or something.
Basically you start with some complex number . The first value is always set to zero. Using the formula above you calculate and from this , and so on. Note that this sequence of complex numbers depends on the “starting value” .
For some values of the absolutes of grow larger and larger. The points “escapes”. If this happens does not belong to the Mandelbrot set. However if the sequence of numbers doesn’t escape after infinite steps, the number does belong to the Mandelbrot set.
On a computer you can’t do infinite steps. One way to work around this is to check after every step if the absolute of the next number exceeds some threshold value. If – after a certain maximum number of steps – the absolutes are still smaller than the threshold value, we can say that the point is an element of the Mandelbrot set, at least with high probability. The larger you choose the threshold value and the maximum number of steps, the better the approximation to the Mandelbrot set.
To get those colorful images of the Mandelbrot set, you create a grid of starting points for for every pixel on the image and send them all through the sequence. Some of them will exceed the threshold value after a few iterations, others will take longer. Then we assign every pixel a colour based on how many iterations it took to exceed. If the points don’t escape at all for a certain maximum number of steps, they are considered part of the Mandelbrot set and get a different colour (black in the example above). Here is a nice gif, which shows how you get a better and more detailed approximation of the set by increasing the maximum number of iterations.
More interesting: Plotting Buddhabrot pictures
Now we know how to find out if a point belongs to the Mandelbrot set (at least approximatively). To plot a Buddhabrot we take some starting number and let it run through the Mandelbrot sequence. If it is not part of the set, we send it through the sequence again. Now we record the path the numbers take, as they wander through the complex plane. To record this path we set up a two-dimensional array, where each entry represents a point in the complex plane. At first every value of this array is set to zero. This array will give us our Buddhabrot image and we call this the “counter array”.
As the sequence wanders through the complex plane we record the path using the counter array. For each point (element) of the sequence, we add +1 to the respective entry in the counter array. Now take a lot (a LOT!) of different starting points and let them wander through the complex plane. In the end we can plot the array.
The picture you get depends on the maximum number of iterations you’ve chosen for the plot. Here are some examples:
These black and white plots were generated using gnuplot, but that it’s not important which software you choose (maybe code it yourself?). Just plot an image based on the counter array. Bright pixels correspond to high counts.
Needs moar colours!
We can make colourful plots using the Nebulabrot technique: Take three different (read: different maximum number of iterations) Buddhabrot plots and use them as red, green and blue channels of a picture. Using this technique I got this cool image:
To be honest I tweaked the colours a little bit, but the principle still applies: Exploit the fact that you can get very different Buddhabrot plots for various iteration numbers and mix these images to get pretty pictures.
Watching the Buddhabrot grow
I also created an animation that shows how the Buddhabrot “grows”. Each successive image is a Buddabrot plot with a higher maximum number of iterations than the previous image. Note the noise: This is because of the random sampling.
For each individual image I took a sample of 10,000,000 points.
Fortran 90 code
You can read the code of the program here: http://pasteit.com/17432
The program needs a function called ran2(seed) to generate random numbers in the interval . I used this one http://pasteit.com/17459 (I didn’t write it and I don’t know how it works).
This f90 program consists basically of four subroutines:
The subroutine createNewCounterArray(filename, fn_len) creates a new counter array (standard size is 1000×1000) and saves it to a file. filename is a String (Note: This is an array of characters. Fortran 90 does not come with a String object. That’s also the reason for the integer argument fn_len. You can’t read the length of an array, so you have to tell the subroutine how long the file name should be. If you want the file name to be ‘buddha.txt’ set the fn_len to 10.) You need to run this for a new plot.
loadCounterArray(filename, fn_len, out_c_array) loads the file created by the createNewCounterArray and writes it to the array out_c_array, which should be a 1000 by 1000 integer array.
saveCounterArray(filename, fn_len, in_c_array) saves a counter array to a file. in_c_array is a 1000 by 1000 integer array.
These three subroutines are used to save a plot and load it later. Buddhabrot plots take a lot of time, so I wanted to be able to save the progress somehow.
computePoints(max_points, max_iterations, counterArray) samples a certain number of points (max_points) and sends them through the Mandelbrot sequence using max_iterations. The progress is saved to the counterArray. Note: The threshold value for the sequence is hardcoded to 10. The rectangle in the complex plane from which the random points are chosen is also hardcoded.
Using these 4 subroutines I was able to create the plots above. The program itself creates the individual plots for the animated Buddhabrot using gnuplot. You can write Buddhabrot stuff using any language, but Fortran is cool because it’s fast and supports complex numbers. There is no need to write a complex number class first!