Tripping over Mandelbrot sets

While at work, I came across my colleague implementing a graphics library and drawing amazing patterns on his display. Now, creating shapes using graphics library is pretty mainstream, however, this seemed too convoluted for a shape to be readily included in a graphics library. Naturally, I was overcome by curiosity and asked him,

“What sorcery is this?” 

just to get two words for an answer: Mandelbrot Set.

I was perplexed and performed a quick search on the topic. I was awestruck by the result. Here is a link to the same.

This seemed like a great opportunity to explore Mandelbrot sets using Python, making it my first blog article on Python as I get to hit two birds with a single stone.

Introduction

The Mandelbrot set is a set of complex numbers for which the function, does not diverge when iterated from z = 0 to z = infinity. 

mandelbrot_eq

where C is the complex number of our interest.

It is not possible to compute the equation up to infinity, thus, a definite value is used to limit the computation for analysis. This is directly linked to the plot as we will see later.

Complex number

A complex number is a number which when multiplied by itself (or squared) results in -1.

This is weird and unrealistic, as we know that the square of any number is always positive. For example,

2 * 2 = 4

(-5 )* (-5) = 25

Then, what is

(number) * (number) = -1

This is unimaginable and hence the number is termed as imaginary or i

i * i = -1

Thus, making

i = √-1

So a number would be considered complex if it contains an imaginary part.

5 + i, 9 – 4i, 2are all complex numbers.

So, by definition, if C = i then,

mandelbrot_eq_eg

and so on.

Now the question arises, what is the value, for which the function must remain bounded i.e. does not diverge? This value is known as Hausdorff dimension.

Hausdorff Dimension.

Hausdorff dimension is an integer that relates to the dimension corresponding to its topology (shape). It is the measure of a local size in space which is defined by the distance between its points in space.

Thus, the Hausdorff dimension for:

a point is 0

a line is 1

a square is 2, and

a cube is 3

As humans, we are limited to three-dimensional (3D) space, making 3, the maximum value of Hausdorff dimension.

Thus, for our application to obtain a Mandelbrot set, the Hausdorff dimension i.e. the boundary value for the function is 2. The logic behind this is the set when plotted on the Cartesian plane, would be a two-dimensional (2D) surface, similar to a square.

Thus,

mandelbrot_cond

The mathematics behind Mandelbrot set is quite interesting. However, understanding the same would require introducing a whole lot of other mathematical concepts, making the whole thing beyond the scope of this article. However, a good place to start would be from the article by Wolfram MathWorld.

Installation

In order to implement this project, Python 3.6.1 or greater is required. This project requires a lot of additional packages like SciPy and NumPy, other than those that come with the installer. I could just install these packages using pip utility, however, I already had Anaconda installed, making my life easier. I would recommend my viewer’s to do the same, but working with bare-bone python is cool as well.

Just issue following commands, in case you are missing the packages listed above.

SciPy

pip install scipy

NumPy

pip install numpy

Installing Anaconda

  • Download latest Anaconda distribution from their official site.
  • Run installer.
  • Follow installer instructions and install with recommended specifications.
  • And, you are ready to go.
  • Run Anaconda Prompt or search for the same and launch the application.

Note! It takes a while for the shell to boot and be ready for usage. This is because a lot of packages are loaded on start-up. Please wait patiently.

Code

While understanding maths and equations are fun, visualizing theory is what I love. So, I experimented and wrote a python script to plot the infamous Mandelbrot set. The code is available and can be downloaded from my Github repository.

The code uses numpy and pylab to generate Mandelbrot set, store the values as arrays and plot them as coordinates. One might think, how to implement complex numbers in Python, but therein lies the beauty of using this language. By default, Python supports usage of complex numbers using the readily available cmath library.

mandelbrot_set()

The function implements the Mandelbrot equation to generate a set of complex numbers stored in a numpy array.

Arguments

x_min – the lower limit of the real axis.

x_max – the upper limit of the real axis.

x_num – the number of samples to be plotted on the real axis.

y_min – the lower limit of the imaginary axis.

y_max – the upper limit of the imaginary axis.

y_num – the number of samples to be plotted on the imaginary axis.

max_iteration – maximum number of iterations i.e. a definite value to replace infinity.

Return value

The function returns the number of iterations as an array and the complex numbers that satisfy Manderbolt equation Z < 2 as an array.

Working

X = np.linspace(x_min, x_max, x_num, dtype = np.float32)
Y = np.linspace(y_min, y_max, y_num, dtype = np.float32)

The above snippet uses linspace method defined in numpy. It returns evenly spaced numbers over the specified interval.

So, x_num of equally spaced values would be returned between x_min and x_max. The data type of these values would be 32-bit floating point number, defined by dtype argument.

The same applies to Y.

C = X + Y[:, None] * 1j

This is the cmath syntax to represent a complex number.

complex_number = Real_num + Imaginary_num * 1j

Note! i and j are the same and are used interchangeably to represent a complex number.

N = np.zeros(C.shape, dtype = int)
Z = np.zeros(C.shape, np.complex64)

zeros is a numpy method that returns a zero-array of given shape and type i.e data type.

C.shape is the shape of the array i.e. complex

Here,

is an array filled with zeroes to hold the current iteration value.

is an array filled with zeroes to hold complex values that satisfy Mandelbrot equation.

I = np.less(abs(Z), 2)

less is a numpy method that takes in two arguments, checks if the first argument is greater or not and returns True or False based on the result.

Here, the absolute value of Z is compared with 2, to check if it is less than 2 or not.

Z[I] = Z[I] ** 2 + C[I]

This is the implementation of Mandelbrot equation.

main

The function initializes the values required to call mandelbrot_set() and passes them as arguments.

with np.errstate(invalid = ‘ignore’):
M = np.nan_to_num(N + 1 – np.log(np.log(abs(Z))) / np.log(2))

errstate is a numpy method that performs floating-point error handling. Based on the error generated, an error-handler is defined in the argument.

nan_to_num is a numpy method that replaces NaN (not-a-number) with 0, positive infinity with the largest possible positive number and negative infinity with the largest possible negative number (i.e smallest number).

imshow(M, cmap = plt.cm.prism, interpolation = ‘none’, extent = (x_min, x_max, y_min, y_max))

imshow is a pyplot method defined under matplotlib. It is a straightforward way to display images on the axes.

Plots

I generated plots with various patterns outlining the behavior of the sets with respect to the number of iterations used.

The Mandelbrot plot illustrates the region where the Mandelbrot equation is satisfied i.e. the square of the complex number is less than 2. The region where these complex numbers are concentrated is seen in solid black color, while the other regions illustrate the rate at which the values diverge from Hausdorff dimension.

The following set of images demonstrate how the complex numbers are clustered on the axes and the greater the number of iterations, more evenly the values are distributed when they diverge, this reduces color variation over the entire plot.

 

mandelbrot-2
max_iteration = 2
mandelbrot-5
max_iteration = 5
mandelbrot-10
max_iteration = 10

 

mandelbrot-20
max_iteration = 50
mandelbrot-50
max_iteration = 100
mandelbrot-100
max_iteration = 200

 

Following are some of the other color mappings I used to obtain beautiful plots.

 

mandelbrot-copper
cmap = copper

 

Figure_gist_earth
cmap = gist_earth

 

mandelbrot_nipy_spectral
cmap = nipy_spectral

 

mandelbrot-hsv
cmap = hsv

 

mandelbrot-prism
cmap = prism

For more color mappings, check out colormaps_reference.

 

Conclusion

Mandelbrot sets are just a small part of numerous such sets. Mandelbar sets and Julia sets are other such sets exploiting the properties of complex numbers. These sets along with many others are collective entities that belong to a major field of study called fractals. The best source to learn about fractals is from their official website. The real-world applications are many and the most prominent one being the gaming and graphics industry. Fractals play a major role here. These topics will be covered in another blog post.

 

 

 

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s