Cantor’s middle-thirds set and its dimension#

Starts from \([0, 1]\) and repeatedly removes the open middle third of every remaining interval. After \(n\) steps there are \(2^n\) intervals of total length \((2/3)^n \to 0\), yet the limit set is uncountable. Box counting recovers its fractional dimension \(\log 2/\log 3 \approx 0.631\).

import matplotlib.pyplot as plt
import numpy as np

from mathematicskit.fractals_chaos import box_counting_dimension, chaos_game
from mathematicskit.fractals_chaos.visualizers.plots import plot_box_counting


def cantor_intervals(n):
    """Left endpoints and common length of the 2**n stage-n intervals."""
    lefts = np.array([0.0])
    for k in range(1, n + 1):
        lefts = np.concatenate([lefts, lefts + 2.0 / 3**k])
    return np.sort(lefts), 3.0**-n

Removing middle thirds#

fig, ax = plt.subplots(figsize=(8, 3.5))
for n in range(7):
    lefts, width = cantor_intervals(n)
    ax.broken_barh([(x, width) for x in lefts], (-n - 0.3, 0.6), color="black")
    print(f"stage {n}: {len(lefts):3d} intervals, total length {len(lefts) * width:.4f}")
ax.set_yticks(-np.arange(7), [f"n = {n}" for n in range(7)])
ax.set_xlim(0, 1)
ax.set_title("Cantor set construction")
Cantor set construction
stage 0:   1 intervals, total length 1.0000
stage 1:   2 intervals, total length 0.6667
stage 2:   4 intervals, total length 0.4444
stage 3:   8 intervals, total length 0.2963
stage 4:  16 intervals, total length 0.1975
stage 5:  32 intervals, total length 0.1317
stage 6:  64 intervals, total length 0.0878

Text(0.5, 1.0, 'Cantor set construction')

Box-counting dimension#

The two maps \(x \mapsto x/3\) and \(x \mapsto x/3 + 2/3\) send the Cantor set onto its two halves, so the chaos game samples it. Boxes of size \(3^{-k}\) meet \(2^k\) pieces of the set, so the slope of \(\log N\) against \(\log(1/\text{size})\) tends to \(\log 2/\log 3\).

third = np.diag([1 / 3, 1 / 3])
points = chaos_game([(third, np.array([0.0, 0.0]), 0.5), (third, np.array([2 / 3, 0.0]), 0.5)], 100000, seed=0)
result = box_counting_dimension(points)
print(f"estimated dimension: {result.dimension:.4f}")
print(f"exact value log(2)/log(3): {np.log(2.0) / np.log(3.0):.4f}")
plot_box_counting(result)
Box-counting dimension
estimated dimension: 0.6438
exact value log(2)/log(3): 0.6309

<Axes: title={'center': 'Box-counting dimension'}, xlabel='1 / box size', ylabel='box count'>

Total running time of the script: (0 minutes 0.498 seconds)

Gallery generated by Sphinx-Gallery