- Introduction
- Review of Complex Numbers
- Enter the Julia Set: Ordered Chaos
- The Mandelbrot Set: The Sum of All Julias
- Why Are These Functions Fractals?
- Mandelbrot and Julia Set Algorithms

[Top]

To help classify numbers, we often divide them up into *sets.* For example, there is the set of all numbers, which contains every number possible. A better example is the set of integers, which are all numbers which are whole and have no fractional parts (-2, -1, 0, 1, 2,...). The set of *real numbers* are all numbers that can be expressed by a rational fraction. This includes integers (2 = 2/1) as well as decimal values (0.75 = 3/4).

Just like your mother used to make you distinguish between your real and imaginary friends, there are also *imaginary numbers.* The most fundamental imaginary number is the square root of -1, which we will assign to the variable ** i.** The value if

Normally, real and imaginary numbers rarely meet. However, as calculus was invented and mathematicians began solving more and more complex math problems to find special values, strange things began to happen. Often, mathematicians would try to find the *roots* of an equation; that is, where one of the inputs equals 0. While solving more complex equations, they discovered that some roots did not fit in the set of real numbers. These roots often had both a real and imaginary part. It has since been found that many, many equations have such roots, and a special name has been assigned to such numbers. We call any number with both a real and imaginary part a *complex number.*

Complex numbers are often written in the form ** x + yi,** where

**Addition:***(a + bi) + (c + di) = (a + c) + (b + d)i***Multiplication:***(a + bi)(c + di) = ac + adi + bci + bdi*^{2}= (ac - bd) + (ad + bc)i

There is a special case of multiplication where we multiply a complex number by itself: in other words, we raise it to the power of 2. This gives us the following equation:

*(a + bi)*^{2}= (a + bi)(a + bi) = a^{2}+ abi + abi + (bi)^{2}= (a^{2}- b^{2}) + 2abi

We single this particular fact out because it is very important to the graphs of the Mandelbrot and Julia sets.

We can graph complex numbers easily to a plane (2-dimensional graph). To do this, we simply assign the ** x** value to an

- The values of
will increase without bound (go to infinity)*Z* - The values of
will collapse to 0 (zero)*Z* - The values of
will change, but will not fit in either of the above two categories*Z*

In the world of fractals, infinity and zero would be called *attractors,* because many points approach (are attracted to) these points. The values that fit in the first two categories are sometimes called the *Fatou set.* The values that fit in the third category are said to be in the *Julia set.* Points in the Fatou set tend to stick together; that is, points close to each other will follow similar paths, drawing closer to either infinity or zero. Points in the Julia set, however, are said to be *chaotic,* meaning that very small differences in points tend to show wildly different results.

So where do all those cool pictures come from?

Since we do not know from the start which points are in the Fatou set and which are in the Julia set, we must test each and every one. In reality, this is impossible, but we can approximate this with the help of computers. In essence, we tell the computer to create a graph where each pixel on the screen represents a point on the graph. How far each pixel is apart from its neighbors is a function of the resolution (size) of the graph and the boundaries we set for it. We then take each ** (x, y)** pair (which represents a complex number, remember) and use that as our

The wild colors produced in *MM!* depend on how "quickly" escaping values move toward infinity. For example, if you used the Grey Scale Palette, the lighter the color is, the more quickly it reaches infinity. (However, there are only 256 colors, and if the calculation goes beyond 256 iterations, the colors will cycle around and be reused. Try this with "The Wheel" preset view to see what I mean.) The very first color in any palette (such as black in the Grey Scale and Rainbow palettes) denotes values inside the Julia set.

As you can easily imagine, testing every single point in the plane can take quite a long time, especially if we create large images (high resolution) with large cut-off values (many iterations). In general, the higher the resolution and the higher the iteration count, the more detail we see, but it will also take much, much longer to complete.

[Top]

The Mandelbrot set is named after Benoit Mandelbrot (1924-), a brilliant Polish mathematician (and fellow IBMer). Mandelbrot, inspired by Julia's published works, was one of the first to apply computers to the study of Julia sets, and was the first to coin the term *fractal.* With the aid of his trusty computer, he began to explore Julia sets, and found (by accident) a very interesting relationship between them. As we discovered above, Julia sets are all points where the sequence of ** Z** values change, often drastically, but do not approach infinity nor zero. Points in the Julia set tend to drift to other such points, and their graphs may connect. Some Julia sets may consist of many disconnected points (called "dust sets"); others from larger "solid" areas that seem all connected; some form thin, wiggly lines that are all connected but do not outline any shapes ("dendritic" types).

Noting the different types of Julia sets, Mandelbrot set out to find some connection between them. Why were some dust sets, some solid, and some dendritic? In time, he discovered a very simple test to determine this value. By setting ** Z** to be the origin of the complex plane

Or is it? Curious about this new-found information, Mandelbrot decided to plot a graph of this new equation and colored the values depending on whether they were types (1), (2), or (3). Interestingly, he created a sort of "master" Julia set, a totally different fractal we know today as the *Mandelbrot set.*

If we zoom in on a portion of a Julia set, we will see the same detail repeated over and over on a smaller scale. Other than size, it does not change. However, because the Mandelbrot set is an amalgamation of all Julia sets, the detail changes drastically depending on where you zoom in. It is based on the precise location in which you are zooming, and is often similar in shape to the Julia sets derived from that area. The Mandelbrot set is *never* the same twice, and you can technically zoom forever (if it weren't for the limits of your computer's hardware).

[Top]

So why the Mandelbrot and Julia sets fractals? Technically, the sets themselves are not. However, the complex graphs created by graphing them in the complex plane are.

Unfortunately, the term *fractal* is extremely hard to define. The definition above is highly simplistic. Through some highly complex mathematics, we can prove that the Mandelbrot and Julia sets meet this definition, but I'll save you the headaches here. Why don't we look as some other definitions of fractals and compare what we know to them.

*The Divergent Measure definition: Any shape that has the unusual property that when you measure its length, area, surface area or volume in discrete units, the measured value varies exponentially with the size of the discrete unit.* We know this to be true by the very definition of the two sets. As we stated above, even minor changes in our starting values produce wildly different values of the result. Close examination of the graphs also reveals this with the bizarre patterns displayed.

*Hausdorff definition: Any geometric form whose Hausdorff dimension is greater than its topological dimension.* Hmmm... it might help to know what a Hausdorff dimension is. For a shape ** F** imbedded in

where ** N_{e}** is the minimum number of points in the space

Ouch! My eyes just hurt looking at that! Suffice it to say we won't calculate all that, but it has been found that the Mandelbrot set has a Hausdorff dimension of 2, which is greater than the topological (boundary) dimension, which is 1. This means the graph is indeed a fractal.

*The Natural definition: A geometric figure or natural object that combines the following characteristics: (a) its parts have the same form or structure as the whole, except that they are at a different scale and may be slightly deformed; (b) its form is extremely irregular or fragmented, and remains so, whatever the scale of examination; (c) it contains "distinct elements" whose scales are very varied and cover a large range.* This looks a little more within our grasp to prove. The first part is what we like to call *self-similarity,* which the Julia set demonstrates easily (no matter how far in we zoom, we see the same structures), but the Mandelbrot set is harder to see. However, on closer examination, we see the master Mandelbrot set repeated over and over leading us to believe that the first part is true. Part (b) is highly obvious for our sets, as is part (c).

Thus, we can prove our graphs are indeed fractals. If this quick gloss-over doesn't satisfy you, I strongly suggest a quick jaunt to the Web, where tons of sites can give you far better definitions than I.

[Top]

and*xmin, xmax, ymin,*are the boundaries of our current view. For simplicity's sake, in*ymax**MM!*we define that our viewing area must be square, therefore*xmax - xmin = ymax - ymin*is the resolution, or size, of our image in pixels. Since he have defined the image to be square, the*res*and*x*resolution will be the same.*y*is our color depth, or the number of colors available to us.*num_colors*is the number of iterations we allow before declaring a point to be in the set. If we escape the radius before this number is reached, we declare that the given point escapes to infinity.*iters*and*xgap*represent the distance between to pixels in the actual graph. The*ygap*value of point*x**p*will be_{n+1}more than the*xgap*value of point*x**p*The same follows for_{n}.values.*y*is the function that draws a pixel to the screen. It takes three arguments: an*setPixel()*value, a*x*value, and the color of the pixel. For us, we will use an indexed palette, where a positive integer between 0 and*y*will represent a given color.*num_colors*and*j*will be iterative values used to iterate through every point in the plane.*k*and*x, y, savex, savex2, savey, radius,*will be intermediate values used in the calculation.*count*

The algorithm:

xgap = (xmax - xmin) / res ygap = (ymax - ymin) / res for j = 0 to (res - 1) for k = 0 to (res - 1) x = xmin + j * xgap y = ymin + k * ygap savex = x savey = y radius = 0.0 count = 0 while (radius < 5.0) and (count < iters) savex2 = x x = x * x - y * y + savex y = 2.0 * savex2 * y + savey radius = x * x + y * y count = count + 1 endwhile if radius >= 5.0 setPixel(j, res - k, count mod num_colors) else setPixel(j, res - k, 0) endif endfor endfor

Notes:

- Note that in the
function calls, the*setPixel()*component*y*is subtracted from*k*This means we draw the graph from the bottom up (really!).*res.* - For Julia sets, instead of setting
and*savex*to the*savey*and*x*starting values, set them to the*y*and*x*parts of the constant*y*for the Julia set you wish to create (remember,*C*)*C = (x + yi)* - The escape
value is hard-coded here to 5. Why? Because it has been proven that the origin stays bounded if and only if its image always stays within a distance of 2 from the origin. This gives us a circular boundary with a radius of*radius*= 2*x*^{2}+ y^{2}^{2}= 4 < 5. (A little extra for added measure.) Officially, thevalue can be changed in the MandelObject class if you reference it outside of*radius**MM!,*but you should only make it higher.*MM!*has always hard-coded it to 5. - Can you see where the multiplication and addition of complex numbers comes in? If not, consider the following equations:
*Z*^{2}+ C = (z_{1}+ z_{2}i)^{2}+ (c_{1}+ c_{2}i)*= ((z*_{1}^{2}- z_{2}^{2}) + 2z_{1}z_{2}i) + (c_{1}+ c_{2}i)*= ((z*_{1}^{2}- z_{2}^{2}) + c_{1}) + (2z_{1}z_{2}+ c_{2})iRemember that

and*x*in the above algorithm corresponds to*y**(x + yi) = Z.* is used to hold the old value of*savex2*so we do not lose it after we recalculate*x**x.*- Note that
and*j, k, res, iters, num_colors,*are all integers, while all other variables should be floating point numbers, preferably double-precision. If you wish to use a language such as C++ or Java with this algorithm, you should explicitly cast these variables where appropriate.*count*

[Top]

© Copyright 2007, Jeffrey T. Darlington. All rights reserved.