Lesson 4: Loops that remember
Build the chaos game in Python, and learn on the way:
- a loop that carries its state from step to step
- random whole numbers with rng.integers
- a while loop for a condition
- arrays of points and slicing
- np.column_stack
Watch it first
Plays from YouTube after a click.
The script
Open in Colab: this lesson as a notebook"""Chaos game: jump a part r of the way to a random corner of a polygon, again and again.
Run: python chaos-game.py (needs: pip install numpy matplotlib)
"""
import numpy as np
import matplotlib.pyplot as plt
plt.style.use("dark_background")
corners, r, no_repeat = 3, 0.5, False # triangle, halfway: the Sierpinski triangle
steps = 60000
rng = np.random.default_rng()
angles = np.pi / 2 + 2 * np.pi * np.arange(corners) / corners
vertex = np.column_stack([np.cos(angles), np.sin(angles)])
points, chosen = np.zeros((steps, 2)), np.zeros(steps, dtype=int)
x, last = np.array([0.0, 0.0]), -1
for i in range(steps):
c = rng.integers(corners)
while no_repeat and c == last: # the restricted game: never the same corner twice
c = rng.integers(corners)
x = x + r * (vertex[c] - x) # the whole rule
points[i], chosen[i], last = x, c, c
plt.figure(figsize=(6, 6))
plt.scatter(points[20:, 0], points[20:, 1], s=0.3, c=chosen[20:], cmap="rainbow")
plt.axis("equal")
plt.axis("off")
plt.show()
# Try: corners, r = 5, 0.618 (a pentagon) or corners, no_repeat = 4, True (a square, restricted)
No Python on this computer? The notebook runs the same script, the exercises and the answers in your browser, on Google Colab.
Line by line
vertex = np.column_stack([np.cos(angles), np.sin(angles)])The corners of the polygon: their x and y values side by side, one row per corner.
c = rng.integers(corners)A random whole number from 0 to corners − 1: the corner to jump towards.
while no_repeat and c == last:The restricted game: as long as the new corner is the last one, draw again.
x = x + r * (vertex[c] - x)The rule: move the part r of the way from the point to the corner. With r = 0.5, halfway.
points[i], chosen[i], last = x, c, cKeep the point and its corner, and remember the corner for the next step.
plt.scatter(points[20:, 0], points[20:, 1], s=0.3, c=chosen[20:], cmap="rainbow")Skip the first 20 points, which are still on their way to the fractal, and colour the rest by their corner.
Try it yourself
Draw a pentagon whose five copies just touch.
Hint
Change corners and r on one line.
Answer
corners, r, no_repeat = 5, 0.618, False
Why does the plot skip the first 20 points?
Hint
Where does the point start?
Answer
It starts at the centre, which is not on the fractal. Each jump halves its distance to the fractal, so after 20 jumps it is less than a millionth (2⁻²⁰) of the picture away.
Play the square game with and without no_repeat. What changes?
Hint
corners = 4, r = 0.5.
Answer
Without the restriction the points simply fill the square; with no_repeat = True a fractal appears.
Quiz
Flashcards
Read the front, say the back to yourself, then open the card.
rng.integers(n)
A random whole number from 0 to n − 1.
while condition:
Repeats its block as long as the condition is True.
a[20:, 0]
Rows 20 to the end, column 0, of a 2-D array.
Contraction
A step that brings any two points closer together, like a jump halfway to a corner.
Attractor
The shape that repeated steps pull every point onto: here, the Sierpiński triangle.