Generating Endless New Fractals with Genetics

All the fractals represented in the image above are actually generated by a iterative mathematical function, just like any normal fractal, and the functions that created them were all generated by a computer using its own mutatable language to represent the algorithmn responsible for the image.

(1) The data representing the fractal is compilied, optimized and the interpretered and run to generate an image on the right, then the original data is repeatedly mutated randomly and the process repeats.

The common example of a fractal is the mandelbrot, created using the iterative formula $z_{n+1}=z_n^2+c$

First a plane of pixels is generated in the complex plane and then this function is applied to each pixel until it either converges or diverges. If it converges it is coloured and is part of the mandelbrot fractal. A computer calculates this function as $(x_{n+1},y_{n+1})=(x_n^2-y_n^2+x_{0},2x_ny_n+y_{0})$

Although this is a simple operation it can result in a complex image, called the mandelbrot and can be coloured in various different ways.

The image can also look different if you change the rendering technique. In the Buddhabrot, every point of the mandelbrot set is iterated and every new point (pixel) it iterates to has colour added to it. This is repeated for all points in the set and then the image is normalized, this results in images like these:

Furthermore, the colouring scheme can also be changed (as it has in the one above) so that instead of a adding a constant after each iteration you add a rgb colour value that is determined from the iteration number. E.g the inital points could be blue and then the last 1000 iterations could start adding red to the image.

To generate lots of these unique fractals the program has to have a way to represent the procedures it uses to achieve the desired image. This language to express this also has to be mutatable, so any character can be changed and the procedure still makes sense and can be interpreted. This is achieved by using the following schematic.

The machine that runs the code has 15 memory slots each corrosponding to a letter of the alphabet,  reflected halfway and the last 3 variables are special (A=L=01  , B=M=02  ,  C=N=03 …W,X,Y are special). This variables are initialised in the first part of the code (DNA of the fractal). e.g.

```D#+9000170206
Q#+0000749873
R#+0821350000
T#+0796368908
X#-0101080300
A#+6013010522
I#+2847005050
I#+1203096481
I#-3770800750
J#+4910305379
X#+7430440500
S#+8233100291
O#+5755246089```

This called the init stage. The first line simply means, set D (04) to the number +900.0170206, (we divide the number by 10000000 instead of including a decimal point). If a variable is not initalised then it is set to 0.

After the init stage, some variables are manipulated, A (also L) are set to the scaled x position of the pixel, B (also M) are set to the scaled y position of the pixel, and C (also N) are set to zero. Then the special variables W,X,Y are created, they are locked and cannot be changed, and they are simply the starting position of the pixel, W= first scaled x position ,X= first scaled y position ,Y= 0

The second part of the DNA refers to the functions that should be applied to each pixel to iterate its position.

```Q[#E[#QW[#TLO]]Q]
H[#AQG]
I[#RAW]
A[#G[#TAA][#BOH]]
X[#P[#J[#LAQ]J]A]
A[#G[#XXA]W]
M[#GB[#SQK]]
Y[#L[#IXO]V]```

This describes how each variable should change, the syntax is first letter is the variable to change (e.g. Q also F), it should be changed to [#E _ _ ] where E is a function of _ and _. To allow complex programs _ can be a variable and also another function. E.g Y[#L[#IXO]V] means Y should be changed to the L function of [#IXO] and V, where [#IXO] is the I function of X and O. This allows complex behaviours and nesting of expressions to take place. Each letter repsonding to function is different, e.g. the function [#Axy] simply returns x, the function [#Gxy] returns  x+y, the function [#Exy] returns the floor of x, the function [#Kxy] returns the xy. A full list of functions i

s given below along with the recursion used to interpret the functions:

```public double getFunctionValue(String s) {
//Recursive alog to work out function values
// System.out.println("Function: "+s);
double value = 0;
if(s.startsWith("[")) //[#ABC]   #=fodder  A =id   BC = inputs
{
int id = ((int)s.charAt(2))-65;

int split = 0;
if(s.substring(3).startsWith("["))
{
int brackets = 1;
for(int i = 4 ; i < s.length();i++)
{
if(s.substring(i,i+1).equalsIgnoreCase("]"))
{
brackets--;
}else
if(s.substring(i,i+1).equalsIgnoreCase("["))
{
brackets++;
}

if( brackets == 0)
{
split =  i+1;
break;
}
}

}else
{
split = 4;
}

double x = getFunctionValue(s.substring(3, split));
double y = getFunctionValue(s.substring(split,s.length()-1));

switch (id){
case 0:  value = x;  //A
break;
case 1:  value = Math.pow(x,2d); //B
break;
case 2:  value = Math.floor(x); //C
break;
case 3:  value = Math.round(x); //D
break;
case 4:  value = Math.ceil(x); //E
break;
case 5:  value = x; //F
break;
case 6:  value = x+y; //G
break;
case 7:  value = x+y; //H
break;
case 8:  value = x-y; //I
break;
case 9:  value = x-y; //J
break;
case 10:  value = x*y; //K
break;
case 11:  value = x*y; //L
break;
case 12:  value = Math.pow(Math.abs(x),Math.abs(y)); //M
break;
case 13:  value = Math.pow(Math.abs(y),Math.abs(x)); //N
break;
case 14:  value = x/((y==0d)?0.000001d:y); //O
break;
case 15:  value = y/((x==0d)?0.000001d:x); //P
break;
case 16:  value = Math.pow(Math.abs(x),Math.abs(y)); //Q
break;
case 17:  value = Math.pow(Math.abs(y),Math.abs(x)); //R
break;
case 18:  value = Math.cos(x); //S
break;
case 19:  value = Math.sin(x); //T
break;
case 20:  value = rand.nextDouble(); //U
break;
case 21:  value = (rand.nextDouble()-0.5d)*x; //V
break;
case 22:  value = -x; //W
break;
case 23:  value = -Math.abs(x); //X
break;
case 24:  value = Math.abs(x); //Y
break;
}

return value;
}else
{
return getMemory(s.charAt(0));
}
}```

The last part of the DNA denotes how the fractal will be coloured. It is composed of 18 lines, split into 3 sections of 6 lines each for red, green and blue. Each 6 lines is further split into 3 sections of 2 lines, where each 2 lines corresponds to variables of a sigmoid curve (the steepness and the midpoint), and the entire graph is made up of 3 sigmoids for each colour.

For example the DNA code for the colours of the fractal (1) is:

```-950030
-035465
-053983
-901065
+006473
-790010
-451083
+495678
+105849
+206620
-160087
+040206
+503300
+622012
-865090
-675625
-702610
-220540```

and this corresponds to a graph of the rgb colours like this over each iteration:

This format for expressing fractals as DNA allows any letter or number in the DNA to be changed and the fractal will aslo change. For example if we start with this fractal

Q[#E[#QW[#TLO]]Q]

We can make small changes to a single function which leads to a similiar style, but still different, fractal.

Here are just some of the examples that the program ws able to produce given only a couple hours to generate fractals: