📚 Math in Society
⇩ Download ▾

15.5 Complex Recursive Sequences

We will now explore recursively defined sequences of complex numbers.

The previous example generated a basic linear sequence of real numbers. The same process can be used with complex numbers.

Mandelbrot Set

The Mandelbrot Set is a set of numbers defined based on recursive sequences

# Is c in the Mandelbrot set?  Start at z = 0 and apply z -> z*z + c over and over.
# If the point ever gets more than 2 units from the origin it escapes and c is OUT.
C_VALUES = [1 + 1j, 0.5j, 0.4 + 0.3j, -1 + 0j, 0.3 + 0.5j, -0.75 + 0.1j]   # EDIT
MAX_STEPS = 12       # EDIT

def show(c):
    a, b = round(c.real, 5), round(c.imag, 5)
    sign = "+" if b >= 0 else "-"
    return f"{a:g} {sign} {abs(b):g}i"

for c in C_VALUES:
    print(f"c = {show(c)}")
    z = 0j
    escaped_at = None
    for k in range(1, MAX_STEPS + 1):
        z = z * z + c
        far = abs(z)
        print(f"   z{k} = z{k - 1}^2 + c = {show(z):>26}   distance from 0 = {far:.4f}"
              + ("   ESCAPED" if far > 2 and escaped_at is None else ""))
        if far > 2:
            escaped_at = k
            break
    if escaped_at:
        print(f"   -> ran away after {escaped_at} step(s): c is NOT in the Mandelbrot set\n")
    else:
        print(f"   -> still within 2 units after {MAX_STEPS} steps: c looks like it IS "
              f"in the set (not a proof)\n")

print("the whole test, in three lines of Python:")
print("   z = 0")
print("   for _ in range(50): z = z*z + c")
print("   inside = abs(z) <= 2")
# Try it: 0.25 + 0j is just inside; 0.26 + 0j escapes. Try both.

The Mandelbrot set filled solid black on the complex plane, with the real axis ticked from -2 to 1 and the imaginary axis from -1 to 1. A large cardioid sits astride the origin, a round bulb is attached to its left around -1, smaller bulbs stud the boundary above, below and to the left, and the whole edge is fringed with fine detail that repeats at smaller scales.If all complex numbers are tested, and we plot each number that is in the Mandelbrot set on the complex plane, we obtain the shape to the right[1].

The boundary of this shape exhibits quasi-self-similarity, in that portions look very similar to the whole.

In addition to coloring the Mandelbrot set itself black, it is common to the color the points in the complex plane surrounding the set. To create a meaningful coloring, often people count the number of iterations of the recursive sequence that are required for a point to get further than 2 units away from the origin. For example, using c=1+i above, the sequence was distance 2 from the origin after only two recursions.

import numpy as np
import matplotlib.pyplot as plt

# EDIT the window to zoom. Interesting spots to try:
#   the whole set:  -2.2, 0.8, -1.2, 1.2      MAXIT 60
#   seahorse valley: -0.80, -0.70, 0.10, 0.20  MAXIT 200
#   the tail:       -1.80, -1.72, -0.04, 0.04  MAXIT 200
XMIN, XMAX, YMIN, YMAX = -2.2, 0.8, -1.2, 1.2
MAXIT = 60
PIXELS = 420

x = np.linspace(XMIN, XMAX, PIXELS)
y = np.linspace(YMIN, YMAX, PIXELS)
C = x[None, :] + 1j * y[:, None]
Z = np.zeros_like(C)
escape = np.zeros(C.shape, dtype=int)
alive = np.ones(C.shape, dtype=bool)

for k in range(1, MAXIT + 1):
    Z[alive] = Z[alive] ** 2 + C[alive]
    gone = alive & (np.abs(Z) > 2)
    escape[gone] = k          # how many steps it took to get 2 units from the origin
    alive &= ~gone

inside = alive.sum()
print(f"window: real {XMIN} to {XMAX}, imaginary {YMIN} to {YMAX}, {MAXIT} steps allowed")
print(f"of {escape.size:,} sampled points, {inside:,} never escaped "
      f"({inside / escape.size:.1%}) - those are drawn black")
print(f"{'escaped after':>16}{'points':>12}")
for lo, hi in ((1, 2), (3, 5), (6, 10), (11, 25), (26, MAXIT)):
    if lo <= MAXIT:
        n = int(((escape >= lo) & (escape <= hi)).sum())
        print(f"{f'{lo}-{hi} steps':>16}{n:>12,}")
print("fast escapers get one shade, slow escapers another - that is the colouring")

# log scale on the escape count so the slow escapers near the edge stand out;
# points still inside get 0, the darkest end of the colour map.
shown = np.where(alive, 0.0, np.log1p(escape))
fig, ax = plt.subplots(figsize=(6.6, 5.6))
ax.imshow(shown, extent=(XMIN, XMAX, YMIN, YMAX), origin="lower", cmap="magma")
ax.set_xlabel("real axis"); ax.set_ylabel("imaginary axis")
ax.set_title("the Mandelbrot set, coloured by escape speed")
plt.show()

For some other numbers, it may take tens or hundreds of iterations for the sequence to get far from the origin. Numbers that get big fast are colored one shade, while colors that are slow to grow are colored another shade. For example, in the image below[2], light blue is used for numbers that get large quickly, while darker shades are used for numbers that grow more slowly. Greens, reds, and purples can be seen when we zoom in – those are used for numbers that grow very slowly.

Three panels zooming into the Mandelbrot set, each magnifying the small white box drawn on the panel before it. The first shows the whole set in black, the main cardioid with its round bulb to the left, on a pale blue ground. The second zooms to the studded boundary above the bulb. The third fills the frame with branching filaments. Points in the set are black; the surrounding colours record how many iterations the sequence needs to get more than 2 units from the origin, light blue for numbers that grow large quickly and greens, pinks and purples for numbers that grow very slowly.

The Mandelbrot set, for having such a simple definition, exhibits immense complexity. Zooming in on other portions of the set yields fascinating swirling shapes.

Two deeper zooms into the boundary of the Mandelbrot set, each a spiral of studded filaments winding into a central eye: the first drawn in green, pink and cyan against pale yellow, the second against black and deep blue.

[1] en.Wikipedia.org/wiki/File:Mandelset_hires.png

[2] This series was generated using Scott’s Mandelbrot Set Explorer

Adapted from Math in Society by David Lippman, hosted on LibreTexts (math.libretexts.org) and licensed under CC BY-SA 3.0. Changes were made. License: CC-BY-SA-3.0.

These eBooks are a prerelease and are not yet certified conformant with WCAG 2.1 AA or ADA Title II. Every page is built against an automated accessibility gate, and the published editions will meet ADA Title II requirements when they release in late September 2026. If something is unusable, please tell us.