The personal weblog of Martin Donath, professional web developer, technology ninja and design enthusiast based in Cologne, Germany.

Strange Attractors

The beauty of strange attractors has been fascinating me for a long time. Beside their visual appeal it is stunning that they are the result of really simple mathematical equations producing practically unpredictable numbers over a long period of time.

In this article I introduce and discuss a very simple and compact Processing.js script which is based on a two-dimensional quadratic map and a fractal pattern – a sequence of 12 letters – delivering the coefficients for the quadratic map.

Actually, I am not a physicist – I just like strange attractors from an aesthetic point of view. Okay, I am a bit of a math addict, too. However, it’s not as complicated as it may sound in the first place.

Fundamentals

Attractors

Now, what is a strange attractor? A strange attractor is an attractor with fractal dimensionality existing in a phase space. Not yet? Then backwards:

A phase space holds all possible states of a system, meaning for each possible state of a system there is exactly one point (one solution) within this phase space. The number of dimensions of a phase space is equal to the degrees of freedom of the corresponding system. Within this phase space an attractor is a subset of points towards which the system evolves over time. If a given point within the phase space gets close to the attractor, it stays on a trajectory around (or towards) this attractor. An attractor can be a point, line, manifold or a complex set with fractal structures, that is a strange attractor. Strange attractors are a special form of attractors, as they have fractal – meaning non-integer – dimensionality, which is why they behave chaotic.

An example of a simple point attractor is the drainage of a bathtub. If the tub contains water, the water particles are attracted by the drainage. Because of the coriolis effect, they will move on a trajectory around the drainage before finally being sucked in.

There are different kinds of strange attractors, but of particular interest for us are those based on two-dimensional quadratic maps, as they are easy to compute.

Quadratic Maps

A two-dimensional quadratic map is the simplest example of a non-linear equation. The position of an arbitrary point [x,y] within a given phase space can be calculated with the following two recursive equations in an iterative manner:

1
2
3
4
nx = a[0]         + a[1]  * x + a[2]  * x * x
   + a[3] * x * y + a[4]  * y + a[5]  * y * y;
ny = a[6]         + a[7]  * x + a[8]  * x * x
   + a[9] * x * y + a[10] * y + a[11] * y * y;

The next position [nx,ny] of a point [x,y] depends on the current position as well as 12 coefficients a[0]a[11] defining the unique character of a strange attractor.

The coefficients are derived from a 12-letter sequence, which also gives a strange attractor its name. This sequence is called a fractal pattern and can contain the letters ‘A’ to ‘Y’ (in uppercase). Using this letters, a coefficient can have 25 possible values ranging from –1.2 to +1.2 with an increment of 0.1, so ‘A’ translates to –1.2, ‘B’ to –1.1 etc. Some potential strange attractors are:

1
'QGGVSLMHHGCR', 'GIIETPIQRRUL', 'GLXOESFTTPSV', 'MDVAIDOYHYEA'

Combinatorically speaking there are 2512 strange attractors, of which 1.6% are chaotic (= they have visual appeal), leaving a number as small as 1015 (1 quadrillion or 1.000 trillions!). Hell yeah!

To get the coefficients from this 12-letter sequence, each character is converted to its ASCII value (A: 65, Y: 89), subtracted by 65, to normalize the value between 0 and 24, and by 12, to center the value around 0, leaving the values within a range of –12 to +12. Finally, dividing by 10 normalizes to the desired range of –1.2 to +1.2. In Javascript:

1
2
3
for (i = 0; i < f.length; i++) {
    a[i] = (f.charCodeAt(i) - 65 - 12) / 10;
}

This is everything we need. Now we will wrap this up in a nice script.

The Script

I am a big fan of Javascript and Processing, so we’ll use the Javascript port of Processing called Processing.js. I love Processing for it’s sketch-oriented approach, enabling very rapid prototyping of ideas. As you may have noticed, there is a Processing.js instance attached to a canvas at the top of the page, generating images while you’re reading this article.

Get the latest version of Processing.js, which is 1.2.3 at the date of writing, include it in your page and run the following script (explanations below):

Strange Attractor Generation (strange-attractor.js) download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
new Processing(document.getElementById('...'), function(p) {

  // Fractal pattern and coefficients.
  var f = 'QGGVSLMHHGCR';
  var a = [];

  // Parameters.
  var x = 0.1, y = 0.1;
  var r = p.random(360);

  // Initialize canvas.
  p.setup = function() {
    p.size(800, 400);

      // Set colors.
      p.background(0, 0);
      p.noFill();
      p.stroke(255, 0, 102, 50);

      // Initialize coefficients.
      for (i = 0; i < f.length; i++) {
          a[i] = (f.charCodeAt(i) - 65 - 12) / 10;
      }
  };

  // Center and rotate canvas and draw points.
  p.draw = function() {
      p.translate(p.width / 2, p.height / 2);
      p.rotate(p.radians(r));

      // Make 25 iterations each drawing cycle.
      for (i = 0; i < 25; i++) {
          p.point(x * 200, y * 200);

          var nx = a[0]         + a[1]  * x + a[2]  * x * x
                 + a[3] * x * y + a[4]  * y + a[5]  * y * y;
          var ny = a[6]         + a[7]  * x + a[8]  * x * x
                 + a[9] * x * y + a[10] * y + a[11] * y * y;

          x = nx; y = ny;
      }
  };
});

Personally I prefer the pure Javascript syntax of Processing.js, as you’re not bound to the methods of the Processing language. Furthermore, there seem to be some problems and incompatibilities when combined with Javascript frameworks such as MooTools or jQuery.

Now, what does the script above do? It’s quite simple:

  1. The DOM must contain a canvas instance which is given to the Processing.js constructor beside the actual sketch to be executed. Within the sketch function the variables needed are defined and initialized.
  2. The setup() method is executed once and sets the size of the canvas, the background color (in this case transparent), the fill color (none) and the stroke color (semi-transparent magenta). Next the coefficients are computed from the fractal pattern given by the member f in the way already described above.
  3. The draw() method is executed repeatedly. First, the origin ist translated to the center of the canvas and rotated by a random value r (generated during setup) just for some variation. Then the point is drawn at the current position and the quadratic map function is solved to get the next point. This is done 25 times within each drawing cycle, so 25 points are added every cycle.

The starting point shouldn’t be [0,0], because a[0] and a[6] may be 0. Therefore we chose [0.1,0.1]. That’s it. Here are some of the resulting strange attractors:

LFMTGMBOOJLX QFFVSLMIIGCR SOJSCEMKBBBE VFPPDBCPMSXU VLEJLCRUFQTJ XMDLHBOPUBET

These are strange attractors I found myself during some experimentation. Hover over an image to see its fractal pattern (the image title).

Where to go from here

As denoted in the paper ’Automatic Generation of Strange Attractors’ by J.C. Sprott, one could actively search for chaotic solutions of strange attractors (as already mentioned, 1.6% of all possible solutions) by checking the sensitivity to its initial conditions. This is done by evaluating the Lyapunov exponent for each of the two equations of the quadratic map. However, as this would go beyond the intended scope of this article, I refer to the already mentioned paper.

Conclusion

Strange attractors are fun to play with and majestic in their appearance. If you start messing around with the script, you will soon realize the power of simple mathematics. In case you find other beautiful fractal patterns, tell me!

Comments