## Strange Attractors

Lately I’ve experimented with finding strange attractors — A complex mathematical creature generated by a simple repetitive rule. To generate these images, an “x, y” point is first chosen at random and the corresponding pixel is colored white (in a simplified case). Two functions then decide the next “x, y” point:

Which just means that each new x position is determined by some formula incorporating the current x and/or y position, and each new y position is determined by some *other *formula incorporating the current x and/or y position. Depending on the formulae used, after many thousands of repetitions this may or may not generate an image of a strange attractor.

So it seems that the trick to finding these strange attractors is to simply try out many formulae hoping to generate some interesting patterns. So what formula should I use? According to ThinkQuest, the most common attractor is the *quadratic attractor*. The formulae used for a quadratic attractor take the general form:

To generate infinite equations of that form I need only tweak the coefficients *a*, *b*, *c*, *d*, *e* and *f*. I can leave out any of the terms (ie. the coefficient can be 0,) or I can leave in a term with no coefficient (ie. a coefficient of 1 is allowed.) For example if I decide on the coefficients *1.4*, *0*, *1*, *2*, *1 *and *-1.2* then the equation will look like:

I put together a Python class to generate these equations:

class Formula(object): def __init__(self): # generate the random coefficients self.coefficients = [random.choice([random.random()*4-2, 0, 1])for x in range(6)] def __call__(self, x, y): a, b, c, d, e, f = tuple(self.coefficients) return a*(x**2) + b*x*y + c*(y**2) + d*x + e*y + f

This class generates Formula objects which can be called as if they were functions. An example usage would be:

f = Formula() g = Formula() newx = f(oldx, oldy) newy = g(oldx, oldy)

This first attempt is naïve in places but it succeeded in generating the first real results:

Not bad for a first attempt I think. Full Python source follows:

import Image import random from math import floor SIZE = 200 # image size img_index = 0 class Formula(object): def __init__(self): self.coefficients = [random.choice([random.random()*4-2, 0, 1])for x in range(6)] #print self.coefficients def __call__(self, x, y): a, b, c, d, e, f = tuple(self.coefficients) return a*(x**2) + b*x*y + c*(y**2) + d*x + e*y + f while True: random.seed() seed = int(random.random() * 1000000000) random.seed(seed) f = Formula() g = Formula() x, y = random.random(), random.random() img = Image.new("RGB", (SIZE, SIZE)) for i in range(100000): #print x, y plotx = int(floor(x*SIZE/2))+SIZE/2 ploty = int(floor(y*SIZE/2))+SIZE/2 #print plotx, ploty try: img.putpixel((plotx, ploty), (255, 255, 255)) except IndexError: break x, y = f(x, y), g(x, y) if not x or not y: break # break out of pattern that has diminished to zero if x > 1 or x < -1 or y > 1 or y < -1: break # break out if growing too big else: img.save("a_%06d_%d.jpg" % (img_index, seed), "JPEG") img_index += 1

Does it work in 3D?

As far as I know it will work if you add a z component ie:

x = f(x, y, z)

y = g(x, y, z)

z = h(x, y, z)

That’s on my to do list!

There are also plenty of different equations types that produce different results, so plenty of scope to experiment while my attention span holds out.

I’ve greatly improved and optimised my current 2d code, and coded some image manipulation stuff. I’ll be posting that soon.