The Clifford attractor, also known as the fractal dream attractor, is the system of equations:
where a, b, c, and d are constants of choice. It is an attractor because at given values of a, b, c, and d,
any starting point
with
with
A wide array of shapes may be made by changing the constants, and the code to do this is here Try experimenting with different constants!
In what way is this a fractal? Let's zoom in on the lower right side: In the central part that looks like Saturn's rings, there appear to be 6 lines.
At a smaller scale, however, there are more visible, around 10
And at a smaller scale, still more,
Fractals are objects that appear similar at different scale, or more precisely objects that have a scaling dimension greater than their topological dimension. In this case, we can idealize the topological dimension to be
For
For
For
And for
From
The flashes are not a result of video artefacts, but instead represent small changes that lead to the attractor shifting back to points. Observe that the transition between a 0 and >1 dimensional attractor is not completely smooth! Small changes to
This is not peculiar to the Clifford attractor: any one-to-one mapping from
And when
Say you want to model an ordinary differential equation:
such that the change in the variable
ie the position of x at time 0 is some constant equal to
If the equation is nonlinear, chances are that there is no analytic solution. What is one to do? Do an approximation! Perhaps the simplest way of doing this is by using discrete approximations to estimate where a point will go given its current position and its derivative. This is known as Euler's method, and can be expressed as follows:
where
With smaller and smaller values of
For a two dimensional equation, the approximations can be made in each dimension:
To make these calculations and plot the results in python, the wonderful numpy and matplotlib libraries are used and we define the Clifford attractor function with constants
# import third party libraries
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('dark_background')
def clifford_attractor(x, y, a=-1.4, b=1.7, c=1.0, d=0.7):
'''Returns the change in arguments x and y according to
the Clifford map equation. Kwargs a, b, c, and d are specified
as constants.
'''
x_next = np.sin(a*y) + c*np.cos(a*x)
y_next = np.sin(b*x) + d*np.cos(b*y)
return x_next, y_next
Setting up the number of iterations and the time step size, we then initialize the numpy array with 0s and add a starting
# number of iterations
iterations = 1000000
delta_t = 0.01
# initialization
X = np.zeros(iterations)
Y = np.zeros(iterations)
# starting point
(X[0], Y[0]) = (10.75, 8.2)
For computing (2), let's loop over the clifford function, adding in each next computed value to the numpy array.
# euler's method for tracking differential equations
for i in range(iterations-1):
x_next, y_next = clifford_attractor(X[i], Y[i])
X[i+1] = X[i] + x_next * delta_t
Y[i+1] = Y[i] + y_next * delta_t
For continuous differential systems, one can follow a path along a vector grid in order to get an intuitive understanding of how the differential system influences a point's path. To get a vector grid started, we define a grid using numpy with minimum, maximum, and intervals in the
# Vector plot initialization
x = np.arange(10.7, 11.2, 1/110)
y = np.arange(7.6, 8.4, 1/30)
X2, Y2 = np.meshgrid(x, y)
The next step is to calculate the size and direction of each vector at the designated grid points according to the clifford map, and assign each value a color.
# calculate each vector's size and direction
a = -1.4
b = 1.7
c = 1.0
d = 0.7
dx = np.sin(a*Y2) + c*np.cos(a*X2)
dy = np.sin(b*X2) + d*np.cos(b*Y2)
color_array = (np.abs(dx) + np.abs(dy))**0.7
Now let's plot the graph, adding both vector plot and differential iterations to the same plot.
# make and display figure
plt.figure(figsize=(10, 10))
# differential trajectory
plt.plot(X, Y, ',', color='white', alpha = 0.2, markersize = 0.05)
# vector plot
plt.quiver(X2, Y2, dx, dy, color_array, scale = 20, width=0.0018)
plt.axis('on')
plt.show()
For a starting point situated at $ (x_0, y_0) = (10.75, 8.2)$, at
at
with more iterations at
From
For
Discrete differential systems are recurrence relations: a point's next position is entirely determined by its current position according to the equation system given. In contrast, both a point's next position in a continuous system is almost entirely determined by its current position: the equation system merely determines the direction and rate of change.
One can think of Euler maps with large
Thus as is the case for continuous systems (and unlike that for discrete systems), one can trace a point's path using a vector plot on a semicontinuous map. On the other hand, semi-continuous but not continuous maps of dissipative nonlinear equations may be fractals in two dimensions, as is the case for discrete maps (see here for an explanation).
To generate a different Clifford attractor as defined in a discrete map, a change in the values of at least one of
For example, take the semicontinuous map with the same constants as before,
and at
and as
The regions that attract all points into a certain attractor are called the basins of attraction (see the henon map page for more information). For example, the attractor (shown above) of the starting point
For
For an investigation into which point ends up where, see this page.